Zulip Chat Archive
Stream: lean4
Topic: Compiler stuck computing something...
Sofia Snow (Sep 16 2022 at 16:05):
Hello. I tried adding the Linear
definition below, noted the LSP stopped responding and all cores pegged at 100%. The compiler doesn't seem to like the inductive constructors of the Linear
proposition, nor does it like it as a type.
inductive Cover : (x y z : List α) -> Type u
| done : Cover [] [] []
| left : Cover x y z -> Cover (t :: x) y (t :: z)
| right : Cover x y z -> Cover x (t :: y) (t :: z)
| both : Cover x y z -> Cover (t :: x) (t :: y) (t :: z)
inductive Linear : Cover x y z -> Prop
| done : Linear .done
| left : Linear c -> Linear (.left c)
| right : Linear c -> Linear (.right c)
Sofia Snow (Sep 16 2022 at 16:07):
Noticed on an older nightly, so I updated, running nightly-2022-09-15 now.
Leonardo de Moura (Sep 16 2022 at 22:24):
I can reproduce this issue. Created an issue for it https://github.com/leanprover/lean4/issues/1616
Arthur Paulino (Dec 07 2022 at 11:52):
Hi! I'm also facing an issue in which the compiler is getting stuck. Here's the #mwe:
import Std.Data.RBMap
abbrev MultilinearPolynomial α := Std.RBMap Nat α compare
namespace MultilinearPolynomial
/-- Instantiates a MPL from the list of raw `(b, c)` pairs -/
def ofPairs (pairs : List $ Nat × α) : MultilinearPolynomial α :=
.ofList pairs _
end MultilinearPolynomial
abbrev Zmod (_ : Nat) : Type := Int
instance [Ord α] [Ord β] : Ord (α × β) where compare
| (a₁, b₁), (a₂, b₂) =>
let a := compare a₁ a₂
if a == .eq then compare b₁ b₂ else a
def multilinearLagrangePolynomialCache :
Std.RBMap (Nat × Nat) (MultilinearPolynomial $ Zmod n) compare := .ofList [
((2, 3), .ofPairs [(0, 0), (1, 0), (2, 1), (3, -1), (4, 0), (5, 0), (6, -1), (7, 1)]),
((5, 3), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 1), (6, 0), (7, -1)]),
((2, 1), .ofPairs [(0, 1), (1, -1)]),
((3, 2), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 1)]),
((1, 3), .ofPairs [(0, 0), (1, 1), (2, 0), (3, -1), (4, 0), (5, -1), (6, 0), (7, 1)]),
((4, 1), .ofPairs [(0, 1), (1, -1)]),
((5, 4), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 1), (6, 0), (7, -1), (8, 0), (9, 0), (10, 0), (11, 0), (12, 0), (13, -1), (14, 0), (15, 1)]),
((0, 2), .ofPairs [(0, 1), (1, -1), (2, -1), (3, 1)]),
((0, 1), .ofPairs [(0, 1), (1, -1)]),
((1, 2), .ofPairs [(0, 0), (1, 1), (2, 0), (3, -1)]),
((2, 2), .ofPairs [(0, 0), (1, 0), (2, 1), (3, -1)]),
((3, 3), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 1), (4, 0), (5, 0), (6, 0), (7, -1)]),
((4, 2), .ofPairs [(0, 1), (1, -1), (2, -1), (3, 1)]),
((2, 0), .ofPairs [(0, 1)]),
((2, 5), .ofPairs [(0, 0), (1, 0), (2, 1), (3, -1), (4, 0), (5, 0), (6, -1), (7, 1), (8, 0), (9, 0), (10, -1), (11, 1), (12, 0), (13, 0), (14, 1), (15, -1), (16, 0), (17, 0), (18, -1), (19, 1), (20, 0), (21, 0), (22, 1), (23, -1), (24, 0), (25, 0), (26, 1), (27, -1), (28, 0), (29, 0), (30, -1), (31, 1)]),
((3, 1), .ofPairs [(0, 0), (1, 1)]),
((5, 2), .ofPairs [(0, 0), (1, 1), (2, 0), (3, -1)]),
((5, 1), .ofPairs [(0, 0), (1, 1)]),
((4, 3), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 0), (4, 1), (5, -1), (6, -1), (7, 1)]),
((1, 0), .ofPairs [(0, 1)]),
((5, 5), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 1), (6, 0), (7, -1), (8, 0), (9, 0), (10, 0), (11, 0), (12, 0), (13, -1), (14, 0), (15, 1), (16, 0), (17, 0), (18, 0), (19, 0), (20, 0), (21, -1), (22, 0), (23, 1), (24, 0), (25, 0), (26, 0), (27, 0), (28, 0), (29, 1), (30, 0), (31, -1)]),
((0, 0), .ofPairs [(0, 1)]),
((3, 5), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 1), (4, 0), (5, 0), (6, 0), (7, -1), (8, 0), (9, 0), (10, 0), (11, -1), (12, 0), (13, 0), (14, 0), (15, 1), (16, 0), (17, 0), (18, 0), (19, -1), (20, 0), (21, 0), (22, 0), (23, 1), (24, 0), (25, 0), (26, 0), (27, 1), (28, 0), (29, 0), (30, 0), (31, -1)]),
((4, 4), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 0), (4, 1), (5, -1), (6, -1), (7, 1), (8, 0), (9, 0), (10, 0), (11, 0), (12, -1), (13, 1), (14, 1), (15, -1)]),
((1, 1), .ofPairs [(0, 0), (1, 1)]),
((3, 4), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 1), (4, 0), (5, 0), (6, 0), (7, -1), (8, 0), (9, 0), (10, 0), (11, -1), (12, 0), (13, 0), (14, 0), (15, 1)]),
((5, 0), .ofPairs [(0, 1)]),
((0, 5), .ofPairs [(0, 1), (1, -1), (2, -1), (3, 1), (4, -1), (5, 1), (6, 1), (7, -1), (8, -1), (9, 1), (10, 1), (11, -1), (12, 1), (13, -1), (14, -1), (15, 1), (16, -1), (17, 1), (18, 1), (19, -1), (20, 1), (21, -1), (22, -1), (23, 1), (24, 1), (25, -1), (26, -1), (27, 1), (28, -1), (29, 1), (30, 1), (31, -1)]),
((2, 4), .ofPairs [(0, 0), (1, 0), (2, 1), (3, -1), (4, 0), (5, 0), (6, -1), (7, 1), (8, 0), (9, 0), (10, -1), (11, 1), (12, 0), (13, 0), (14, 1), (15, -1)]),
((4, 0), .ofPairs [(0, 1)]),
((0, 4), .ofPairs [(0, 1), (1, -1), (2, -1), (3, 1), (4, -1), (5, 1), (6, 1), (7, -1), (8, -1), (9, 1), (10, 1), (11, -1), (12, 1), (13, -1), (14, -1), (15, 1)]),
((4, 5), .ofPairs [(0, 0), (1, 0), (2, 0), (3, 0), (4, 1), (5, -1), (6, -1), (7, 1), (8, 0), (9, 0), (10, 0), (11, 0), (12, -1), (13, 1), (14, 1), (15, -1), (16, 0), (17, 0), (18, 0), (19, 0), (20, -1), (21, 1), (22, 1), (23, -1), (24, 0), (25, 0), (26, 0), (27, 0), (28, 1), (29, -1), (30, -1), (31, 1)]),
((1, 4), .ofPairs [(0, 0), (1, 1), (2, 0), (3, -1), (4, 0), (5, -1), (6, 0), (7, 1), (8, 0), (9, -1), (10, 0), (11, 1), (12, 0), (13, 1), (14, 0), (15, -1)]),
((1, 5), .ofPairs [(0, 0), (1, 1), (2, 0), (3, -1), (4, 0), (5, -1), (6, 0), (7, 1), (8, 0), (9, -1), (10, 0), (11, 1), (12, 0), (13, 1), (14, 0), (15, -1), (16, 0), (17, -1), (18, 0), (19, 1), (20, 0), (21, 1), (22, 0), (23, -1), (24, 0), (25, 1), (26, 0), (27, -1), (28, 0), (29, -1), (30, 0), (31, 1)]),
((3, 0), .ofPairs [(0, 1)]),
((0, 3), .ofPairs [(0, 1), (1, -1), (2, -1), (3, 1), (4, -1), (5, 1), (6, 1), (7, -1)])
] _
It works with 25 polynomials but then 36 makes it get stuck. And I need a much bigger cache, maybe ~300 polynomials. I'm using 4.0.0-nightly-2022-11-14
. Am I doing something in a bad way? Thanks in advance!
cc @Matej Penciak
Mario Carneiro (Dec 07 2022 at 13:44):
Both heap profiling and time profiling point to Lean.MetavarContext.MkBinding.{visit, elim}
, although I'm not sure that says much other than that it's looking at a huge number of exprs for some reason, probably a loss of subterm sharing somewhere
Mario Carneiro (Dec 07 2022 at 13:45):
It seems like a bad idea that the cache used here has no upper bound that I can see
Sebastian Ullrich (Dec 07 2022 at 13:47):
Usually caches with upper bounds are the reason for things suddenly going south above a certain term size. When there is sharing, the memory used by the cache usually is the least concern.
Sebastian Ullrich (Dec 07 2022 at 13:51):
We saw MkBinding
before in https://github.com/leanprover/lean4/pull/1390#issuecomment-1205107076, though the leaf spending most of the time there was elimMVars
Arthur Paulino (Dec 07 2022 at 13:52):
Sorry, I didn't understand. Should I use an upper bound? (how do I do that?)
And how do I make use of the sharing Sebastian mentioned?
Mario Carneiro (Dec 07 2022 at 13:54):
You know what, I think it's the use of .ofPairs
Mario Carneiro (Dec 07 2022 at 13:54):
This causes each subterm to get postponed and I think this messes everything up
Mario Carneiro (Dec 07 2022 at 13:56):
But also, you should be aware that lean has some known problems with large literals inside source files. You should try to use a custom elaborator to avoid some of the costs, but others can't be avoided as long as you are producing an Expr
at the end. Deep expressions are also bad, and even if you use something with nice binary recursion the compiler will linearize it and die anyway
Mario Carneiro (Dec 07 2022 at 13:57):
Reading data externally at runtime should be fine though, e.g. loading up a huge data structure parsed from JSON
Arthur Paulino (Dec 07 2022 at 13:58):
I tried replacing .ofPairs
by .ofList ... _
and had the same issue
Mario Carneiro (Dec 07 2022 at 13:59):
you're still using dot-ident there
Mario Carneiro (Dec 07 2022 at 13:59):
Use MultilinearPolynomial.ofPairs
Mario Carneiro (Dec 07 2022 at 13:59):
Lean doesn't know the type of that slot until it elaborates everything else
Mario Carneiro (Dec 07 2022 at 14:00):
and I think the repeated re-elaboration is generating a lot of allocations
Arthur Paulino (Dec 07 2022 at 14:02):
It solved the issue :open_mouth: thanks!!
Sebastian Ullrich (Dec 07 2022 at 14:05):
Hmm, elabDotIdent
should probably suspend immediately when the expected type is not known
Arthur Paulino (Dec 07 2022 at 14:05):
But there's still some hanging going on. I will remove the nesting with RB
stuff and just cache simple types like lists and pairs
Mario Carneiro (Dec 07 2022 at 14:06):
The error message here should give you some sense of what lean is having to deal with to elaborate this expression:
def multilinearLagrangePolynomialCache :
List ((Nat × Nat) × MultilinearPolynomial (Zmod n)) := [
((2, 3), .ofPairs []),
((5, 3), .ofPairs []),
((2, 1), .ofPairs []),
((3, 2), .ofPairs []),
((1, 3), .ofPairs []),
((4, 1), .ofPairs []),
((5, 4), .ofPairs []),
((0, 2), .ofPairs []),
((0, 1), .ofPairs []),
((1, 2), .ofPairs []),
((2, 2), .ofPairs []),
((3, 3), .ofPairs []),
((4, 2), .ofPairs []),
((2, 0), .ofPairs []),
((2, 5), .ofPairs []),
((3, 1), .ofPairs []),
((5, 2), .ofPairs []),
((5, 1), .ofPairs []),
((4, 3), .ofPairs []),
((1, 0), .ofPairs []),
((5, 5), .ofPairs []),
((0, 0), .ofPairs []),
((3, 5), .ofPairs []),
((4, 4), .ofPairs []),
((1, 1), .ofPairs []),
((3, 4), .ofPairs []),
((5, 0), .ofPairs []),
((0, 5), .ofPairs []),
((2, 4), .ofPairs []),
((4, 0), .ofPairs []),
((0, 4), .ofPairs []),
((4, 5), .ofPairs []),
((1, 4), .ofPairs []),
((1, 5), .ofPairs []),
((3, 0), .ofPairs []),
((0, 3), .ofPairs [])
] _
Mario Carneiro (Dec 07 2022 at 14:08):
we end up with a ton of metavariables in a ton of distinct contexts because of all the let statements, which is basically a worst case for the elaborator
Mario Carneiro (Dec 07 2022 at 14:09):
I thought the let-macro for list literals didn't trigger until length 64 though
Sebastian Ullrich (Dec 07 2022 at 14:11):
elemsAndSeps.size < 64
, note the And
Arthur Paulino (Dec 07 2022 at 14:12):
This is my plan for caching:
def multilinearLagrangePolynomialCacheData : List $ (Nat × Nat) × List (Nat × Int) := [
((1, 1), [(1, 1)]),
((3, 1), [(1, 1)]),
((4, 4), [(4, 1), (5, -1), (6, -1), (7, 1), (12, -1), (13, 1), (14, 1), (15, -1)]),
((1, 3), [(1, 1), (3, -1), (5, -1), (7, 1)]),
((3, 4), [(3, 1), (7, -1), (11, -1), (15, 1)]),
((2, 3), [(2, 1), (3, -1), (6, -1), (7, 1)]),
((0, 4), [(0, 1), (1, -1), (2, -1), (3, 1), (4, -1), (5, 1), (6, 1), (7, -1), (8, -1), (9, 1), (10, 1), (11, -1), (12, 1), (13, -1), (14, -1), (15, 1)]),
((0, 0), [(0, 1)]),
((3, 2), [(3, 1)]),
((1, 0), [(0, 1)]),
((3, 3), [(3, 1), (7, -1)]),
((2, 2), [(2, 1), (3, -1)]),
((1, 2), [(1, 1), (3, -1)]),
((3, 0), [(0, 1)]),
((0, 3), [(0, 1), (1, -1), (2, -1), (3, 1), (4, -1), (5, 1), (6, 1), (7, -1)]),
((4, 0), [(0, 1)]),
((4, 2), [(0, 1), (1, -1), (2, -1), (3, 1)]),
((0, 1), [(0, 1), (1, -1)]),
((2, 4), [(2, 1), (3, -1), (6, -1), (7, 1), (10, -1), (11, 1), (14, 1), (15, -1)]),
((0, 2), [(0, 1), (1, -1), (2, -1), (3, 1)]),
((4, 1), [(0, 1), (1, -1)]),
((2, 0), [(0, 1)]),
((4, 3), [(4, 1), (5, -1), (6, -1), (7, 1)]),
((1, 4), [(1, 1), (3, -1), (5, -1), (7, 1), (9, -1), (11, 1), (13, 1), (15, -1)]),
((2, 1), [(0, 1), (1, -1)])
]
That shouldn't raise any red flag, right? No metavariables involved as far as I can see
Mario Carneiro (Dec 07 2022 at 14:13):
Don't use long list literals if you can avoid it
Mario Carneiro (Dec 07 2022 at 14:13):
longer than 64 32 elements
Arthur Paulino (Dec 07 2022 at 14:14):
How can I cache then? I can't be in IO
Sebastian Ullrich (Dec 07 2022 at 14:14):
Should we simply have a custom elaborator for list literals?
Mario Carneiro (Dec 07 2022 at 14:14):
you can use an init
declaration
Mario Carneiro (Dec 07 2022 at 14:14):
the macro is terrible and needs to be replaced but last time someone posted about this leo basically said this only comes up in code which is misusing lean anyway so it's not a high priority
Mario Carneiro (Dec 07 2022 at 14:14):
I was planning on doing just that
Arthur Paulino (Dec 07 2022 at 14:15):
Where can I find an example of an init
declaration?
Mario Carneiro (Dec 07 2022 at 14:16):
initialize foo : HashMap A B <- (bla : IO (HashMap A B))
Mario Carneiro (Dec 07 2022 at 14:18):
It doesn't really solve the problem of storing high information content definitions in Expr
though, since it's still a regular declaration
Mario Carneiro (Dec 07 2022 at 14:19):
but it's generally a good idea not to lean on the elaborator too hard in such definitions, write things with explicit types
Arthur Paulino (Dec 07 2022 at 14:20):
But the list I wrote only has simple types
Arthur Paulino (Dec 07 2022 at 14:21):
Should I write a custom elaborator for lists then? Is the []
syntax the issue?
Mario Carneiro (Dec 07 2022 at 14:21):
yes, it's a major component of the problem in this case
Mario Carneiro (Dec 07 2022 at 14:22):
I would use a custom DSL to make the input terser anyway
Arthur Paulino (Dec 07 2022 at 14:27):
Alright, thanks! I'll report back after trying it
Arthur Paulino (Dec 07 2022 at 14:54):
Does the #[]
syntax suffer from the same issue?
Arthur Paulino (Dec 07 2022 at 16:25):
Hmm, I'm getting the following error with the DSL:
maximum recursion depth has been reached (use `set_option maxRecDepth <num>` to increase limit)
Arthur Paulino (Dec 07 2022 at 16:54):
This is the cache file with the DSL:
https://github.com/yatima-inc/YatimaStdLib.lean/blob/ap/multilinear-extension/YatimaStdLib/MLE/Cache.lean
Why is it reaching the maximum recursion depth?
Arthur Paulino (Dec 07 2022 at 16:55):
Well, not that version. But it crashes if I add like 100 lines
Arthur Paulino (Dec 07 2022 at 19:25):
Is there something I'm doing wrong in the DSL elaborator?
https://github.com/yatima-inc/YatimaStdLib.lean/blob/ap/multilinear-extension/YatimaStdLib/MLE/CacheDSL.lean
Mario Carneiro (Dec 08 2022 at 01:12):
Why is mkListLit not tail recursive? It should be written using a foldr
Arthur Paulino (Dec 08 2022 at 01:29):
You mean the function from core, right?
Arthur Paulino (Dec 08 2022 at 01:29):
Maybe I can make a customized version
Arthur Paulino (Dec 08 2022 at 01:40):
def mkListLit (type : Expr) (xs : List Expr) : MetaM Expr := do
let u ← getDecLevel type
let cons := .const ``List.cons [u]
return xs.foldr (init := mkApp (mkConst ``List.nil [u]) type) fun e acc =>
mkApp (mkApp (mkApp cons type) e) acc
Arthur Paulino (Dec 08 2022 at 01:44):
Still reaching maximum depth tho :dizzy:
Arthur Paulino (Dec 08 2022 at 01:48):
My next attempt will be using an initializer, reading the cached polynomials from a JSON file
Mario Carneiro (Dec 08 2022 at 01:48):
I think that's a good idea
Mario Carneiro (Dec 08 2022 at 01:49):
Another suggestion I have is to try using List.append
in a binary tree for long enough lists; this is kind of like what the macro was doing but without all the let stuff
Arthur Paulino (Dec 08 2022 at 01:50):
List.append
in a binary tree? How come?
Mario Carneiro (Dec 08 2022 at 01:51):
that is, replace [x1, ...., x2n]
with [x1, ..., xn] ++ [x(n+1), ..., x2n]
Mario Carneiro (Dec 08 2022 at 01:51):
It decreases the depth of the expr
Mario Carneiro (Dec 08 2022 at 01:53):
this is important because most lean internal functions on Expr
are not tail recursive, they use the C stack directly and there is no stack splitting fallback so a lot of stuff struggles not to blow the stack
Arthur Paulino (Dec 08 2022 at 01:57):
That's a good thing to learn! But I feel like I should just quit this strategy of caching values on a Lean file via an IO
function that (over)writes Lean code
Mario Carneiro (Dec 08 2022 at 01:59):
oh yeah, autogenerated lean files are always hit the hardest by these kind of restrictions
Arthur Paulino (Dec 08 2022 at 02:02):
I might come back asking for help on initializers on another thread though. But for now I'm satisfied with my current understanding. Thanks for all the help!
Arthur Paulino (Dec 08 2022 at 02:05):
Arthur Paulino said:
def mkListLit (type : Expr) (xs : List Expr) : MetaM Expr := do let u ← getDecLevel type let cons := .const ``List.cons [u] return xs.foldr (init := mkApp (mkConst ``List.nil [u]) type) fun e acc => mkApp (mkApp (mkApp cons type) e) acc
But that could be upstreamed to core regardless
Last updated: Dec 20 2023 at 11:08 UTC