Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: feat: integrate simp_mem with sym_n #179

Draft
wants to merge 53 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
a5c4d44
feat: withBenchmark combinator for fine-grained benchmarking
alexkeizer Sep 26, 2024
8e44bd9
feat: aggregated benchmarks
alexkeizer Sep 26, 2024
0ab52f3
refactor: extract a `withHeartbeatsAndMs` combinator
alexkeizer Sep 26, 2024
1e71b8d
feat: withBenchmarksReport combinator
alexkeizer Sep 26, 2024
59d1c2d
feat: benchmark a less trivial condition, using the numBlocks register
alexkeizer Sep 26, 2024
50128e3
refactor: BenchT abbrev
alexkeizer Sep 26, 2024
8378162
fix: pc of SHA512 benchmark
alexkeizer Sep 26, 2024
7dc9282
fix: reinstate 150 step benchmark
alexkeizer Sep 26, 2024
93a3f81
feat: preserve insertion order of the first sample of an aggregated stat
alexkeizer Sep 26, 2024
1f948b8
Merge branch 'main' into benchmarks-v2
alexkeizer Sep 26, 2024
1c56f0e
fix: sorry-out alignment goals in benchmark
alexkeizer Sep 26, 2024
9443720
feat: macro to disable multiple linters
alexkeizer Sep 27, 2024
e838675
feat: change the behaviour of `benchmark` when `profiler` is set to t…
alexkeizer Sep 27, 2024
1123c54
feat: add benchmarks with kernel and linters disabled
alexkeizer Sep 27, 2024
430fd9e
fix: remove accidental profiler option
alexkeizer Sep 27, 2024
ff86cf1
feat: bail early if there are no runs in a benchmark
alexkeizer Sep 27, 2024
718d8d6
refactor: prefer traces over log
alexkeizer Sep 27, 2024
a2afadb
refactor: invoke lean directly to run benchmarks
alexkeizer Sep 27, 2024
99f3f0f
fix: print hash of HEAD when doing benchmarks
alexkeizer Sep 27, 2024
998dbbc
fix: actually use `BENCH`, which explicitly sets the number of runs
alexkeizer Sep 27, 2024
5253302
feat: `profiler` make target
alexkeizer Sep 27, 2024
8c0940a
feat: suppress benchmark trace nodes in the profiler
alexkeizer Sep 27, 2024
ff43937
refactor: drop a use of `h_sp?`
alexkeizer Oct 1, 2024
79bc06d
refactor: drop the other use of hSp
alexkeizer Oct 1, 2024
e887c14
refactor: remove `SymContext.h_sp?`
alexkeizer Oct 1, 2024
42142ef
refactor: simplify `sym1` simplification step
alexkeizer Oct 1, 2024
b48f168
feat: attempt to preserve stack alignment roof in AxEffect update
alexkeizer Oct 1, 2024
477d811
Merge branch 'main' into benchmarks-v3
alexkeizer Oct 2, 2024
7e08a4b
revert bad merge
alexkeizer Oct 2, 2024
1ef20d7
chore: rename `withHeartbeatsAndMs` -> `...AndMilliseconds`
alexkeizer Oct 2, 2024
193ba2d
remove `profilerDir` option
alexkeizer Oct 2, 2024
ca101bc
feat: write shell-scripts to automatically log benchmark/profile data…
alexkeizer Oct 2, 2024
5c94d37
fix: set profile file extension to `.json`
alexkeizer Oct 2, 2024
e1860ad
Squashed commit of benchmarks-v3 / PR #204
alexkeizer Oct 2, 2024
32614c3
chore: add more trace nodes, for better profiling data
alexkeizer Oct 2, 2024
6aca323
chore: add tags to trace nodes
alexkeizer Oct 2, 2024
df3ab2c
chore: reduce threshold in profiler
alexkeizer Oct 2, 2024
e24b5db
chore: reduce threshold in profiler
alexkeizer Oct 2, 2024
e5f62fe
feat: use `withCurrHeartbeats` to reset the heartbeat usage for each …
alexkeizer Oct 3, 2024
fb314f4
fix SHA512 benchmark to compute the correct expected value for all nu…
alexkeizer Oct 3, 2024
9628874
Merge branch 'main' into benchmarks-v3
alexkeizer Oct 3, 2024
2fc7ece
fix SHA512 benchmark to compute the correct expected value for all nu…
alexkeizer Oct 3, 2024
f13d7f0
feat: add 50 step benchmark
alexkeizer Oct 3, 2024
74b3b9c
feat: make benchmarks more robust against changes in `sym_n`
alexkeizer Oct 3, 2024
2fd9ccb
Merge branch 'benchmarks-v3' into better-tracing
alexkeizer Oct 3, 2024
147db12
Merge branch 'better-tracing' into snorkel-heartbeats
alexkeizer Oct 3, 2024
b8fa9b5
refactor: move tracing helpers to new `Sym/Common` file
alexkeizer Oct 3, 2024
366d482
feat: improve tracing for `AxEffects`
alexkeizer Oct 3, 2024
fa4030e
chore: make section names more meaningful
alexkeizer Oct 4, 2024
66ad4fd
refactor: extract out `MemoryEffects` structure
alexkeizer Oct 7, 2024
077b5da
fix `MemoryEffects.validate` to expect the right type
alexkeizer Oct 7, 2024
40cb6f2
feat: integrate simp_mem with sym_n
alexkeizer Oct 7, 2024
711cf60
remove helpers that were moved to common file
alexkeizer Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/lake-packages/*
/.lake/*
*.log
/data/*
16 changes: 14 additions & 2 deletions Arm/Insts/Common.lean
Original file line number Diff line number Diff line change
Expand Up @@ -219,20 +219,32 @@ def CheckSPAlignment (s : ArmState) : Prop :=
instance : Decidable (CheckSPAlignment s) := by unfold CheckSPAlignment; infer_instance

@[state_simp_rules]
theorem CheckSPAligment_of_w_different (h : StateField.GPR 31#5 ≠ fld) :
theorem CheckSPAligment_w_different_eq (h : StateField.GPR 31#5 ≠ fld) :
CheckSPAlignment (w fld v s) = CheckSPAlignment s := by
simp_all only [CheckSPAlignment, state_simp_rules, minimal_theory, bitvec_rules]

theorem CheckSPAligment_w_of_ne_sp_of (h : StateField.GPR 31#5 ≠ fld) :
CheckSPAlignment s → CheckSPAlignment (w fld v s) := by
simp only [CheckSPAligment_w_different_eq h, imp_self]

@[state_simp_rules]
theorem CheckSPAligment_of_w_sp :
CheckSPAlignment (w (StateField.GPR 31#5) v s) = (Aligned v 4) := by
simp_all only [CheckSPAlignment, state_simp_rules, minimal_theory, bitvec_rules]

theorem CheckSPAligment_w_sp_of (h : Aligned v 4) :
CheckSPAlignment (w (StateField.GPR 31#5) v s) := by
simp only [CheckSPAlignment, read_gpr, r_of_w_same, zeroExtend_eq, h]

@[state_simp_rules]
theorem CheckSPAligment_of_write_mem_bytes :
theorem CheckSPAligment_write_mem_bytes_eq :
CheckSPAlignment (write_mem_bytes n addr v s) = CheckSPAlignment s := by
simp_all only [CheckSPAlignment, state_simp_rules, minimal_theory, bitvec_rules]

theorem CheckSPAligment_write_mem_bytes_of :
CheckSPAlignment s → CheckSPAlignment (write_mem_bytes n addr v s) := by
simp only [CheckSPAligment_write_mem_bytes_eq, imp_self]

@[state_simp_rules]
theorem CheckSPAlignment_AddWithCarry_64_4 (st : ArmState) (y : BitVec 64) (carry_in : BitVec 1)
(x_aligned : CheckSPAlignment st)
Expand Down
5 changes: 5 additions & 0 deletions Benchmarks.lean
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Benchmarks.SHA512_75
import Benchmarks.SHA512_75_noKernel_noLint
import Benchmarks.SHA512_150
import Benchmarks.SHA512_150_noKernel_noLint
import Benchmarks.SHA512_225
import Benchmarks.SHA512_225_noKernel_noLint
import Benchmarks.SHA512_400
import Benchmarks.SHA512_400_noKernel_noLint
122 changes: 84 additions & 38 deletions Benchmarks/Command.lean
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,104 @@ initialize
defValue := false
descr := "enables/disables benchmarking in `withBenchmark` combinator"
}
registerOption `benchmark.runs {
defValue := (5 : Nat)
descr := "controls how many runs the `benchmark` command does. \
NOTE: this value is ignored when the `profiler` option is set to true"
}
/- Shouldn't be set directly, instead, use the `benchmark` command -/
registerTraceClass `benchmark

variable {m} [Monad m] [MonadLiftT BaseIO m] in
def withHeartbeatsAndMs (x : m α) : m (α × Nat × Nat) := do
/-- Measure the heartbeats and time (in milliseconds) taken by `x` -/
def withHeartbeatsAndMilliseconds (x : m α) : m (α × Nat × Nat) := do
let start ← IO.monoMsNow
let (a, heartbeats) ← withHeartbeats x
let endTime ← IO.monoMsNow
return ⟨a, heartbeats, endTime - start⟩

elab "benchmark" id:ident declSig:optDeclSig val:declVal : command => do
logInfo m!"Running {id} benchmark\n"
/-- Adds a trace node with the `benchmark` class, but only if the profiler
option is *not* set.

We deliberately suppress benchmarking nodes when profiling, since it generally
only adds noise
-/
def withBenchTraceNode (msg : MessageData) (x : CommandElabM α )
: CommandElabM α := do
if (← getBoolOption `profiler) then
x
else
withTraceNode `benchmark (fun _ => pure msg) x (collapsed := false)

/--
Run a benchmark for a set number of times, and report the average runtime.

If the `profiler` option is set true, we run the benchmark only once, with:
- `trace.profiler` to true, and
- `trace.profiler.output` set based on the `benchmark.profilerDir` and the
id of the benchmark
-/
elab "benchmark" id:ident declSig:optDeclSig val:declVal : command => do
let originalOpts ← getOptions
let mut n := originalOpts.getNat `benchmark.runs 5
let mut opts := originalOpts
opts := opts.setBool `benchmark true
let stx ← `(command|
set_option benchmark true in
example $declSig:optDeclSig $val:declVal
)

let n := 5
let mut totalRunTime := 0
-- geomean = exp(log((a₁ a₂ ... aₙ)^1/n)) =
-- exp(1/n * (log a₁ + log a₂ + log aₙ)).
let mut totalRunTimeLog := 0
for i in [0:n] do
logInfo m!"\n\nRun {i} (out of {n}):\n"
let ((), _, runTime) ← withHeartbeatsAndMs <|
elabCommand stx

logInfo m!"Proof took {runTime / 1000}s in total"
totalRunTime := totalRunTime + runTime
totalRunTimeLog := totalRunTimeLog + Float.log runTime.toFloat

let avg := totalRunTime.toFloat / n.toFloat / 1000
let geomean := (Float.exp (totalRunTimeLog / n.toFloat)) / 1000.0
logInfo m!"\
{id}:
average runtime over {n} runs:
{avg}s
geomean over {n} runs:
{geomean}s
"
if (← getBoolOption `profiler) then
opts := opts.setBool `trace.profiler true
opts := opts.setNat `trace.profiler.threshold 1
n := 1 -- only run once, if `profiler` is set to true
else
opts := opts.setBool `trace.benchmark true

if n = 0 then
return ()

-- Set options
modifyScope fun scope => { scope with opts }

withBenchTraceNode m!"Running {id} benchmark" <| do
let mut totalRunTime := 0
-- geomean = exp(log((a₁ a₂ ... aₙ)^1/n)) =
-- exp(1/n * (log a₁ + log a₂ + log aₙ)).
let mut totalRunTimeLog : Float := 0
for i in [0:n] do
let runTime ← withBenchTraceNode m!"Run {i+1} (out of {n}):" <| do
let ((), _, runTime) ← withHeartbeatsAndMilliseconds <|
elabCommand stx

trace[benchmark] m!"Proof took {runTime / 1000}s in total"
pure runTime
totalRunTime := totalRunTime + runTime
totalRunTimeLog := totalRunTimeLog + Float.log runTime.toFloat

let avg := totalRunTime.toFloat / n.toFloat / 1000
let geomean := (Float.exp (totalRunTimeLog / n.toFloat)) / 1000.0
trace[benchmark] m!"\
{id}:
average runtime over {n} runs:
{avg}s
geomean over {n} runs:
{geomean}s
"
-- Restore options
modifyScope fun scope => { scope with opts := originalOpts }

/-- Set various options to disable linters -/
macro "disable_linters" "in" cmd:command : command => `(command|
set_option linter.constructorNameAsVariable false in
set_option linter.deprecated false in
set_option linter.missingDocs false in
set_option linter.omit false in
set_option linter.suspiciousUnexpanderPatterns false in
set_option linter.unnecessarySimpa false in
set_option linter.unusedRCasesPattern false in
set_option linter.unusedSectionVars false in
set_option linter.unusedVariables false in
$cmd
set_option linter.constructorNameAsVariable false in
set_option linter.deprecated false in
set_option linter.missingDocs false in
set_option linter.omit false in
set_option linter.suspiciousUnexpanderPatterns false in
set_option linter.unnecessarySimpa false in
set_option linter.unusedRCasesPattern false in
set_option linter.unusedSectionVars false in
set_option linter.unusedVariables false in
$cmd
)

/-- The default `maxHeartbeats` setting.
Expand Down Expand Up @@ -96,7 +142,7 @@ private def withBenchmarkAux (x : m α) (f : Nat → Nat → m Unit) : m α :=
if (← getBoolOption `benchmark) = false then
x
else
let (a, heartbeats, t) ← withHeartbeatsAndMs x
let (a, heartbeats, t) ← withHeartbeatsAndMilliseconds x
f heartbeats t
return a

Expand Down
8 changes: 6 additions & 2 deletions Benchmarks/SHA512.lean
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ namespace Benchmarks

def SHA512Bench (nSteps : Nat) : Prop :=
∀ (s0 sf : ArmState)
(_h_s0_num_blocks : r (.GPR 2#5) s0 = 10)
(_h_s0_num_blocks : r (.GPR 2#5) s0 = 10#64)
(_h_s0_pc : read_pc s0 = 0x1264c0#64)
(_h_s0_err : read_err s0 = StateError.None)
(_h_s0_sp_aligned : CheckSPAlignment s0)
(_h_s0_program : s0.program = SHA512.program)
(_h_run : sf = run nSteps s0),
r StateField.ERR sf = StateError.None
∧ r (.GPR 2#5) sf = BitVec.ofNat _ (9 - (nSteps / 485))
∧ r (.GPR 2#5) sf = BitVec.ofNat 64 (10 - ((nSteps + 467) / 485))
-- / -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- | This computes the expected value of x2, taking into account that
-- | the loop body is 485 instructions long, and that x2 is first
-- | decremented after 18 instructions (485 - 18 = 467).
3 changes: 2 additions & 1 deletion Benchmarks/SHA512_150.lean
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ open Benchmarks
benchmark sha512_150_instructions : SHA512Bench 150 := fun s0 _ h => by
intros
sym_n 150
· exact (sorry : Aligned ..)
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
19 changes: 19 additions & 0 deletions Benchmarks/SHA512_150_noKernel_noLint.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

disable_linters in
set_option debug.skipKernelTC true in
benchmark sha512_150_noKernel_noLint : SHA512Bench 150 := fun s0 _ h => by
intros
sym_n 150
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
19 changes: 19 additions & 0 deletions Benchmarks/SHA512_225_noKernel_noLint.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

disable_linters in
set_option debug.skipKernelTC true in
benchmark sha512_225_noKernel_noLint : SHA512Bench 225 := fun s0 _ h => by
intros
sym_n 225
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
3 changes: 2 additions & 1 deletion Benchmarks/SHA512_400.lean
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ open Benchmarks
benchmark sha512_400_instructions : SHA512Bench 400 := fun s0 _ h => by
intros
sym_n 400
· exact (sorry : Aligned ..)
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
19 changes: 19 additions & 0 deletions Benchmarks/SHA512_400_noKernel_noLint.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

disable_linters in
set_option debug.skipKernelTC true in
benchmark sha512_400_noKernel_noLint : SHA512Bench 400 := fun s0 _ h => by
intros
sym_n 400
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
17 changes: 17 additions & 0 deletions Benchmarks/SHA512_50.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

benchmark sha512_50 : SHA512Bench 50 := fun s0 _ h => by
intros
sym_n 50
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
19 changes: 19 additions & 0 deletions Benchmarks/SHA512_50_noKernel_noLint.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

disable_linters in
set_option debug.skipKernelTC true in
benchmark sha512_50_noKernel_noLint : SHA512Bench 50 := fun s0 _ h => by
intros
sym_n 50
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
17 changes: 17 additions & 0 deletions Benchmarks/SHA512_75.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

benchmark sha512_75 : SHA512Bench 75 := fun s0 _ h => by
intros
sym_n 75
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
19 changes: 19 additions & 0 deletions Benchmarks/SHA512_75_noKernel_noLint.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/-
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author(s): Alex Keizer
-/
import Tactics.Sym
import Benchmarks.Command
import Benchmarks.SHA512

open Benchmarks

disable_linters in
set_option debug.skipKernelTC true in
benchmark sha512_75_noKernel_noLint : SHA512Bench 75 := fun s0 _ h => by
intros
sym_n 75
simp (config := {failIfUnchanged := false}) only [h, bitvec_rules]
all_goals exact (sorry : Aligned ..)
done
Loading
Loading