Zulip Chat Archive

Stream: general

Topic: Extremely slow simp


Gabriel Ebner (Feb 27 2020 at 23:02):

The following example takes more than one minute on my machine:

import all
set_option trace.simplify true
set_option profiler true

open_locale nnreal
example (a : ) (ha) : ((a, ha : 0) : ) = a :=
by simp

The simplifier rewrites once. However it seems to spend a huge time trying to match add_con.coe_add (20s), con.coe_mul (19s), filter.filter_product.of_one (9s), filter.filter_product.of_neg (4s), and filter.filter_product.of_zero (15s). Does anybody have any idea what's going on here?

Rob Lewis (Feb 27 2020 at 23:04):

What are the imports?

Gabriel Ebner (Feb 27 2020 at 23:05):

import all

Kevin Buzzard (Feb 27 2020 at 23:14):

You should have used squeeze_simp, then you would only have to do it once

Rob Lewis (Feb 27 2020 at 23:42):

Past my bedtime now, but the (or a) culprit seems to be an instance search for example : has_mul {r : ℝ // 0 ≤ r} := by apply_instance. nnreal gets unfolded somewhere it shouldn't.

Rob Lewis (Feb 27 2020 at 23:48):

Ah, (⟨a, ha⟩ : ℝ≥0) doesn't actually have type nnreal, it has type {r : real // 0 <= r}. Nothing's getting unfolded, it isn't even folded to start with.

Antoine Labelle (May 28 2022 at 17:41):

The following proof takes around 2 min 30 to compile. Any idea why it is so slow and how to speed it up? (it requires adding @[simps] to docs#category_theory.monoidal_category.full_monoidal_subcategory to work).

import representation_theory.basic
import representation_theory.fdRep

universes u
open representation

variables {k G V W : Type u} [field k] [group G]
variables [add_comm_group V] [module k V] [add_comm_group W] [module k W]
variables [finite_dimensional k V] [finite_dimensional k W]
variables (ρV : representation k G V) (ρW : representation k G W)

local attribute tensor_product.ext

@[simps] def linear_equiv.to_FinVect_iso
  (e : V ≃ₗ[k] W) :
  FinVect.of k V  FinVect.of k W :=
{ hom := e.to_linear_map,
  inv := e.symm.to_linear_map,
  hom_inv_id' := by {ext, exact e.left_inv x},
  inv_hom_id' := by {ext, exact e.right_inv x} }

noncomputable
def dual_tensor_iso_lin_hom : (fdRep.of ρV.dual)  (fdRep.of ρW)  fdRep.of (lin_hom ρV ρW) :=
begin
  refine Action.mk_iso (dual_tensor_hom_equiv k V W).to_FinVect_iso _,
  intro g, ext f w v, simp [module.dual.transpose_apply],
end

Kevin Buzzard (May 28 2022 at 17:54):

I get an unknown lin_hom. Is this representation.lin_hom?

Kevin Buzzard (May 28 2022 at 17:55):

Then I get a type mismatch. I'm on today's master.

Antoine Labelle (May 28 2022 at 17:55):

Where do you get a type mismatch?

Kevin Buzzard (May 28 2022 at 17:56):

Why not add the simps attribute in the mwe?

Kevin Buzzard (May 28 2022 at 17:56):

If you're on today's master and you cut and paste, you'll be able to see exactly what I'm seeing :-)

Kevin Buzzard (May 28 2022 at 17:58):

Am I supposed to be adding attribute [simps] category_theory.monoidal_category.full_monoidal_subcategory to this mwe? I get it on Action.mk_iso, a type mismatch.

Antoine Labelle (May 28 2022 at 18:01):

Kevin Buzzard said:

Why not add the simps attribute in the mwe?

Oh I forgot that you can add the simps attribute locally and not just before the definition. So yes I think the mwe requires attribute [simps] category_theory.monoidal_category.full_monoidal_subcategory.

Antoine Labelle (May 28 2022 at 18:05):

Let me try to figure out why there's a type mismatch.

Antoine Labelle (May 29 2022 at 18:03):

Ok, I haven't been able to figure out why the MWE didn't work (if someone understands why let me know!) but I PR'd the branch in which the proof works : #14453

Antoine Labelle (May 29 2022 at 18:04):

(The proof in question is at the end of representation_theory/basic).

Antoine Labelle (May 29 2022 at 19:29):

Hmm, so the proof is so slow that CI gives a deterministic timeout even though it works locally for me. I tried squeeze_simp but my computer start lagging before squeeze_simp succeed... Does squeeze_simp work for anyone else?

Alex J. Best (May 29 2022 at 19:33):

squeeze_simp can be quite slow as it basically just tries simp over and over again to do the squeezing, you might be able to adjust the timeout locally (see https://leanprover-community.github.io/tips_and_tricks.html#memory-and-deterministic-timeout) then wait a few minutes for squeeze simp and get a version that works on CI

Ruben Van de Velde (May 29 2022 at 19:40):

Or try simp? rather than squeeze_simp - it's a little less reliable, but tends to be faster

Antoine Labelle (May 29 2022 at 20:02):

simp? worked but even after changing to simp_only it takes almost 2 minutes to compile and CI fails with deterministic timeout.

Stuart Presnell (May 29 2022 at 22:22):

What did simp? suggest? Is there anything you can pull out of the simp_only to use directly in, for example, a rw or refine?

Kyle Miller (May 29 2022 at 22:29):

Even this is very slow (with or without noncomputable!):

def dual_tensor_iso_lin_hom : (fdRep.of ρV.dual)  (fdRep.of ρW)  fdRep.of (lin_hom ρV ρW) :=
begin
  sorry,
end

Kyle Miller (May 29 2022 at 22:29):

It takes a bit more than 11 seconds for me.

Antoine Labelle (May 29 2022 at 22:35):

Kyle Miller said:

Even this is very slow (with or without noncomputable!):

def dual_tensor_iso_lin_hom : (fdRep.of ρV.dual)  (fdRep.of ρW)  fdRep.of (lin_hom ρV ρW) :=
begin
  sorry,
end

Indeed that's pretty weird. I wonder what takes so much time.

Antoine Labelle (May 30 2022 at 00:22):

And changing the simp only to a bunch of rewrites won't be enough for CI, since just the following gives a deterministic timeout with a time limit of 100 000.

def dual_tensor_iso_lin_hom : (fdRep.of ρV.dual)  (fdRep.of ρW)  fdRep.of (lin_hom ρV ρW) :=
begin
  refine Action.mk_iso (dual_tensor_hom_equiv k V W).to_FinVect_iso _,
  intro g, ext f w v,
  sorry,
end

Stuart Presnell (May 30 2022 at 09:52):

On my (admittedly rather old) computer this:

import representation_theory.basic
import representation_theory.fdRep

universes u
open representation

variables {k G V W : Type u} [field k] [group G]
variables [add_comm_group V] [module k V] [add_comm_group W] [module k W]
variables [finite_dimensional k V] [finite_dimensional k W]
variables (ρV : representation k G V) (ρW : representation k G W)

lemma test1 : fdRep.of ρV.dual = fdRep.of ρV.dual := rfl

takes 33 seconds, but then the profiler can't account for that time:

parsing took 0.341ms
type checking of test1 took 26.1ms
decl post-processing of test1 took 0.0402ms
elaboration of test1 took 0.587ms

Stuart Presnell (May 30 2022 at 10:07):

For comparison, this takes 20 seconds:

lemma test2 : fdRep.of ρV.dual = fdRep.of ρV := sorry

while this is immediate:

lemma test3 : ρV.dual = ρV.dual := rfl

and this takes 7 seconds:

lemma test4 : fdRep.of ρV = fdRep.of ρV := rfl

Stuart Presnell (May 30 2022 at 10:16):

and just this takes 15 seconds:

#check fdRep.of ρV.dual

Yaël Dillies (May 30 2022 at 10:17):

Something to do with docs#fdRep.of, then?

Kevin Buzzard (May 30 2022 at 10:19):

What happens if you put noncomputable! in front of the lemmas?

Stuart Presnell (May 30 2022 at 10:19):

#check fdRep.of ρV takes 3 seconds

Stuart Presnell (May 30 2022 at 10:24):

Adding noncomputable! hasn't changed the timings

Stuart Presnell (May 30 2022 at 10:28):

These are all wall-clock timings, by the way. If I add set_option profiler true then the output of the profiler only adds up to a few milliseconds.

Ben Toner (May 30 2022 at 10:39):

You can probably assume that the time missing from the profiler is spent on type checking: see https://github.com/leanprover-community/lean/issues/58

Antoine Labelle (Jun 01 2022 at 17:26):

Stuart Presnell said:

On my (admittedly rather old) computer this:

import representation_theory.basic
import representation_theory.fdRep

universes u
open representation

variables {k G V W : Type u} [field k] [group G]
variables [add_comm_group V] [module k V] [add_comm_group W] [module k W]
variables [finite_dimensional k V] [finite_dimensional k W]
variables (ρV : representation k G V) (ρW : representation k G W)

lemma test1 : fdRep.of ρV.dual = fdRep.of ρV.dual := rfl

takes 33 seconds, but then the profiler can't account for that time:

parsing took 0.341ms
type checking of test1 took 26.1ms
decl post-processing of test1 took 0.0402ms
elaboration of test1 took 0.587ms

Note that we get equally slow results with docs#Rep.of instead of fdRep.of, so it's not a problem with the finite dimensionality instance. So the thing that takes a lot of time must be the conversion of ρ : G →* (V →ₗ[k] V) to ρ : G ⟶ Mon.of (category_theory.End (Module.of V)) in the definition of Rep.of, especially when ρ is defined as representation.dual. Is there a modification of the definition of Rep.of that would make this faster?

Stuart Presnell (Jun 01 2022 at 17:55):

Antoine Labelle said:

Note that we get equally slow results with docs#Rep.of instead of fdRep.of

As another data point, this takes 13 seconds:

#check Rep.of ρV.dual

Antoine Labelle (Jun 05 2022 at 15:33):

It took some time, but I think I finally found the culprit here: it seems to be the coercion from representation k G to G →* (V →ₗ[k] V). Indeed, the following is immediate

def representation.to_monoid_hom : G →* (V →ₗ[k] V) := ρV
#check Rep.of ρV.dual.to_monoid_hom

whereas without to_monoid_hom it takes 13 seconds as mentioned by Stuart.

Antoine Labelle (Jun 05 2022 at 15:38):

This makes me wonder if the definition of representation is ok. It is currently defined as

abbreviation representation := G →* (V →ₗ[k] V)

I don't know much about how abbreviation works, is it the same as def or does it have a different behavior?

Antoine Labelle (Jun 05 2022 at 15:45):

If we keep representation as it is, we have two options. Either we change the argument of Rep.of to be of type representation k G instead of G →* (V →ₗ[k] V), or we don't touch Rep.of but we put to_monoid_hom everytime we want use Rep.of on something of type representation k G. @Scott Morrison maybe you have an opinion on that since you're the author of Rep?

Antoine Labelle (Jun 05 2022 at 15:47):

(One issue with the first option is that it requires representation_theory.Rep to import representation_theory.basic whereas in #14453 I have the opposite import.)

Kyle Miller (Jun 05 2022 at 15:52):

abbreviation is pretty much @[reducible, inline] def (though unlike def it doesn't generate equation lemmas, which impacts how you unfold it.)

Kyle Miller (Jun 05 2022 at 15:54):

The presence of V twice in that abbreviation is worrisome to me. There's a chance it's causing exponential behavior since reducible means Lean is happy to unfold it when doing typeclass inference.

Kyle Miller (Jun 05 2022 at 15:56):

inline only has an effect on VM compilation and the noncomputability checker, but still it doesn't strike me as being a good idea to inline code that refers to variables more than once.

Antoine Labelle (Jun 07 2022 at 23:01):

@Kyle Miller Do you think that representation should be a def and not an abbreviation in this case?
Also the problem is really due to presence of V twice, wouldn't docs#module.End have the same problems? Has anyone noticed any issue with module.End?

Yaël Dillies (Jun 08 2022 at 06:20):

Surely V appearing twice is not quite the criterion, else we would have had troubles ages ago with docs#equiv.perm.

Eric Wieser (Jun 08 2022 at 12:11):

I've had problems with module.End and @[simps] before


Last updated: Dec 20 2023 at 11:08 UTC