Skip to Content.
Sympa Menu

coq-club - Re: [Coq-Club] Ltac2 Performance Question

coq-club AT inria.fr

Subject: The Coq mailing list

List archive

Re: [Coq-Club] Ltac2 Performance Question


Chronological Thread 
  • From: Gregory Malecha <gregory AT bedrocksystems.com>
  • To: coq-club AT inria.fr
  • Cc: "jonikelee AT gmail.com" <jonikelee AT gmail.com>
  • Subject: Re: [Coq-Club] Ltac2 Performance Question
  • Date: Sun, 2 Aug 2020 10:44:02 -0400
  • Authentication-results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=gregory AT bedrocksystems.com; spf=None smtp.mailfrom=gregory AT bedrocksystems.com; spf=None smtp.helo=postmaster AT mail-pg1-f180.google.com
  • Ironport-phdr: 9a23:zVBRhxHB8yYWtrwpmThz0J1GYnF86YWxBRYc798ds5kLTJ7zrsuwAkXT6L1XgUPTWs2DsrQY0rSQ7PqrCTVIyK3CmUhKSIZLWR4BhJdetC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBxrwKxd+KPjrFY7OlcS30P2594HObwlSizexfLJ/IA+0oAnPucUbgpZuIbstxxXUpXdFZ/5Yzn5yK1KJmBb86Maw/Jp9/ClVpvks6c1OX7jkcqohVbBXAygoPG4z5M3wqBnMVhCP6WcGUmUXiRVHHQ7I5wznU5jrsyv6su192DSGPcDzULs5Vyiu47ttRRT1jioMKjw3/3zNisFog61brhCuqRxxzYDXfY+bKuZxc7jHct8GX2dMRNpdWzBDD466coABD/ABPeFdr4TlplUOtwWxBQarBOP1yj5Dm3j40rc+0+s/DQ7G3BYvFM8JvXTbttX6KqgSUeevzKjI1jjMdO1Z1irn6IjPbh8houqMXLJrccrN10YvEhjFgk+MpoziOjOYz+IAuHWU4OR8T+ygkXInqx1vrTi1wMchkpXEi4AWx13E9Ch03ok4KMO6RUN/f9OpE4Zcuj+VOYZyQs0sQ2VltDo4x7MIpZK1cycHxZokyhPfdfGKboeG7BLlWe2MLzl4g3dld6i+hxa06UWgxez8VtW00FZXtSVJiMXDtncI1xDL5ciHS+d9/ke82TmUzQzf8P1LIUcxlafdNpUvwaYwm4INvUjfGiL6gkb7ga+Mekk65+Sl6/7rbqjlq5OAMYJ/lxvwPb40msOlBOQ1KggOUHaf+eS7zLDj+Ff2QLROjvEviqnZv43WKd0VpqKkAAJZzpwv6xm4Dzeh39QYmWcIIEhZdxKAiojlI1DOIPbmAvejm1mgjitnyvTcMrDiApjBNGbPnKrhcLpn9kJRyxY/wcha551OC7EBJPzzWlX2tNzdFhI5PBa0zPjoCNV6zIMfWXmCDbSHP6zPq1+I4f4gI+qXZI4Vozb9N+Yq5/v1jXMjhVAdeqyp0YMNaH+kBvRmP1mZYX30j9gdFmcKpxMyQ/DuiF2fSjFefG2yXqI55jEjEo2qF4bDRoa3gLyAxii3BJNWZnoVQmyLRHzvbsCPX+oGQCOUOM5o1DIeBpa7TIp0+gujuwjg2vJCJ+7Z8S0R/cbsztV64PfCvRs/+SZzBMeGwnqRQmRv2GgPQmllj+hEvUVhxwLbguBDiPtCGIkLvqIbYkIBLZfZitdCJZX3UwPFcM2OTQz+EN+rDSs2RdEq0sQSbkNmXd6li0Kbhnb4M/ouj7WOQacM3OfExXGrf5R3xnrc06IilEg9XsZKLiutgastr1GOVb6MqF2QkuORTYpZ3CPJ8z3dn2+HvUUdSAEpFKucDShZaUzRotD0oEjFSu32BA==

Thanks Jason and Jonathan!

I'm still on 8.11.2, it looks like I need to upgrade to 8.12 to get more array functions.

Regarding the two suggestions,
1. In the AST, references to globals are leaf nodes (modulo universe instances), so I had expected this to happen anyways without any manual intervention on my part. I do have other cases with universe polymorphism and in those cases I definitely can not pull that trick without building a sub-optimal proof at the universe level. I could do the comparisons manually, but it seems that there are no equality tests on types like [inductive] and [constructor]. I opened an issue for that: https://github.com/coq/coq/issues/12786
That said, this is great because it actually gives me a way to bind the universe [instance], unfortunately, there seem to be no accessors on [instance]..so it might not help as much as I would like.

2. I want to check that the head constant is [and], otherwise I'd be returning an incorrect proof term. Again, I am probably mistaken, but I thought that lazy_match was implemented using Constr.Unsafe. This should definitely be possible when the pattern is linear, and might also be true when the pattern is non-linear, though there would be some side-conditions to check.

On Sun, Aug 2, 2020 at 12:14 AM Jason Gross <jasongross9 AT gmail.com> wrote:
> constructing the array is quite annoying, maybe there is notation that I missed?

I generally use `Array.of_list` with the notation `[x; y; z]` (or maybe it's `[|x; y; z|]`?, I can't quite recall),which is a tiny bit more expensive, but much more compact.

> (* Ltac2 (Unsafe) implementation *)

I would suggest two changes:
1. pass in `constr:(I)` and `'conj` at the top level (and pass them down recursively) so you only construct them once rather than at every node
2. Use `match Constr.Unsafe.kind p with` rather than `lazy_match!`.  It's significantly more opaque and less robust to mis-matches (generally, e.g., I'll skip the check that the head constr is and, skip the array length checks, etc), but I think it's significantly faster.

On Sat, Aug 1, 2020 at 11:57 PM Gregory Malecha <gregory AT bedrocksystems.com> wrote:
The unsafe version of the tactic is included below, constructing the array is quite annoying, maybe there is notation that I missed? Certainly adding the [check] here is pretty expensive.

I filed an issue here which contains the full text (also included below): https://github.com/coq/coq/issues/12785

Returning to the earlier question, I get back a decent amount of performance in my original tactic by using [@conj p q l r] rather than [conj l r] in both the Ltac and the Ltac2 case.

My latest figures show less performance loss than I originally measured (2x instead of 3x), there might have been too much jitter in my tests. The numbers below are averages of 10 fresh runs.

(* Ltac2 implementation *)
Ltac2 rec build2 p :=
  lazy_match! p with
  | True => constr:(I)
  | ?p /\ ?q =>
    let l := build2 p in
    let r := build2 q in
    constr:(@conj $p $q $l $r)
  end.

(* Ltac2 (Unsafe) implementation *)
Ltac2 rec build2_unsafe p :=
  lazy_match! p with
  | True => constr:(I)
  | ?p /\ ?q =>
    let l := build2_unsafe p in
    let r := build2_unsafe q in
    let ary := Array.make 4 p in
    let _ := Array.set ary 1 q in
    let _ := Array.set ary 2 l in
    let _ := Array.set ary 3 r in
    Unsafe.make (Unsafe.App 'conj ary)
  end.

(* Ltac2 (Unsafe-Check) implementation *)
Ltac2 rec build2_unsafe_check p :=
  lazy_match! p with
  | True => constr:(I)
  | ?p /\ ?q =>
    let l := build2_unsafe_check p in
    let r := build2_unsafe_check q in
    let ary := Array.make 4 p in
    let _ := Array.set ary 1 q in
    let _ := Array.set ary 2 l in
    let _ := Array.set ary 3 r in
    match Unsafe.check (Unsafe.make (Unsafe.App 'conj ary)) with
    | Val v => v
    | Err e => Control.throw e
    end
  end.

(* Ltac implementation *)
Ltac build_it p k :=
  lazymatch p with
  | True => k constr:(I)
  | ?p /\ ?q => build_it p ltac:(fun P => build_it q ltac:(fun Q => k constr:(@conj p q P Q)))
  end.

Fixpoint build_goal (n : nat) : Prop :=
  match n with
  | 0 => True
  | S n => build_goal n /\ build_goal n
  end.

Goal build_goal 10.
  simpl.
  Time Control.enter (fun () =>
    let g := Control.goal () in
    let pf := build2 g in
    exact $pf).
  (** ~0.2241s *)
  Undo.
  Time Control.enter (fun () =>
    let g := Control.goal () in
    let pf := build2_unsafe g in
    exact $pf).
  (** ~0.1444s *)
Time Control.enter (fun () =>
    let g := Control.goal () in
    let pf := build2_unsafe_check g in
    exact $pf).
  (** ~0.2307s *)
  Undo.
  Time repeat constructor.
  (** ~0.1658s *)
  Undo.
  Time ltac1:(match goal with
              | |- ?G => build_it G ltac:(fun p => exact p)
              end).
  (** ~0.0939s *)
Qed.


On Sat, Aug 1, 2020 at 2:02 PM jonikelee AT gmail.com <jonikelee AT gmail.com> wrote:
On Sat, 1 Aug 2020 13:16:32 -0400
Gregory Malecha <gregory AT bedrocksystems.com> wrote:

> Thanks for pointing that out. It inspired me to look at the resulting
> code. I get the following:
>
> build : constr -> constr
> build :=
>   fun x =>
>   let rec build :=
>     fun p =>
>     let m :=
>       [Pattern.MatchPattern, pattern:(True), (fun _ => fun _ =>
> constr:(I)); Pattern.MatchPattern, pattern:(and ?p ?q),
>         (fun _ =>
>          fun p => let q := Array.get p 1 with p := Array.get p 0 in
> let l := build p in let r := build q in constr:(@conj _ _ _ _))] with
>       t := p in
>     Pattern.lazy_match0 t m in
>   build x
>
> I assume that the `_`s in the constr: are printing artifacts.
>
> You are right, building the term with Unsafe gets me performance on
> par with Ltac. It seems like this would be a natural implementation
> of constr, and for some reason I thought that I had read that it was
> in the manual, but I must be mistaken.

Grregory,

What does the Unsafe-using version of your example look like?



--

Gregory Malecha

Mail: gregory AT bedrocksystems.com

BedRock

Systems Inc
UNBREAKABLE FOUNDATION FOR

FORMALLY SECURED COMPUTING


--

Gregory Malecha

Mail: gregory AT bedrocksystems.com

BedRock

Systems Inc
UNBREAKABLE FOUNDATION FOR

FORMALLY SECURED COMPUTING



Archive powered by MHonArc 2.6.19+.

Top of Page