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: Jason Gross <jasongross9 AT gmail.com>
  • To: coq-club <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 00:13:33 -0400
  • Authentication-results: mail2-smtp-roc.national.inria.fr; spf=None smtp.pra=jasongross9 AT gmail.com; spf=Pass smtp.mailfrom=jasongross9 AT gmail.com; spf=None smtp.helo=postmaster AT mail-ed1-f50.google.com
  • Ironport-phdr: 9a23:Ugti/xHaXUuK1dBvZLHGrJ1GYnF86YWxBRYc798ds5kLTJ7zo82wAkXT6L1XgUPTWs2DsrQY0rSQ7PmrCTVIyK3CmUhKSIZLWR4BhJdetC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBxrwKxd+KPjrFY7OlcS30P2594HObwlSizexfLJ/IA+0oAnMucUbgpZuIbstxxXUpXdFZ/5Yzn5yK1KJmBb86Maw/Jp9/ClVpvks6c1OX7jkcqohVbBXAygoPG4z5M3wqBnMVhCP6WcGUmUXiRVHHQ7I5wznU5jrsyv6su192DSGPcDzULs5Vyiu47ttRRT1jioMKjw3/3zNisFog61brhCuqRxxzYDXfY+bKuZxc7jHct8GX2dMRNpdWzBDD466coABD/ABPeFdr4Tlo1UBtwC+BQ6qBOjyyzFInHj23bYh0+88FgzG3hYvH8kJsHTSo9X1LqASUfuuzKTM1jjDYPZW1i386IjMaBwuvfaMXbdpfMfX1EIgGB/LgE+Kpoz5IzOayP4Ns26D4ud+Ue+hhXIqpxxyrzahyMohlofHi4Ibx13F6Sh0wJg5KNmmRUB1btCpEZtduj+GO4drX84vQ2BltSU1x7Abp5K2ejUBxpogxx7acfOHco6I7wrsVOaQPTd4hG9ld6mlixmu9kigz+vxXdS33lZStidJjMXAu3QX2xHQ6sWLUOVx8lui1DqV1w3f9udJKl0um6XBMZ4u2Lswm4ITsUvdGi/2n137jKqMeUUl/uik8vrobaj7qpOFOY95ih3yPr4hmsy4BuQ4PQwOUHaB9eug073j+FX1QLRMjvIojqnUqI7WKdgfq6KjAAJY0pwv5wijAzqlytgVnWULIEpAeB2djojpP1/OIOr/Dfe6m1mski1kx+vBPr3nDZXNNH/DkKz6fbt58ENcxw8zwspe55JQEL0OPPXzWkrpuNzCEhA5KxC0w/rgCNhlyoweXnuPDraFP6PWrF+H/fkiI/KMZY8QoDbyMeIp5//ojX8jmF8SZ7Ol3ZUNaCPwIvMzKEKAJHHon91JRWwNp081SPHgoFyESz9aIXioCfES/DY+XaCvFoDFDq+3h6ealHO5F4ZRYG9cDUuXQF/ncoyFX7EHbyfEcZwpqSANSbX0E9xp7hqprgKvk+M7fNqRwTURsNfY7PYw//fazEhg+jl9DsDb2GaIHTktwzE4AgQu1aU6mnRTj1eO1a8i3q5dHN1Xov5FC0I0aMaawOt9BNT/HAnGe4XREQf0cpCdGTg0C+kJ7ZoLakd5Fc+li0majSWvCr4R0beMAc5t/w==

> 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



Archive powered by MHonArc 2.6.19+.

Top of Page