Zulip Chat Archive
Stream: lean4
Topic: TC performance issue when hitting maxSize
Tomas Skrivan (Oct 31 2023 at 16:25):
I have been dealing with curious TC performance issue. In a moderately sized computation I had to synthesize Add (K × K × K × K × K × K × K × K × K × K × K)
. Interestingly, synthesizing this class for 10 K
s takes ~4ms but for 11K
s it takes ~450ms. The issue is that for 11K
s the type class synthesis hits the maximum size, kills the good inference path, goes crazy and after half a second it finds an instance in some mysterious way. The issue is easily solvable just by increasing synthInstance.maxSize
My issue is that there is no warning or error letting you know that this is happening. Actually, what is the purpose of the synthInstance.maxSize
. Why there is no error like when hitting synthInstance.maxHeartbeats
? Would it make sense to throw an error or a warning?
mwe
import Mathlib.Data.IsROrC.Basic
variable {K : Type} [IsROrC K]
set_option profiler true
set_option profiler.threshold 1
-- fast
-- 10 K
example : Add (K × K × K × K × K × K × K × K × K × K) := by infer_instance
-- slow
-- 11 K
example : Add (K × K × K × K × K × K × K × K × K × K × K) := by infer_instance
-- fast
-- 11 K
set_option synthInstance.maxSize 200 in
example : Add (K × K × K × K × K × K × K × K × K × K × K) := by infer_instance
Eric Wieser (Nov 01 2023 at 23:40):
What's the instance in each case? (You can check with #synth
)
Kyle Miller (Nov 01 2023 at 23:43):
import Mathlib.Data.IsROrC.Basic
variable {K : Type} [IsROrC K]
set_option profiler true
set_option profiler.threshold 1
-- fast
-- 10 K
#synth Add (K × K × K × K × K × K × K × K × K × K)
-- Prod.instAdd
-- slow
-- 11 K
#synth Add (K × K × K × K × K × K × K × K × K × K × K)
-- Distrib.toAdd
-- fast
-- 11 K
set_option synthInstance.maxSize 200 in
#synth Add (K × K × K × K × K × K × K × K × K × K × K)
-- Prod.instAdd
Kyle Miller (Nov 01 2023 at 23:49):
I just wanted to experiment to see if there was an alternative to raising synthInstance.maxSize
, and adding these instances does work:
namespace Prod
@[to_additive]
instance instMul_2 {M₁ M₂ N : Type*} [Mul M₁] [Mul M₂] [Mul N] : Mul (M₁ × M₂ × N) :=
inferInstance
@[to_additive]
instance instMul_4 {M₁ M₂ M₃ M₄ N : Type*} [Mul M₁] [Mul M₂] [Mul M₃] [Mul M₄] [Mul N] :
Mul (M₁ × M₂ × M₃ × M₄ × N) :=
inferInstance
end Prod
You don't need both, but the second does have a measurable impact on synthesis time.
Tomas Skrivan (Nov 02 2023 at 13:37):
For 12 K
s it is slow again
Tomas Skrivan (Nov 02 2023 at 13:45):
I have built a custom version of lean which throws an error when maximum size is reached i.e. throwing on this line. The whole mathlib recompiles without a problem only in two files Mathlib/Lean/CoreM.lean
and Std/CodeAction/Attr.lean
the option maxSize
has to be increased. Each time it is trying to synthesize instance of typeNonempty (A → ... → Y → Z)
.
I'm thinking about adding boolean option synthInstance.strictMaxSize
. When set to true TC synthesis will throw when it reaches the maximum size. Would it make sense to make a PR?
Last updated: Dec 20 2023 at 11:08 UTC