Skip to content

Faster single-thread aggregation: padding tails summed once, a live-prefix dense reduction, and four smaller prover changes - #501

Merged
tcoratger merged 35 commits into
leanEthereum:riscv-explorationfrom
kevaundray:kw/agg1-combined
Oct 7, 2026
Merged

tcoratger merged 35 commits into
leanEthereum:riscv-explorationfrom
kevaundray:kw/agg1-combined

Conversation

@kevaundray

@kevaundray kevaundray commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

This PR was created with Claude Code, prompted by @kevaundray.

#463 (word-level witnesses) is merged upstream now, so its part comes from the base. This PR's own changes are the six prover changes below, each also published as a branch of its own. A related open PR, #464 (the commit NTT plan for few workers), changes the same NTT function as section 3. This branch no longer contains it (dc24a752 took it out); whichever of the two lands second merges the other.

Every change is prover-only: the verifier, the transcript and the proofs are unchanged, byte for byte.

The base now includes #523 (leaves at rate 1/4, a two-scalar transcript step, stratified WHIR queries), so this PR is #501 on top of #523. Measured locally (Ryzen 9 7950X3D) on that same combination, while this branch still contained #464 and before #518 to #521 landed, against upstream before #523 (468c67cd), the aggregator time per leaf of a 2-to-1 tree over leanXMSS-400 leaves falls by 46% at 32 threads (0.168 to 0.091 s) and by 56% at one thread (0.969 to 0.425 s); #523 alone gives -30% and -43%, so these changes take another 23% off on top of it at both thread counts. The 4-to-1 tree at 32 threads falls by 44% (0.098 to 0.055 s per leaf).

Where single-thread aggregation spends its time

A 2-to-1 aggregation node (cargo leanvm aggregate --n 100 --leaves 4 --arity0 2 --arity 2, the shape CI tracks as aggregate-leanxmss-100-2to1 and -1thread) proves one recursion proof over two children: the first-level node verifies two leanXMSS RISC-V proofs in rows, the node two first-level recursion proofs. Both have the same circuit heights (EMUL 2^17, EXK 2^16, HASH 2^15, CAST 2^13, SPLIT and PUB 2^10; 10.16M committed words).

On one thread, upstream at f774828d took 974 ms for the first-level node and 1041 ms for the node. The recursion proof is 95% of it (about 911 ms):

span (1T, first-level node, upstream f774828d) ms
Build witness 73
Commit (base encode and Merkle) 150
Prove bus 115
Prove constraints 46
Flock reduction of the HASH rows (zerocheck 229) 237
PCS open (first pass 77, first lane fold 72, extension commits 103) 286
Reduce claims (node: 84, of which the dense reduction 70) 25

#463 and #465 (both merged since) and #464 (open, a separate PR) take the witness, the base commit, the bus and the constraints. They leave the HASH zerocheck, the opening and the node's claim reduction as they are; the changes here go after those, plus two smaller leftovers.

1. The zerocheck sums a batch's identical padding tail once

Branch kw/agg1-padskip (7a88b966, on f774828d).

  • Why: the HASH table holds 22,871 (first-level node) and 19,665 (node) live rows in 2^15 instances, so 30% to 40% of the zerocheck's instances are copies of one padding compression. The packed witness is instance-major and the zerocheck binds the lowest variables first, so while a round binds bits inside an instance (or inside a group of whole instances), every padding group has the same round polynomial and the same folded tables.
  • What: flock::reduction::Instance gains live, the instances before the identical tail. The zerocheck kernels (Round 1's univariate skip, the paired and storing bit passes, the paired table passes) sum the live head as before, run once on the last group, and add it weighted by the tail's eq mass, which is one plus the mass below the head (a logarithmic number of products). The storing passes copy the last group over the tail, so later rounds see whole tables. HashBatch sets live to its row count; class_flock::prove_reductions finds each RISC-V batch's tail in its committed z (reduction::live_instances).
  • Why it is correct: the round message is linear in the instances' contributions, and every instance past live contributes the same polynomial times its eq weight, so their sum is the last group's polynomial times the sum of their eq weights. The folded tables of identical groups are identical, so copying the last one gives the tables the full pass would write. A new flock test pins the proof of a batch told of its tail to one not told, with tails at block, step and task boundaries, mid-block, past every step, and at block 0.
  • Measured alone at 1T on f774828d: first-level node 973 to 902 ms (-7.2%), node 1041 to 952 ms (-8.5%); the flock reduction 249 to 170 ms and 237 to 147 ms. The leanXMSS 100 leaf 0.999 to 0.971 s. At 32 threads within noise (the zerocheck span 17.4 to 13.5 ms).

2. The tree's dense claim reduction runs over the live prefix, with factored weights and fused rounds

Branch kw/agg1-densefuse (0d2c7e0f, on f774828d).

  • Why: on the node, the dense reduction is a degree-two sumcheck of the fixed polynomial (2^22 entries) against a full weight table, with a products pass and two fold passes per round: 70 ms at 1T and 24 ms at 32T, memory bound.
  • What: the weight table is zero past the blocks its terms touch (1.45M of 4.2M entries), so each round works on that prefix; the boundary entry is the polynomial's value on its dyadic block (an mle_eval_par of the table). Terms of a block that share their low coordinates form a group; with at most two groups per block the weights stay factored (a low eq table times a high entry) for the first rounds and are never written out at full size. Each round folds tile by tile and builds the next message from the folded tile while it is in L1. The matrix reduction's rounds fold and build their message in one pass too.
  • Why it is correct: entries past the prefix carry zero weight and add nothing to any message, and the boundary entry keeps the final evaluations exact. A new test reduces claims with odd prefixes and with both factored and written-out parts against the reference reduction.
  • Measured alone at 1T on f774828d: Reduce claims 25.7 to 13.2 ms (first-level node) and 85.4 to 25.4 ms (node); node 1042 to 985 ms (-5.5%), first-level node 973 to 965 ms. At 32T, Reduce claims 9.0 to 6.3 ms and 35.1 to 12.9 ms.

3. A deep NTT task covers at least 64 rows

Branch kw/agg1-ntt-tasks (b4af9163, on f774828d).

  • Why: the last WHIR level's extension commit encodes 4 message rows at rate 2^13. Its deep NTT pass cut 8192 tasks of 4 rows, and the Merkle builder, handed 4 leaves at a time (below a 32-leaf hash batch), hashed them one by one: that level took 21.3 ms at 1T against 8.6 ms for the level before it, which is twice its size.
  • What: upstream's AdditiveNttF64::transform gives each deep task 2^MIN_TASK_LOG (64) rows of contiguous sub-blocks and hands them to the Merkle builder at once. Only encodes whose deep sub-blocks hold fewer than 64 rows change: in leanXMSS 100 that is the last WHIR level (4-row sub-blocks, now 16 to a task), while the base commit's sub-blocks hold 2^10 rows and run as in the base.
  • Why it is correct: each sub-block still runs the same layers with the same twiddles; a task only runs several of them in order, so the codeword and the tree are unchanged.
  • Measured alone at 1T on f774828d: the level-4 commit 21.3 to 3.4 ms; first-level node 972 to 955 ms, node 1039 to 1019 ms; the leanXMSS 100 leaf 1011 to 994 ms (its last WHIR level has the same shape). At 32T, first-level node 152 to 145 ms, node 174 to 170 ms.
  • Related: pcs: a cheaper commit NTT plan when few workers run #464: pcs: a cheaper commit NTT plan when few workers run #464 (open) changes the deep pass of the same transform; it adds the Message enum (rows or lanes) and its few-worker plan. This branch carries this change on upstream's NTT alone. The two compose: the grouped deep pass matches on pcs: a cheaper commit NTT plan when few workers run #464's Message::Rows, and a lane-major message never reaches the deep pass. Whichever of the two lands second takes that resolution.

4. Small pools keep the opening's weight from its first pass

Branch kw/agg1-openweight (21cc3b39, on f774828d).

  • Why: the stacked opening's lifted weight (the point claims' eq tables plus the ring-switch map) is filled twice per proof: by the first pass and again by the first lane fold.
  • What: with at most 4 workers (KEEP_WEIGHT_MAX_THREADS), the first pass also writes each filled chunk into a dense buffer, which the first fold reads as Basis::Dense. Larger pools keep refilling, which is cheaper there (2T -9/-6 ms, 4T -3/-3 ms, 32T +5 to +7 ms when kept).
  • Why it is correct: the kept buffer holds the values the fold would compute again; a test pins the kept weight to the filled one.
  • Measured alone at 1T on f774828d: first pass 79 to 89 ms, first lane fold 73 to 44 ms, PCS open 289 to 270 ms; first-level node 978 to 960 ms, node 1046 to 1025 ms; the leanXMSS 100 leaf 1.002 to 0.986 s. 32T unchanged (the gate is off).
  • Memory trade: on 1 to 4 workers this keeps 24 bytes per committed word: the aggregation process peak went from 1.02 to 1.31 GiB at 1T, and the leanXMSS 100 prover from 0.83 to 1.08 GiB. The gate was measured on one x86 machine only.

5. A tree proves and reads with the fixed columns it built once

Branch kw/agg1-fixed (7e875365, on f774828d).

  • Why: Tree::new already builds each circuit's fixed columns, but Circuit::prove and verify_to_raw (once per child in prove_node) rebuilt them, a serial pass over every slot of every table.
  • What: Circuit::prove_with and Circuit::verify_to_raw_with take the tree's columns; Circuit::prove and verify_to_raw keep building their own.
  • Why it is correct: the columns are a function of the circuit alone, and the tree's are built from the same circuit.
  • Measured alone on f774828d: FixedColumns::of was 0.5% of a first-level node's proof and 1.2% of a node's in a sampled profile (about 5 and 12 ms at 1T); end to end at 1T inside run-to-run noise. At 32T, where the pass is serial, the node 174/180 to 167/170 ms.

6. The HASH rows' packed witness is generated straight into the stack

Branch kw/agg1-hashwit (af9403dc, on #463 at ddbef89c).

Combined result

Measured in the study on f774828d with the six changes plus #463, #464 and #465 (one thread, quiet host, medians of 3 alternating rounds of --repeat 3):

--n 100 first-level node 1T node 1T first-level node 32T node 32T leanXMSS 100 leaf 1T
upstream f774828d 974 ms 1041 ms 146 ms 174 ms 1001 ms
+ #463, #464, #465 814 ms 881 ms 143 ms 174 ms 836 ms
+ #463, #464, #465 and the six changes 686 ms 677 ms 126 ms 122 ms 767 ms

That is -30% on the first-level node and -35% on the node at one thread, and the same at 400 signatures (first-level node 974 to 700 ms, node 1043 to 678 ms). The changes' gains add up: the five without #463/#464/#465 took the first-level node to 857 ms and the node to 844 ms.

CI's bench comment on dc24a752 (this branch merged into its base, against the base 556206d7, which includes #463 and #523, so these numbers measure the six changes alone; base and PR run in turns on one runner, 5 rounds each, medians with the rounds' range):

x86-64 (AMD EPYC 7763)

benchmark base this PR change
aggregate-leanxmss-100-2to1-first 856.83 ms 731.45 ms -15.04% (-15.83% to -14.47%)
aggregate-leanxmss-100-2to1-node 925.88 ms 772.97 ms -16.71% (-16.91% to -16.13%)
aggregate-leanxmss-100-2to1-1thread-first 1.69 s 1.45 s -13.92% (-14.41% to -13.76%)
aggregate-leanxmss-100-2to1-1thread-node 1.80 s 1.53 s -15.11% (-15.25% to -14.10%)
aggregate-leanxmss-100-4to1-first 1.72 s 1.45 s -15.35% (-15.54% to -15.02%)
aggregate-leanxmss-100-4to1-node 1.90 s 1.60 s -15.78% (-16.10% to -11.83%)
leanxmss-100 (leaf) 1.49 s 1.34 s -9.93% (-14.81% to -9.83%)
leanxmss-100-1thread (leaf) 2.99 s 2.69 s -10.27% (-10.87% to -10.04%)

arm64 (Neoverse-N2)

benchmark base this PR change
aggregate-leanxmss-100-2to1-first 510.26 ms 420.95 ms -17.57% (-20.76% to -17.33%)
aggregate-leanxmss-100-2to1-node 570.94 ms 446.01 ms -21.86% (-26.93% to -18.05%)
aggregate-leanxmss-100-2to1-1thread-first 1.81 s 1.49 s -17.80% (-18.29% to -17.41%)
aggregate-leanxmss-100-2to1-1thread-node 1.92 s 1.56 s -18.44% (-19.14% to -18.17%)
aggregate-leanxmss-100-4to1-first 1.02 s 837.13 ms -18.00% (-22.58% to -17.79%)
aggregate-leanxmss-100-4to1-node 1.13 s 910.21 ms -19.87% (-20.28% to -19.58%)
leanxmss-100 (leaf) 874.34 ms 762.57 ms -12.78% (-13.16% to -7.45%)
leanxmss-100-1thread (leaf) 3.30 s 2.80 s -15.19% (-15.98% to -12.91%)
  • Against the previous head 12b931df, which contained pcs: a cheaper commit NTT plan when few workers run #464 (same bench, each against its own base run): the x86-64 single-thread cases lose the most. On x86-64 the 2-to-1 single-thread first-level node goes from -16.42% to -13.92% and its node from -18.72% to -15.11% (those two ran on an Intel Xeon Platinum 8573C before and an EPYC 7763 now); on an EPYC 7763 both times, leanxmss-100-1thread goes from -11.53% to -10.27%, its commit stage from -5.33% to +1.73% against the base, and the 4-to-1 nodes from -16.11%/-16.41% to -15.35%/-15.78%. On arm64 the 2-to-1 single-thread nodes go from -18.18%/-19.12% to -17.80%/-18.44%, leanxmss-100-1thread from -13.67% to -15.19%, and its commit stage from -2.50% to -0.11%. The multi-thread aggregation and leanXMSS cases move by less than 1.8 points either way.
  • In the stages, the nodes' Reduce claims falls by 66% to 72% (2-to-1 node at 1T on x86-64: 154.70 to 51.75 ms) and the first-level nodes' by 40% to 60%; Prove recursion falls by 8% to 18%. In the RISC-V proving cases, pcs-open falls by 13% to 29%, and build-witness stays within 1.4% of the base. Their commit stage is within 0.7% of the base on arm64 and 0.5% to 1.7% above it on x86-64; the base commit runs the base's NTT plan (in leanXMSS 100 its deep sub-blocks hold 2^10 rows, so section 3 leaves them alone).
  • The other proving benchmarks fall too: Fibonacci 2M -6.53% (x86-64) and -11.84% (arm64), falcon-7 -7.72% and -12.03%, leansphincs-26 -10.66% and -13.41%, hash-50000 -11.20% and -14.13%, shielded-258 -13.01% and -16.68%, stateproof-5 -12.73% and -15.06%, and the flock batches -4.6% to -13.0%.
  • Verifying time of the tree proofs falls 23% to 60%; on x86-64 the verifying of falcon-7 rose 1.38% and of leanxmss-100-1thread 1.63%.
  • Memory: on the x86-64 runner the peak resident memory rose 15% to 34% on the RISC-V proving cases (leanxmss-100: 784.20 to 1022.22 MiB), 24% on the 4-to-1 nodes (1226.15 to 1515.41 MiB) and 3.1% to 3.8% on the 2-to-1 cases; on arm64 no peak moved. heap-peak fell on the aggregation cases (10.3% on x86-64, 4.35% on arm64). The kept opening weight (section 4) is the change that adds a buffer, on pools of at most 4 workers; see its memory trade.
  • allocations rose by 4.2% on the 2-to-1 node, 2.15% on the 4-to-1 node, and 1.05% to 3.1% on the RISC-V proving cases.

#464 taken out

dc24a752 takes #464 out of this branch. pcs/src/ntt/additive_ntt_f64.rs, pcs/src/ntt.rs and pcs/src/whir/commit.rs, the only files #464 changes, are upstream's at 556206d7 again. That also drops #464's AVX-512 register kernels, with the register version of upstream's transposed butterfly an earlier merge had added for them. Section 3's deep-task grouping is applied again onto upstream's transform, as it was first written on f774828d (the patch applies unchanged). Nothing else in the branch used #464.

Fitting the current upstream

This branch merges riscv-exploration at 556206d7 with plain merge commits: c4997182 (upstream at c0a6aab3), 57ecea24 (4189283c) and 12b931df (556206d7); dc24a752 then takes #464 out (above). Upstream since the earlier merges:

Merge with current upstream (earlier)

The prototypes were built on f774828d; an earlier merge brought riscv-exploration at 72ea1121 (after #465, #498, #493, #491, #492, #485 and others), then #463, #464 and kw/agg1-hashwit, with plain merge commits.

A later merge brought upstream to 468c67cd (#503 to #517). Upstream's flock Instance owns its witness, while #463 and section 6 write z straight into the committed column: the merged Instance borrows z and carries live, and a new flock::Tables holds the rest of a witness. #463's word-level generators plug into upstream's Fill. #464's AVX-512 NTT register kernels stayed then, with a register version of upstream's transposed butterfly (both gone with #464 since dc24a752). Circuit::prove and verify_to_raw are test-only now.

Checks

  • Byte identity: the serialized proofs (hashed by a scratch CLI patch, not committed) of this branch's head dc24a752 and of upstream at 556206d7 are identical for leanXMSS 400 and 100, Fibonacci 2M at --log-inv-rate 1, leanDA 1, and cargo leanvm aggregate --n 100 --leaves 4 --arity0 2 --arity 2 (the leaf at rate 1/4, the first-level node and the node), at 1 and 32 workers, built natively (Zen 4, AVX-512) and with -C target-cpu=haswell. Earlier heads matched upstream the same way (12b931df against 556206d7, also at --n 400; 57ecea24 against 4189283c; c4997182 against c0a6aab3).
  • On dc24a752: cargo test --release -p pcs (43 tests) natively, with each of CI's SIMD flag sets (x86-64-v3 with +gfni,+vpclmulqdq,+pclmulqdq,+aes, x86-64-v3 with +vpclmulqdq,+pclmulqdq), with haswell, and for aarch64 (neoverse-n2 with +aes,+sha3) under qemu-aarch64-static; cargo test --release -p leanvm_core --lib (203 tests) and -p flock -p primitives -p fiat_shamir (103 tests) natively.
  • cargo test --release -p leanvm_core --test verifiers: 29 passed, 3 ignored (the same #[ignore] tests as upstream).
  • cargo fmt --all --check; cargo clippyall with haswell flags on Rust 1.97 and 1.99 and natively on 1.99; the AVX-512 clippy step and the ARM64 clippy leg (neoverse-n2, --target aarch64-unknown-linux-gnu); cargo docall.
  • CI on dc24a752: every job passed, cargo testall included.

- mul_lanes_avx512: the reduction's spill is one vpshufb lookup of the top
  nibble and g(x) takes doublings, so fewer ops share the shift/shuffle
  pipes with the unpacks (VPCLMULQDQ zmm issues every other cycle on Zen 4).
- radix-8 and radix-4 groups keep their rows in registers: each row is
  loaded and stored once per group, not once per layer.
- run_layers puts the leftover one or two layers first (largest blocks)
  and walks twiddles block to block with one XOR (TwiddleWalk) instead
  of a subset sum per block; twiddles_radix8 is gone.

Byte-identical: fibonacci 2M rate 1 digest 87a8a891167e3b9a, leanxmss 400
744c5cfc65b1157d. cargo test --release -p pcs passes.

1T (LEANVM_NUM_THREADS=1, taskset -c 2), base / this, two runs each:
  leanxmss 400: Commit 602, 601 -> 580, 572 ms; PCS open Commit L1-L4
    380, 381 -> 349, 349 ms; Prove 5500, 5490 -> 5470, 5390 ms.
  fibonacci 2M: Commit 1160, 1150 -> 1110 ms (other run disturbed, load 11);
    L1-L4 798, 796 -> 746 ms.
  Kernel probe, 48 lanes in L1: 0.343 -> 0.308 ns per lane-butterfly.
32T leanxmss 400: Commit 67.6, 66.9 -> 65.6, 71.7 ms (second run had every
  stage slower, machine noise); proving unchanged within noise.
…s the lane-major stack in place

- With one worker (gated on the planned worker count; 32 threads keep the
  old plan) a gathered group takes up to 64 adjacent residues: they share
  every twiddle, so the group is one transform of R*n lanes, its copies in
  and out are R*n-word runs (whole lines, so streaming stores stop
  splitting lines) and the 41- or 35-lane scalar tail disappears.
  LONE_GATHER_WORDS bounds the scratch (32 MiB).
- encode_lane_major_with: commit no longer transposes the stack into the
  codeword. When the first gathered pass takes >= 8 residues, it reads
  each lane's 8-word lines straight from the lane-major message and turns
  8x8 blocks around in registers (gather_lanes, AVX-512). Otherwise
  (32T, small domains, other targets) it transposes first as before.
- transform_for takes the worker count, so tests pin the one-worker plan.

Byte-identical (same digests). cargo test --release -p pcs passes; tests
cover the lone plan for in-place, no-message and lane-major encodes.
Measured together with the next commit (see there).
…ctor for 2-7 spare lanes

- gather_lanes walks one lane octet's lines front to back (8 lines per
  lane per row group), which halves the lane-major read time at 1T.
- Rows ending in 2 to 7 lanes past a whole vector (fibonacci's 35 lanes)
  take one masked vector in separate #[inline(never)] sweeps; folding the
  mask into the common loop cost the whole-vector shapes about 5%.

Byte-identical: fibonacci 2M 87a8a891167e3b9a, leanxmss 400
744c5cfc65b1157d. cargo test --release -p pcs passes.

This and the previous two commits, 1T, base / this, A B A B:
  leanxmss 400: Commit 606, 608 -> 484, 484 ms; L1-L4 378, 378 -> 360, 350;
    Prove 5480, 5430 -> 5370, 5320 ms.
  fibonacci 2M: Commit 1150, 1150 -> 835, 830 ms; L1-L4 795, 797 -> 731, 730;
    Prove 9180, 9250 -> 8900, 8850 ms.
32T leanxmss 400 (--repeat 3): Commit 68.4, 67.5 -> 66.5, 67.3 ms; proving
  0.556, 0.568 -> 0.559, 0.578 s (+-2 to 4% spreads): unchanged.
Probe (1T, xmss shape, commit alone): transpose 50 + gathered in 39 + out 50
  ms became gathered in 45 + out 22 ms.
With one worker the deep pass takes fit3 rows whenever the plan has a
gathered pass: its L3 is its own, a deep layer costs about the same from
L3 as from L2, and the smaller gathered groups read the lane-major stack
faster. 32T planning is unchanged.

Probe (1T, encode + Merkle alone): leanxmss base commit 482 -> 459 ms,
its L1 extension commit 236 -> 231 ms, fibonacci's L1 493 -> 472 ms
(fibonacci's base commit already took fit3).

Byte-identical: fibonacci 2M 87a8a891167e3b9a, leanxmss 400
744c5cfc65b1157d. cargo test --release -p pcs passes.

All four commits, 1T, base / this, A B A B:
  leanxmss 400: Commit 604, 607 -> 464, 523 ms (second run noisy);
    L1-L4 378, 377 -> 342, 344 ms; Prove 5470, 5460 -> 5260, 5400 ms.
  fibonacci 2M: Commit 1170, 1160 -> 837, 898 ms; L1-L4 794, 809 -> 706,
    709 ms; Prove 10100 (disturbed), 9370 -> 8830, 8890 ms.
32T leanxmss 400: Commit 66.6, 71.4 -> 66.8, 68.7 ms; proving 0.558, 0.58
  -> 0.572, 0.629 s (last run +-21.7%, load 6.8): no change beyond noise.
pcs throughput bench, 1T, PCS_LOG_N=22 (load 7 to 11): commit 47.9, 63.6
  -> 43.0, 42.8 ms; encode alone 29.7, 33.7 -> 25.6, 24.7 ms.
…k circuits; HASH's unrolled

ALU, LOAD, STORE, LD, SD and SHIFT (`ClassSpec::witness`) and every clock circuit (`Clock::witness`) now write their packed witness by word arithmetic instead of the 64-lane walk of their gate list. Each generator computes the circuit's values natively and writes its rows in the order the circuit makes its products through `rv::circuits::Products`, which keeps each table's current word in a register and stores it once full. ALU's 192 interleaved logic rows go through `Products::push_interleaved3` (BMI2 `pdep`, with a portable spread elsewhere). DIV, EXT, and MUL off AVX2 still walk.

HASH's generator was already word arithmetic, but it ORed each carry run into the tables at a slot read from a table the circuit build recorded. It is now unrolled by a macro: every run's place is a constant, so the rows are written with no branch and no read, and the recorded runs (`CARRIES`) are gone. A run starts above bit 0 only on round 0's first `c + d` of a column G, whose `c` is still the IV.

`class_flock::Prepared::build` still asserts that every output port of every instance is what the interpreter computed.

Tests: `semantics::tests::word_witness_is_the_walk` checks ALU, LOAD, STORE, LD, SD and SHIFT on a grid of edge instances (every legal flag word; zero, one, all ones and the sign bits in every operand; every shift amount from 0 to 64 and all ones, with and without high bits; every byte offset of a cell, so every misalignment of every width; cells with every byte's sign bit set or clear) plus 4096 random ones (half decoder-shaped, half edge-biased words in every port, flags included). Each instance is compared alone with the bit-by-bit walk, then the whole batch's packed tables and lincheck stripes with the 64-lane walk. The clock's test covers every table's clock circuit and one with all 32 slots on 4096 rows (padding, first and last cycle, all ones, random; previous timestamps around the row's, live bit flipped, zero, all ones, random); HASH's covers all-zero, all-ones and sign-bit blocks and edge counters. Mutations (a dropped carry, a wrong fill bit, a wrong sign bit, the clock's top carry, a short HASH carry run) each fail their test. The portable spread is tested with target-cpu=x86-64-v2.

Byte-identical proofs: serialized proof digests equal to the base's for leanxmss 400, fibonacci 2M and leanda 1 blob, at 1 and 32 threads.

Measured on a Ryzen 9 7950X3D, shared host, base (77077c6) and this commit alternated, `--tracing`, loads 3.4 to 12.6:

One thread (LEANVM_NUM_THREADS=1, taskset -c 2):
  leanxmss 400   Build flock witnesses 390, 398 -> 209, 212 ms   proving 5.448, 5.475 -> 5.286, 5.298 s
  fibonacci 2M   Build flock witnesses 571, 577 -> 297, 309 ms   proving 9.191, 9.225 -> 8.961, 8.921 s
  leanda 1 blob  Build flock witnesses 426, 425 -> 262, 261 ms   proving 5.633, 5.670 -> 5.486, 5.508 s
32 threads:
  leanxmss 400   Build flock witnesses 47.4, 49.4 -> 47.2, 47.0 ms   proving 0.558, 0.561 -> 0.588, 0.576 s
  fibonacci 2M   Build flock witnesses 71.2, 71.4 -> 70.8, 69.1 ms   proving 0.923, 0.923 -> 0.931, 0.947 s
  leanda 1 blob  Build flock witnesses 52.4, 51.5 -> 50.2, 49.3 ms   proving 0.601, 0.587 -> 0.600, 0.600 s
At 32 threads the span and the proving totals stay within the run to run spread; `--repeat 3` runs at load under 10: leanxmss 0.557 to 0.566 s for the base and 0.559 to 0.601 s for this commit, fibonacci 0.906 to 0.942 s and 0.913 to 0.932 s.
…s committed column

The generators now take the destination for z (`Circuit::generate_witness_{from,with,batched}_into`, the allocating forms wrapping them through `witness::with_z`), and the driver shows each instance's z to a `check` closure while its group is still in the worker's scratch. `Prepared::build` passes the class's window of the committed stack as z and checks every output port against the interpreter there, so the second pass that reread z, checked the ports and copied z into the window is gone, and `Prepared` no longer keeps its own copy of z: `Prepared::prove` reads it from the stack.

Byte-identical proofs: serialized proof digests equal to the base's for leanxmss 400, fibonacci 2M and leanda 1 blob, at 1 and 32 threads. Tests: cargo test --release -p flock, the word-witness pins and leanvm_core's suite.

Measured on a Ryzen 9 7950X3D, shared host at load 3 to 12, the previous commit and this one alternated.

32 threads, --repeat 3, proving:
  leanxmss 400   0.559, 0.564 -> 0.545, 0.545 s
  fibonacci 2M   0.927, 0.926 -> 0.879, 0.882 s
  leanda 1 blob  0.602, 0.607 -> 0.576, 0.587 s
32 threads, --tracing:
  leanxmss 400   Build flock witnesses 49.4, 46.6 -> 26.6, 27.7 ms   Flock reductions 122, 122 -> 117, 134 ms
  fibonacci 2M   Build flock witnesses 70.1, 69.5 -> 38.5, 39.3 ms   Flock reductions 159, 166 -> 168, 164 ms
  leanda 1 blob  Build flock witnesses 50.3, 50.7 -> 31.6, 30.2 ms   Flock reductions 116, 113 -> 118, 114 ms
One thread, --tracing (LEANVM_NUM_THREADS=1, taskset -c 2):
  leanxmss 400   Build flock witnesses 211 -> 188 ms   proving 5.265 -> 5.256 s
  fibonacci 2M   Build flock witnesses 290 -> 274 ms   proving 8.910 -> 8.857 s
  leanda 1 blob  Build flock witnesses 261 -> 242 ms   proving 5.518 -> 5.512 s
Peak memory: leanxmss 3.00 -> 2.75 GiB (32 threads), 2.91 -> 2.66 GiB (one); leanda 3.22 -> 2.95, 3.13 -> 2.86 GiB; fibonacci 4.70 -> 4.81, 4.67 -> 4.79 GiB.
The plan with wide gathered groups (up to 64 adjacent residues), the L3 deep pass and the lane-major stack read in place now runs whenever the transform is planned for at most FEW_WORKERS = 2 workers, not one alone. The tests plan for 1, 2 and 3 workers, so both sides of the gate are pinned to the scalar reference whatever the pool's size.

Gate, measured on a Ryzen 9 7950X3D (workers pinned to the 32 MiB L3 CCD), Commit span of the base encode, one-worker gate / the plan at every count, two runs each:
  2 workers (2 cores):        leanxmss 400 307, 287 -> 281, 245 ms; leanda 305, 329 -> 263, 255 ms; fibonacci 2M 549 -> 467, 511 ms
  4 workers (2 cores + SMT):  leanxmss 220, 216 -> 232, 234 ms; fibonacci 406, 408 -> 455, 447 ms; leanda 235, 235 -> 238, 264 ms
  4 workers (4 cores):        leanxmss 148, 147 -> 164, 180 ms; leanda 157, 182 -> 193, 166 ms
  8 workers (8 cores):        leanxmss 92.5, 87.2 -> 132, 133 ms; leanda 116, 128 -> 141, 141 ms
  32 workers, pcs throughput bench PCS_LOG_N=24 rate 1: commit 24.4, 24.0 -> 30.8, 30.9 ms; encode alone 16.5, 16.3 -> 24.6, 24.6 ms
Three workers were not measured and keep the narrow plan.

This branch against upstream 77077c6, Commit span (base encode), runs base -> this:
  1 worker:   leanxmss 601, 613, 613 -> 533, 472, 458 ms; fibonacci 1160, 1150, 1150 -> 846, 836, 850 ms; leanda 646, 663, 648 -> 484, 493, 497 ms
  2 workers:  leanxmss 279, 312, 312 -> 326, 260, 262 ms; fibonacci 550, 540, 540 -> 452, 461, 457 ms; leanda 335, 334, 336 -> 266, 281, 276 ms
  4 workers (2 cores + SMT, the narrow plan): leanxmss 260, 259 -> 238, 238 ms; fibonacci 462, 473 -> 434, 429 ms; leanda 286, 257 -> 262, 260 ms
  8 workers:  leanxmss 92.7, 91.0 -> 90.3, 90.7 ms; fibonacci 171, 171 -> 163, 164 ms; leanda 98.7, 98.4 -> 99.2, 92.4 ms
  32 workers: leanxmss 67.0, 67.3 -> 65.6, 64.9 ms; fibonacci 125, 120 -> 121, 119 ms; leanda 69.9, 71.3 -> 69.2, 69.9 ms

Byte-identical proofs: leanxmss 400, fibonacci 2M and leanda 1 hash to the same digest on base and branch at every worker count. cargo test --release -p pcs passes, natively (AVX-512), with target-cpu=znver3 (the AVX2 arm) and on aarch64 under qemu.
The stacked opening's lifted weight was filled twice per proof: once by the first pass (the Basis span) and again by the first lane fold (Sumcheck round 4), each fill paying the ring-switch map (apply_sliced_add), the point claims' eq tables and the scatter. On a pool of at most KEEP_WEIGHT_MAX_THREADS (4) workers the first pass now also streams each filled chunk into a dense buffer, and the first fold reads that back as Basis::Dense instead of filling it again. On a larger pool the refill, spread over the workers, costs less than writing the weight out and reading it back, so that path is unchanged. Proofs are byte-identical.

Measured on a 7950X3D, cargo leanvm aggregate --n 100 --leaves 4 --arity0 2 --arity 2 --repeat 3 --cooldown 1, AGG1_NOTREE, pooled per-pass medians (min) over alternating base/branch rounds, loads 1 to 12:

  1T (5 rounds a side, taskset -c 2)
    first-level node  base 0.978 s (0.969)  branch 0.960 s (0.954)  -1.8%
    node              base 1.046 s (1.035)  branch 1.025 s (1.018)  -2.0%
  32T (3 rounds a side, gate off)
    first-level node  base 0.148 s (0.144)  branch 0.148 s (0.143)
    node              base 0.175 s (0.169)  branch 0.174 s (0.169)

Spans at 1T (tracing, one pass): first-level node Basis 79.0 -> 89.1 ms, Sumcheck round 4 73.1 -> 43.9 ms, PCS open 289 -> 270 ms; node Basis 76.9 -> 89.2 ms, round 4 72.4 -> 43.8 ms, PCS open 292 -> 275 ms; leaf Basis 100 -> 113 ms, round 4 84.8 -> 47.6 ms.

Crossover (PCS open, store vs refill, tracing): 2T -9 and -6 ms, 4T -3 and -3 ms, 32T +5 to +7 ms, which sets the gate at 4.

Peak memory at 1T grows by the kept weight (24 bytes per committed word): aggregate 1.02 -> 1.31 GiB, leanxmss --n 100 0.83 -> 1.08 GiB. leanxmss --n 100 at 1T: 1.002 -> 0.986 s (pooled per-pass medians, 3 rounds a side).
A high-rate encode of a short message (the last WHIR level: 4 message rows,
rate 2^13) cut its deep pass into one task per 4-row sub-block, so the Merkle
builder got 4 leaves per call, short of a hash batch, and hashed them one by
one. A task now runs 2^MIN_TASK_LOG rows of contiguous sub-blocks and hands
them over at once. The rows, the codeword and the tree are unchanged.

Measured on the 7950X3D (aggregate --n 100 --leaves 4, 2 alternating rounds,
--repeat 3, load under 10), upstream f774828 vs this:
- level-4 extension commit at 1T: 21.3 ms -> 3.4 ms (span tree)
- 1T first-level node 972 -> 955 ms, node 1039 -> 1019 ms, leanXMSS-100
  leaf 1011 -> 994 ms
- 32T first-level node 152 -> 145 ms, node 174 -> 170 ms
Proof digests unchanged (leaf, first-level node, node).
Tree::new already builds each circuit's fixed columns. Proving a node
(prove_rows) and reading a child (read, which prove_node calls for every
child and verify calls for the root) built them again through
TableArgument::of, a serial pass over every slot of every table. They now
take the tree's columns (Circuit::prove_with, Circuit::verify_to_raw_with);
Circuit::prove and verify_to_raw still build their own.

Measured on the 7950X3D, upstream f774828 vs this, aggregate --n 100:
- sampled profile at 1T: FixedColumns::of is 0.51% of a first-level node
  proof (about 5 ms) and 1.19% of a node proof (about 12 ms: the prover's
  build and one per child read)
- 32T, 2 alternating rounds: node 174/180 -> 167/170 ms; first-level node
  152/149 -> 145/152 ms (within noise)
- 1T end to end is within the run-to-run noise of these rounds (host
  load 4 to 13)
Proof digests unchanged (leaf, first-level node, node).
On top of leanEthereum#463's generate_witness_with_into: HashBatch writes z into the
stack's packed-witness window and copies each live row's 18 port words into
the port buffers while the row is in cache (the padding rows' ports are one
fill afterwards), so the 2^15-instance z (64 MiB) is neither allocated nor
copied into the stack, and the ports are no longer gathered by 18 strided
passes over it. The flock reduction reads z from the stack.

Measured on the 7950X3D, leanEthereum#463 (ddbef89) vs this, aggregate --n 100, 1T:
- Build witness span 43.3/43.4 -> 38.0/38.6 ms (first-level node and node,
  2 traced runs each)
- end to end at 1T within noise (load 2 to 12); 32T first-level node
  155/152 -> 139/153 ms, node 172/188 -> 166/185 ms
Proof digests unchanged (leaf, first-level node, node).
…ghts, fused rounds

The node's dense reduction was a degree-two sumcheck over the whole fixed polynomial (2^22 entries) against a full weight table, each round a products pass and two fold passes. Prover only; the transcript, the verifier and every proof byte are unchanged.

- Live prefix. The weight table is zero past the blocks its terms touch (about 1.45M of the node's 4.2M entries), so every round folds and sums that prefix alone. Where the prefix's last entry pairs with one past it, that entry is the polynomial's value on its block at the challenges so far, an `mle_eval_par` of the table as given; those blocks partition the rest of the table, so the final value is still exact.
- Factored weights. Terms of one block sharing their low coordinates are one group (each of the node's blocks has two terms at one point, so one group). While every block has at most two groups, the weight table is never written out: a round sums each block's low table against the table's run, then scales by the high entry, until the low tables are bound (10 rounds); then it is written out once at that level and folded from there. Otherwise (the first level's bytecode, 18 groups) it is written out at the start, in one pass with the first message.
- Fused rounds. Each round folds the table (and the weights once written) tile by tile and builds the next round's message from the folded tile in L1, with `mul4`, `mul_base8` and unreduced `mul_unreduced4` sums reduced once per message.
- The matrix reduction's row and column rounds fold and build the next message in one pass the same way (`FoldTable::fold_pair`).
- `round(i)` is now `message()`, the message the last bind built.

A new test reduces claims whose blocks leave a prefix odd at several rounds, with factored and written-out parts, and checks the verifier accepts and the values are the polynomials'.

Measured on the 7950X3D, `aggregate --n 100 --leaves 4 --arity0 2 --arity 2 --repeat 3`, AGG1_NOTREE, alternating base (f774828) and branch runs; "proving" means of 3 passes, runs with 1-minute load above 20 or a disturbed pass dropped (loads in parentheses).

1T (taskset -c 2):
- first-level node: base 0.973 s (9.1), 0.991 s (6.5), 0.972 s (9.9), median 0.973 s; branch 0.971 s (13.7), 0.958 s (10.7), median 0.965 s
- node: base 1.042 s (9.1), 1.052 s (6.5), 1.039 s (9.9), median 1.042 s; branch 0.993 s (13.7), 0.975 s (10.7), and per-pass medians 0.990 s, 0.980 s of two runs with one disturbed pass each, median 0.985 s (-5.5%)

32T:
- first-level node: base 0.149 s (9.6), 0.153 s (11.6), 0.160 s (13.7), median 0.153 s; branch 0.149 s (10.8), 0.149 s (10.1), 0.158 s (13.7), median 0.149 s
- node: base 0.176 s (9.6), 0.203 s (11.6), 0.192 s (13.7), median 0.192 s; branch 0.156 s (10.8), 0.155 s (10.1), 0.169 s (13.7), median 0.156 s

Spans (--tracing, one pass), base then branch:
- 1T first-level: Reduce claims 25.7 to 13.2 ms (Dense reduction 17.2 to 5.25 ms, Matrix reduction 8.55 to 7.90 ms)
- 1T node: Reduce claims 85.4 to 25.4 ms (Dense reduction 70.7 to 12.0 ms, Matrix reduction 14.7 to 13.3 ms)
- 32T first-level: Reduce claims 8.99 to 6.33 ms (Dense reduction 2.61 to 0.99 ms)
- 32T node: Reduce claims 35.1 to 12.9 ms (Dense reduction 25.6 to 4.53 ms, Matrix reduction 9.47 to 8.35 ms)

Digests equal base at --n 100 (leaf 1ddc4572a71ec2af, first 6cc4ab4bf8ee46b7, node d0d2b1643bb63a90) and --n 400 (leaf 9311cba19de1b111, first cac5d72e17c200f1, node bc70f47ff4643d4b).
A batch padded to a power of two ends in copies of one padding instance: the recursion machine's HASH table (about 20k to 23k live rows of 2^15) and every RISC-V table's fill rows. The zerocheck binds the lowest variables first, so while it binds bits inside an instance (or inside a group of instances), every group past the live ones has the same per-round polynomial and the same folded tables. The prover now sums the head (the live instances, rounded up to the kernel's unit of work) as before, sums the cube's last group once, and adds it weighted by the tail's eq mass, sum_{g >= head} eq(r_groups, g), which is one plus the mass below the head and costs O(log) products. Field arithmetic is exact, so every message is unchanged and the proof bytes are identical.

- `PaddingSpec::live_blocks` and `PaddingSpec::tail` split a kernel's cube at the tail; a group is a block, or enough whole blocks for the kernel's smallest cube, so small circuits and rounds that bind instance bits split too.
- Round 1 (univariate skip), the paired bit passes, the storing bit pass and the paired table passes take the split; the storing and table passes write the last group in place and copy it over the tail, so the stored tables stay whole and the single-round tail is untouched.
- `reduction::Instance::live` carries the count; `HashBatch` sets it to its row count, and `class_flock::prove_reductions` detects each RISC-V batch's tail from its packed `z` (`reduction::live_instances`). The verifier and the proof are unchanged.
- Test: `an_identical_tail_changes_no_word` pins the proof stream and claims of a batch told of its tail to the one not told, with random live instances and identical tails starting at block 0, mid step, mid task and past every step, over shapes reaching every kernel (both table-pass arities included).

Measured on the 7950X3D, `aggregate --n 100 --leaves 4 --arity0 2 --arity 2 --repeat 3 --cooldown 1` with AGG1_NOTREE=1, proving time (mean of 3 passes), base f774828:

| node kind, threads  | base runs        | branch runs             | median change |
| ------------------- | ---------------- | ----------------------- | ------------- |
| first-level, 1T     | 0.971, 0.974 s   | 0.907, 0.900, 0.902 s   | -7.2%         |
| node, 1T            | 1.041, 1.041 s   | 0.952, 0.952, 0.951 s   | -8.5%         |
| first-level, 32T    | 0.150, 0.147 s   | 0.144, 0.143 s          | -3% (noise)   |
| node, 32T           | 0.174, 0.175 s   | 0.173, 0.171 s          | -1.5% (noise) |

Spreads 0.1% to 2.2% at 1T, 1.4% to 4.7% at 32T; loads 2.7 to 4.9 at start. An earlier pair of 1T rounds at loads 1 to 5 gave base 0.973, 0.977 / 1.038, 1.043 s.

Span tree, 1T, one tracing pass each: first-level Flock reduction 249 -> 170 ms (Round 1 91.8 -> 57.9, Rounds 149 -> 104, Lincheck 8.6 unchanged), node 237 -> 147 ms (Round 1 79.4 -> 50.4, Rounds 149 -> 88.1). HASH holds 22,871 (first-level) and 19,665 (node) live rows of 32,768.

Leaf, `leanxmss --n 100 --repeat 3 --cooldown 1`: 1T base 1.009, 1.041, 0.999 s, branch 0.989, 0.973, 0.971 s (clean pair 0.999 -> 0.971, -2.8%); 32T base 0.141, 0.145 s, branch 0.144, 0.143 s. Its Flock reductions span 250 -> 222 ms at 1T.

Digests unchanged at n = 100 (leaf 1ddc4572a71ec2af, first 6cc4ab4bf8ee46b7, node d0d2b1643bb63a90) and n = 400 (leaf 9311cba19de1b111, first cac5d72e17c200f1, node bc70f47ff4643d4b).
# Conflicts:
#	crates/flock/src/zerocheck.rs
#	crates/flock/src/zerocheck/multilinear.rs
# Conflicts:
#	crates/leanvm_core/src/class_flock.rs
# Conflicts:
#	crates/pcs/src/ntt/additive_ntt_f64.rs
# Conflicts:
#	crates/leanvm_core/src/rec/proof.rs
@kevaundray

Copy link
Copy Markdown
Collaborator Author

Opening this to mainly collect a bunch of different unmerged optimisations to see their diff. (Some of them in isolation only give a marginal change)

On my server, I get numbers so also want to see if they are reproducible on the github CI

@kevaundray

Copy link
Copy Markdown
Collaborator Author

Also not clear we want all or any of these

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Benchmarks: base against this PR, on one runner

dc24a75 merged into its base, against the base 556206d: each benchmark run in turns on one runner, base and PR 5 times each. A size is shown when it changed; a time or a peak memory when it moved the same way in every round and its median by at least 1% (the change is the median ratio, with the rounds' range).

Proving time

benchmark runner base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 1.81 s 1.49 s -17.80% (-18.29% to -17.41%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 1.69 s 1.45 s -13.92% (-14.41% to -13.76%)
aggregate-leanxmss-100-2to1-1thread-node arm64 1.92 s 1.56 s -18.44% (-19.14% to -18.17%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 1.80 s 1.53 s -15.11% (-15.25% to -14.10%)
aggregate-leanxmss-100-2to1-first arm64 510.26 ms 420.95 ms -17.57% (-20.76% to -17.33%)
aggregate-leanxmss-100-2to1-first x86-64 856.83 ms 731.45 ms -15.04% (-15.83% to -14.47%)
aggregate-leanxmss-100-2to1-node arm64 570.94 ms 446.01 ms -21.86% (-26.93% to -18.05%)
aggregate-leanxmss-100-2to1-node x86-64 925.88 ms 772.97 ms -16.71% (-16.91% to -16.13%)
aggregate-leanxmss-100-4to1-first arm64 1.02 s 837.13 ms -18.00% (-22.58% to -17.79%)
aggregate-leanxmss-100-4to1-first x86-64 1.72 s 1.45 s -15.35% (-15.54% to -15.02%)
aggregate-leanxmss-100-4to1-node arm64 1.13 s 910.21 ms -19.87% (-20.28% to -19.58%)
aggregate-leanxmss-100-4to1-node x86-64 1.90 s 1.60 s -15.78% (-16.10% to -11.83%)
falcon-7 arm64 3.22 s 2.83 s -12.03% (-12.20% to -10.56%)
falcon-7 x86-64 5.48 s 5.06 s -7.72% (-8.14% to -7.55%)
fibonacci-asm-2000000 arm64 4.97 s 4.38 s -11.84% (-13.17% to -11.60%)
fibonacci-asm-2000000 x86-64 8.45 s 7.90 s -6.53% (-7.54% to -6.10%)
flock-add-wrapping-batch-262144 arm64 83.41 ms 74.58 ms -10.51% (-10.79% to -9.27%)
flock-add-wrapping-batch-262144 x86-64 137.16 ms 130.69 ms -4.71% (-5.88% to -2.42%)
flock-hash-batch-262144 arm64 5.00 s 4.41 s -12.11% (-12.30% to -11.47%)
flock-hash-batch-262144 x86-64 8.41 s 8.00 s -4.75% (-4.92% to -4.32%)
flock-mul-widening-batch-262144 arm64 2.24 s 1.95 s -12.97% (-13.30% to -12.53%)
flock-mul-widening-batch-262144 x86-64 3.91 s 3.73 s -4.56% (-6.06% to -3.90%)
flock-mul-wrapping-batch-262144 arm64 1.20 s 1.06 s -12.01% (-12.24% to -11.56%)
flock-mul-wrapping-batch-262144 x86-64 2.06 s 1.96 s -4.80% (-7.13% to -3.76%)
hash-50000 arm64 3.18 s 2.70 s -14.13% (-16.00% to -13.78%)
hash-50000 x86-64 5.38 s 4.76 s -11.20% (-11.57% to -10.48%)
leansphincs-26 arm64 1.01 s 873.93 ms -13.41% (-14.13% to -9.01%)
leansphincs-26 x86-64 1.71 s 1.53 s -10.66% (-10.92% to -5.46%)
leanxmss-100 arm64 874.34 ms 762.57 ms -12.78% (-13.16% to -7.45%)
leanxmss-100 x86-64 1.49 s 1.34 s -9.93% (-14.81% to -9.83%)
leanxmss-100-1thread arm64 3.30 s 2.80 s -15.19% (-15.98% to -12.91%)
leanxmss-100-1thread x86-64 2.99 s 2.69 s -10.27% (-10.87% to -10.04%)
shielded-258 arm64 4.54 s 3.78 s -16.68% (-18.17% to -16.47%)
shielded-258 x86-64 7.69 s 6.69 s -13.01% (-13.73% to -12.70%)
stateproof-5 arm64 7.30 s 6.20 s -15.06% (-15.32% to -14.53%)
stateproof-5 x86-64 10.79 s 9.43 s -12.73% (-13.13% to -12.22%)
Prover stages
benchmark runner base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 1.81 s 1.49 s -17.80% (-18.29% to -17.41%)
 ↳ build-circuit 16.68 ms 16.61 ms -0.25% (-2.34% to +0.22%)
 ↳ prove-recursion 1.74 s 1.44 s -17.23% (-17.73% to -16.87%)
 ↳ reduce-claims 49.50 ms 26.36 ms -46.79% (-46.95% to -46.29%)
 ↳ reduce-in-rows 2.08 ms 2.00 ms -5.23% (-5.68% to -1.66%)
 ↳ verify 8.90 ms 8.80 ms -1.11% (-1.72% to +0.76%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 1.69 s 1.45 s -13.92% (-14.41% to -13.76%)
 ↳ build-circuit 22.19 ms 21.44 ms -3.24% (-5.28% to +1.44%)
 ↳ prove-recursion 1.61 s 1.39 s -13.38% (-13.85% to -13.26%)
 ↳ reduce-claims 47.71 ms 28.48 ms -40.31% (-40.69% to -40.01%)
 ↳ reduce-in-rows 1.83 ms 1.86 ms +1.71% (-0.65% to +7.27%)
 ↳ verify 9.19 ms 9.27 ms +0.70% (+0.06% to +1.26%)
aggregate-leanxmss-100-2to1-1thread-node arm64 1.92 s 1.56 s -18.44% (-19.14% to -18.17%)
 ↳ build-circuit 14.93 ms 14.92 ms -0.38% (-0.67% to +1.19%)
 ↳ prove-recursion 1.73 s 1.49 s -14.09% (-14.83% to -13.73%)
 ↳ reduce-claims 152.00 ms 49.33 ms -67.54% (-68.03% to -67.38%)
 ↳ reduce-in-rows 1.84 ms 1.84 ms -0.93% (-3.68% to +1.74%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 1.80 s 1.53 s -15.11% (-15.25% to -14.10%)
 ↳ build-circuit 17.72 ms 17.96 ms +0.70% (-3.76% to +2.14%)
 ↳ prove-recursion 1.61 s 1.45 s -9.95% (-10.13% to -8.85%)
 ↳ reduce-claims 154.70 ms 51.75 ms -66.57% (-66.67% to -66.16%)
 ↳ reduce-in-rows 1.72 ms 1.83 ms +6.27% (+1.79% to +13.21%)
aggregate-leanxmss-100-2to1-first arm64 510.26 ms 420.95 ms -17.57% (-20.76% to -17.33%)
 ↳ build-circuit 12.36 ms 12.21 ms -1.47% (-5.00% to -1.10%)
 ↳ prove-recursion 469.80 ms 389.40 ms -17.18% (-20.70% to -16.98%)
 ↳ reduce-claims 17.21 ms 8.68 ms -49.77% (-50.06% to -48.69%)
 ↳ reduce-in-rows 2.12 ms 2.03 ms -4.41% (-8.67% to -2.86%)
 ↳ verify 8.69 ms 8.67 ms -0.48% (-2.20% to +1.23%)
aggregate-leanxmss-100-2to1-first x86-64 856.83 ms 731.45 ms -15.04% (-15.83% to -14.47%)
 ↳ build-circuit 17.55 ms 17.62 ms -0.80% (-9.07% to +1.16%)
 ↳ prove-recursion 800.59 ms 686.45 ms -14.57% (-15.23% to -13.93%)
 ↳ reduce-claims 28.12 ms 15.57 ms -44.62% (-48.85% to -41.84%)
 ↳ reduce-in-rows 1.90 ms 2.01 ms +4.51% (-12.19% to +6.16%)
 ↳ verify 9.16 ms 9.15 ms +0.03% (-0.81% to +1.82%)
aggregate-leanxmss-100-2to1-node arm64 570.94 ms 446.01 ms -21.86% (-26.93% to -18.05%)
 ↳ build-circuit 13.39 ms 13.06 ms -2.31% (-4.51% to -0.45%)
 ↳ prove-recursion 488.21 ms 406.33 ms -16.63% (-23.25% to -12.69%)
 ↳ reduce-claims 49.17 ms 16.71 ms -65.93% (-67.87% to -65.00%)
 ↳ reduce-in-rows 1.92 ms 1.88 ms -2.11% (-5.12% to +7.45%)
aggregate-leanxmss-100-2to1-node x86-64 925.88 ms 772.97 ms -16.71% (-16.91% to -16.13%)
 ↳ build-circuit 17.44 ms 17.07 ms -2.22% (-5.21% to +3.81%)
 ↳ prove-recursion 800.49 ms 713.29 ms -10.89% (-11.12% to -10.34%)
 ↳ reduce-claims 86.44 ms 29.01 ms -66.22% (-67.17% to -64.06%)
 ↳ reduce-in-rows 1.82 ms 1.93 ms +6.51% (+3.22% to +9.26%)
aggregate-leanxmss-100-4to1-first arm64 1.02 s 837.13 ms -18.00% (-22.58% to -17.79%)
 ↳ build-circuit 25.84 ms 25.97 ms +0.55% (-0.57% to +2.42%)
 ↳ prove-recursion 945.01 ms 777.50 ms -17.61% (-22.51% to -17.41%)
 ↳ reduce-claims 28.89 ms 11.64 ms -59.74% (-60.33% to -59.38%)
 ↳ reduce-in-rows 4.35 ms 4.31 ms -0.76% (-3.19% to -0.21%)
 ↳ verify 17.30 ms 17.32 ms -0.04% (-0.46% to +2.03%)
aggregate-leanxmss-100-4to1-first x86-64 1.72 s 1.45 s -15.35% (-15.54% to -15.02%)
 ↳ build-circuit 37.86 ms 37.85 ms -0.27% (-2.02% to +3.81%)
 ↳ prove-recursion 1.61 s 1.37 s -14.70% (-14.79% to -14.45%)
 ↳ reduce-claims 47.84 ms 20.43 ms -57.33% (-58.37% to -56.10%)
 ↳ reduce-in-rows 3.56 ms 3.74 ms +4.85% (+3.54% to +6.66%)
 ↳ verify 18.16 ms 18.14 ms -0.17% (-1.07% to +1.97%)
aggregate-leanxmss-100-4to1-node arm64 1.13 s 910.21 ms -19.87% (-20.28% to -19.58%)
 ↳ build-circuit 31.29 ms 31.19 ms -0.13% (-1.79% to +2.94%)
 ↳ prove-recursion 945.96 ms 826.89 ms -12.52% (-12.81% to -12.28%)
 ↳ reduce-claims 100.76 ms 28.51 ms -71.72% (-74.13% to -71.50%)
 ↳ reduce-in-rows 3.96 ms 3.95 ms -0.01% (-2.17% to +0.87%)
aggregate-leanxmss-100-4to1-node x86-64 1.90 s 1.60 s -15.78% (-16.10% to -11.83%)
 ↳ build-circuit 44.80 ms 44.36 ms -0.63% (-4.05% to +3.67%)
 ↳ prove-recursion 1.61 s 1.47 s -8.47% (-8.77% to -3.65%)
 ↳ reduce-claims 176.19 ms 50.61 ms -71.15% (-71.44% to -70.12%)
 ↳ reduce-in-rows 3.59 ms 3.78 ms +4.15% (+3.38% to +9.48%)
falcon-7 arm64 3.22 s 2.83 s -12.03% (-12.20% to -10.56%)
 ↳ build-witness 90.38 ms 90.26 ms +0.10% (-0.62% to +0.15%)
 ↳ commit 516.65 ms 517.68 ms +0.20% (+0.04% to +0.80%)
 ↳ execute-program 35.22 ms 35.14 ms -0.31% (-0.57% to +0.20%)
 ↳ flock-reductions 968.21 ms 912.57 ms -5.81% (-5.89% to -0.74%)
 ↳ pcs-open 1.40 s 1.07 s -23.89% (-24.04% to -23.50%)
 ↳ prove-bus 180.14 ms 180.47 ms +0.25% (-0.10% to +0.47%)
 ↳ prove-constraints 23.95 ms 23.85 ms -0.50% (-1.44% to +0.51%)
falcon-7 x86-64 5.48 s 5.06 s -7.72% (-8.14% to -7.55%)
 ↳ build-witness 131.73 ms 131.99 ms +0.16% (-0.48% to +0.45%)
 ↳ commit 896.62 ms 910.01 ms +1.44% (+0.53% to +1.72%)
 ↳ execute-program 43.92 ms 43.37 ms -1.25% (-9.61% to +14.65%)
 ↳ flock-reductions 2.15 s 1.95 s -8.93% (-9.43% to -8.53%)
 ↳ pcs-open 1.86 s 1.61 s -13.41% (-13.91% to -12.88%)
 ↳ prove-bus 358.99 ms 364.59 ms +1.57% (+1.38% to +2.26%)
 ↳ prove-constraints 42.26 ms 42.25 ms -0.59% (-2.83% to +0.18%)
fibonacci-asm-2000000 arm64 4.97 s 4.38 s -11.84% (-13.17% to -11.60%)
 ↳ build-witness 135.72 ms 136.08 ms +0.25% (-0.48% to +1.21%)
 ↳ commit 814.09 ms 812.89 ms +0.05% (-1.09% to +0.24%)
 ↳ execute-program 66.38 ms 66.62 ms +0.37% (-1.43% to +1.54%)
 ↳ flock-reductions 1.57 s 1.56 s -0.48% (-0.89% to -0.09%)
 ↳ pcs-open 2.04 s 1.46 s -28.59% (-30.75% to -28.23%)
 ↳ prove-bus 311.49 ms 310.67 ms -0.26% (-0.45% to -0.16%)
 ↳ prove-constraints 40.73 ms 40.83 ms +0.10% (-0.60% to +2.74%)
fibonacci-asm-2000000 x86-64 8.45 s 7.90 s -6.53% (-7.54% to -6.10%)
 ↳ build-witness 249.49 ms 252.79 ms +1.38% (-1.07% to +2.34%)
 ↳ commit 1.43 s 1.45 s +1.40% (+0.39% to +2.27%)
 ↳ execute-program 80.11 ms 84.58 ms +5.41% (-21.36% to +9.97%)
 ↳ flock-reductions 3.47 s 3.30 s -4.70% (-5.85% to -3.88%)
 ↳ pcs-open 2.53 s 2.11 s -16.75% (-17.40% to -16.38%)
 ↳ prove-bus 623.39 ms 633.61 ms +1.64% (-0.04% to +2.17%)
 ↳ prove-constraints 74.14 ms 73.33 ms -1.13% (-1.52% to -0.21%)
hash-50000 arm64 3.18 s 2.70 s -14.13% (-16.00% to -13.78%)
 ↳ build-witness 92.51 ms 93.02 ms +1.05% (-0.55% to +1.17%)
 ↳ commit 523.16 ms 526.31 ms +0.65% (-0.00% to +8.57%)
 ↳ execute-program 26.34 ms 27.01 ms +1.60% (-0.05% to +4.57%)
 ↳ flock-reductions 941.76 ms 808.67 ms -14.09% (-14.91% to -13.52%)
 ↳ pcs-open 1.43 s 1.08 s -24.09% (-26.32% to -22.11%)
 ↳ prove-bus 144.84 ms 145.25 ms +0.22% (-3.20% to +0.64%)
 ↳ prove-constraints 20.10 ms 20.14 ms +1.23% (-1.17% to +2.18%)
hash-50000 x86-64 5.38 s 4.76 s -11.20% (-11.57% to -10.48%)
 ↳ build-witness 155.47 ms 156.54 ms +0.81% (-0.73% to +7.64%)
 ↳ commit 897.40 ms 909.98 ms +1.48% (+1.17% to +3.54%)
 ↳ execute-program 31.56 ms 31.41 ms +3.69% (-15.68% to +10.42%)
 ↳ flock-reductions 2.12 s 1.74 s -18.04% (-18.69% to -17.70%)
 ↳ pcs-open 1.84 s 1.60 s -12.78% (-13.57% to -12.07%)
 ↳ prove-bus 282.81 ms 287.70 ms +1.70% (+1.27% to +1.89%)
 ↳ prove-constraints 33.48 ms 33.31 ms -0.62% (-3.59% to +0.63%)
leansphincs-26 arm64 1.01 s 873.93 ms -13.41% (-14.13% to -9.01%)
 ↳ build-witness 23.79 ms 23.66 ms -0.55% (-5.99% to +1.23%)
 ↳ commit 147.96 ms 147.58 ms +0.08% (-0.26% to +0.83%)
 ↳ execute-program 12.66 ms 12.81 ms +0.18% (-0.54% to +1.72%)
 ↳ flock-reductions 321.74 ms 288.13 ms -10.27% (-10.80% to -9.87%)
 ↳ pcs-open 430.55 ms 327.63 ms -24.24% (-25.17% to -13.69%)
 ↳ prove-bus 64.81 ms 65.17 ms +0.35% (-0.18% to +0.70%)
 ↳ prove-constraints 9.84 ms 9.86 ms +0.36% (-0.22% to +1.08%)
leansphincs-26 x86-64 1.71 s 1.53 s -10.66% (-10.92% to -5.46%)
 ↳ build-witness 44.67 ms 44.25 ms -0.95% (-3.08% to +1.29%)
 ↳ commit 262.57 ms 265.98 ms +1.27% (+1.14% to +1.87%)
 ↳ execute-program 15.46 ms 15.70 ms +1.68% (-3.63% to +1.93%)
 ↳ flock-reductions 696.73 ms 601.27 ms -13.69% (-14.52% to -13.58%)
 ↳ pcs-open 549.81 ms 459.64 ms -16.32% (-17.31% to +0.23%)
 ↳ prove-bus 124.07 ms 125.61 ms +1.27% (+0.96% to +1.71%)
 ↳ prove-constraints 14.62 ms 14.61 ms +0.06% (-0.86% to +1.37%)
leanxmss-100 arm64 874.34 ms 762.57 ms -12.78% (-13.16% to -7.45%)
 ↳ build-witness 19.88 ms 19.77 ms -0.32% (-2.38% to +0.54%)
 ↳ commit 124.73 ms 124.59 ms -0.10% (-0.28% to +1.13%)
 ↳ execute-program 11.09 ms 11.10 ms -0.68% (-1.03% to +1.91%)
 ↳ flock-reductions 279.37 ms 254.75 ms -9.00% (-9.43% to +2.47%)
 ↳ pcs-open 374.30 ms 286.52 ms -23.47% (-24.30% to -23.00%)
 ↳ prove-bus 55.97 ms 56.27 ms +0.57% (-0.17% to +22.79%)
 ↳ prove-constraints 8.42 ms 8.37 ms -0.57% (-0.71% to +24.55%)
leanxmss-100 x86-64 1.49 s 1.34 s -9.93% (-14.81% to -9.83%)
 ↳ build-witness 37.61 ms 37.57 ms -0.16% (-0.39% to +0.38%)
 ↳ commit 224.84 ms 228.29 ms +1.64% (-0.11% to +1.71%)
 ↳ execute-program 13.13 ms 13.31 ms +1.53% (-1.63% to +2.79%)
 ↳ flock-reductions 603.03 ms 525.92 ms -12.91% (-19.26% to -11.89%)
 ↳ pcs-open 492.46 ms 413.83 ms -16.08% (-21.49% to -15.46%)
 ↳ prove-bus 106.42 ms 108.25 ms +1.63% (+1.54% to +1.82%)
 ↳ prove-constraints 12.23 ms 12.30 ms +0.59% (-1.80% to +1.34%)
leanxmss-100-1thread arm64 3.30 s 2.80 s -15.19% (-15.98% to -12.91%)
 ↳ build-witness 72.86 ms 71.97 ms -1.32% (-1.87% to +2.60%)
 ↳ commit 493.21 ms 492.99 ms -0.11% (-0.67% to +0.37%)
 ↳ execute-program 10.97 ms 10.91 ms -0.53% (-0.82% to +2.13%)
 ↳ flock-reductions 1.06 s 939.63 ms -11.59% (-11.68% to -10.82%)
 ↳ pcs-open 1.44 s 1.06 s -26.40% (-27.62% to -21.61%)
 ↳ prove-bus 202.81 ms 202.51 ms -0.08% (-1.11% to +1.15%)
 ↳ prove-constraints 21.37 ms 21.34 ms -0.04% (-1.52% to +1.06%)
leanxmss-100-1thread x86-64 2.99 s 2.69 s -10.27% (-10.87% to -10.04%)
 ↳ build-witness 83.58 ms 83.14 ms -0.54% (-0.97% to +0.38%)
 ↳ commit 478.95 ms 487.37 ms +1.73% (+1.42% to +4.87%)
 ↳ execute-program 13.05 ms 13.17 ms +0.87% (-8.63% to +2.17%)
 ↳ flock-reductions 1.20 s 1.04 s -13.84% (-14.59% to -13.38%)
 ↳ pcs-open 987.02 ms 833.21 ms -15.86% (-16.96% to -15.13%)
 ↳ prove-bus 207.25 ms 210.07 ms +1.34% (+0.82% to +2.06%)
 ↳ prove-constraints 21.64 ms 21.74 ms +0.50% (-1.05% to +3.36%)
shielded-258 arm64 4.54 s 3.78 s -16.68% (-18.17% to -16.47%)
 ↳ build-witness 114.69 ms 114.22 ms -0.32% (-1.36% to -0.14%)
 ↳ commit 743.62 ms 743.79 ms +0.02% (-1.20% to +0.37%)
 ↳ execute-program 65.81 ms 65.86 ms +0.46% (-2.81% to +0.95%)
 ↳ flock-reductions 1.42 s 1.16 s -17.52% (-18.75% to -17.33%)
 ↳ pcs-open 1.86 s 1.35 s -27.43% (-29.33% to -26.90%)
 ↳ prove-bus 310.35 ms 310.38 ms -0.17% (-0.39% to +0.66%)
 ↳ prove-constraints 34.62 ms 34.77 ms +0.64% (-1.43% to +1.18%)
shielded-258 x86-64 7.69 s 6.69 s -13.01% (-13.73% to -12.70%)
 ↳ build-witness 208.46 ms 207.75 ms -0.25% (-1.57% to +3.40%)
 ↳ commit 1.28 s 1.30 s +1.55% (+1.23% to +1.93%)
 ↳ execute-program 77.72 ms 81.32 ms +1.63% (-5.10% to +12.29%)
 ↳ flock-reductions 3.12 s 2.45 s -21.59% (-22.78% to -21.37%)
 ↳ pcs-open 2.32 s 1.96 s -15.41% (-15.81% to -14.53%)
 ↳ prove-bus 613.49 ms 623.64 ms +1.73% (-1.62% to +2.15%)
 ↳ prove-constraints 61.78 ms 61.18 ms -1.00% (-28.85% to -0.45%)
stateproof-5 arm64 7.30 s 6.20 s -15.06% (-15.32% to -14.53%)
 ↳ build-witness 187.31 ms 186.77 ms -0.32% (-0.71% to +0.03%)
 ↳ commit 1.22 s 1.22 s -0.13% (-0.69% to +0.04%)
 ↳ execute-program 87.84 ms 87.13 ms -0.01% (-1.76% to +1.53%)
 ↳ flock-reductions 2.19 s 1.82 s -16.84% (-17.47% to -14.62%)
 ↳ pcs-open 3.08 s 2.35 s -23.76% (-23.96% to -23.35%)
 ↳ prove-bus 476.79 ms 476.83 ms +0.01% (-0.67% to +0.40%)
 ↳ prove-constraints 58.41 ms 58.48 ms -0.02% (-0.30% to +0.60%)
stateproof-5 x86-64 10.79 s 9.43 s -12.73% (-13.13% to -12.22%)
 ↳ build-witness 318.51 ms 318.04 ms +0.15% (-2.07% to +3.84%)
 ↳ commit 1.62 s 1.63 s +0.46% (-0.75% to +2.58%)
 ↳ execute-program 124.27 ms 124.19 ms +0.11% (-1.39% to +1.00%)
 ↳ flock-reductions 4.46 s 3.68 s -17.48% (-17.88% to -16.99%)
 ↳ pcs-open 3.41 s 2.80 s -17.90% (-18.57% to -17.35%)
 ↳ prove-bus 785.20 ms 787.01 ms +0.26% (-0.14% to +0.80%)
 ↳ prove-constraints 93.49 ms 92.93 ms -1.30% (-2.87% to +1.48%)

Verifying time

benchmark runner base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 10.74 ms 7.02 ms -34.60% (-35.45% to -34.52%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 12.62 ms 7.70 ms -38.63% (-40.31% to -37.55%)
aggregate-leanxmss-100-2to1-1thread-node arm64 16.70 ms 12.98 ms -22.72% (-23.38% to -21.18%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 20.78 ms 15.77 ms -24.22% (-26.03% to -22.48%)
aggregate-leanxmss-100-2to1-first arm64 8.76 ms 4.72 ms -46.12% (-47.50% to -44.74%)
aggregate-leanxmss-100-2to1-first x86-64 11.36 ms 6.32 ms -44.17% (-45.34% to -43.52%)
aggregate-leanxmss-100-2to1-node arm64 10.15 ms 6.41 ms -39.08% (-41.97% to -35.53%)
aggregate-leanxmss-100-2to1-node x86-64 15.71 ms 10.53 ms -32.53% (-33.25% to -31.87%)
aggregate-leanxmss-100-4to1-first arm64 13.96 ms 5.61 ms -59.81% (-60.63% to -59.32%)
aggregate-leanxmss-100-4to1-first x86-64 17.82 ms 7.70 ms -56.73% (-57.31% to -56.58%)
aggregate-leanxmss-100-4to1-node arm64 18.06 ms 8.95 ms -50.65% (-56.61% to -49.56%)
aggregate-leanxmss-100-4to1-node x86-64 26.67 ms 16.13 ms -39.48% (-40.89% to -39.36%)
falcon-7 x86-64 5.37 ms 5.44 ms +1.38% (+0.28% to +2.17%)
leanxmss-100-1thread x86-64 5.07 ms 5.15 ms +1.63% (+0.54% to +1.99%)

Peak memory

benchmark runner base this PR change
aggregate-leanxmss-100-2to1-1thread-first x86-64 1142.24 MiB 1184.42 MiB +3.68% (+3.66% to +3.85%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 1142.24 MiB 1184.42 MiB +3.68% (+3.66% to +3.85%)
aggregate-leanxmss-100-2to1-first x86-64 1169.10 MiB 1213.23 MiB +3.84% (+3.23% to +4.07%)
aggregate-leanxmss-100-2to1-node x86-64 1185.19 MiB 1220.20 MiB +3.11% (+2.73% to +3.32%)
aggregate-leanxmss-100-4to1-first x86-64 1209.55 MiB 1502.11 MiB +24.33% (+23.71% to +24.90%)
aggregate-leanxmss-100-4to1-node x86-64 1226.15 MiB 1515.41 MiB +23.67% (+23.42% to +24.09%)
falcon-7 x86-64 3070.30 MiB 3532.27 MiB +15.05% (+14.71% to +15.11%)
fibonacci-asm-2000000 x86-64 4076.34 MiB 5447.41 MiB +33.65% (+33.57% to +33.77%)
hash-50000 x86-64 2922.95 MiB 3380.61 MiB +15.66% (+15.33% to +15.78%)
leansphincs-26 x86-64 916.41 MiB 1192.66 MiB +30.36% (+30.08% to +30.44%)
leanxmss-100 x86-64 784.20 MiB 1022.22 MiB +30.35% (+30.09% to +30.65%)
leanxmss-100-1thread x86-64 770.14 MiB 1006.19 MiB +30.64% (+30.00% to +31.01%)
shielded-258 x86-64 4154.67 MiB 5408.12 MiB +30.15% (+30.10% to +30.37%)
stateproof-5 x86-64 6091.15 MiB 8067.14 MiB +32.44% (+32.33% to +32.49%)

allocations

benchmark runner base this PR change
aggregate-leanxmss-100-2to1-1thread-node arm64 26.13 µs 27.23 µs +4.21% (+4.21% to +4.21%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 26.15 µs 27.25 µs +4.20% (+4.20% to +4.20%)
aggregate-leanxmss-100-2to1-node arm64 26.23 µs 27.33 µs +4.19% (+4.15% to +4.19%)
aggregate-leanxmss-100-2to1-node x86-64 26.25 µs 27.34 µs +4.19% (+4.19% to +4.19%)
aggregate-leanxmss-100-4to1-node arm64 48.81 µs 49.86 µs +2.15% (+2.15% to +2.15%)
aggregate-leanxmss-100-4to1-node x86-64 48.82 µs 49.87 µs +2.15% (+2.13% to +2.15%)
falcon-7 arm64 14.38 µs 14.75 µs +2.59% (+2.59% to +2.60%)
falcon-7 x86-64 14.60 µs 15.01 µs +2.80% (+2.80% to +2.80%)
fibonacci-asm-2000000 arm64 11.02 µs 11.22 µs +1.82% (+1.81% to +1.84%)
fibonacci-asm-2000000 x86-64 11.24 µs 11.54 µs +2.70% (+2.69% to +2.71%)
hash-50000 arm64 15.09 µs 15.54 µs +2.97% (+2.97% to +2.97%)
hash-50000 x86-64 15.33 µs 15.80 µs +3.08% (+3.07% to +3.08%)
leansphincs-26 arm64 24.32 µs 24.68 µs +1.48% (+1.48% to +1.51%)
leansphincs-26 x86-64 24.57 µs 24.98 µs +1.65% (+1.65% to +1.65%)
leanxmss-100 arm64 24.95 µs 25.32 µs +1.46% (+1.31% to +1.46%)
leanxmss-100 x86-64 25.20 µs 25.61 µs +1.60% (+1.60% to +1.63%)
leanxmss-100-1thread arm64 24.68 µs 25.05 µs +1.47% (+1.47% to +1.47%)
leanxmss-100-1thread x86-64 24.93 µs 25.33 µs +1.62% (+1.62% to +1.62%)
shielded-258 x86-64 43.85 µs 44.31 µs +1.05% (+1.05% to +1.11%)
stateproof-5 arm64 17.72 µs 18.13 µs +2.29% (+2.29% to +2.29%)
stateproof-5 x86-64 17.97 µs 18.40 µs +2.41% (+2.40% to +2.42%)

heap-peak

benchmark runner base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 772.22 ms 738.67 ms -4.35% (-4.35% to -4.35%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 416.30 ms 373.29 ms -10.33% (-10.33% to -10.33%)
aggregate-leanxmss-100-2to1-1thread-node arm64 771.88 ms 738.32 ms -4.35% (-4.35% to -4.35%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 415.95 ms 372.94 ms -10.34% (-10.34% to -10.34%)
aggregate-leanxmss-100-2to1-first arm64 772.18 ms 738.62 ms -4.34% (-4.35% to -4.34%)
aggregate-leanxmss-100-2to1-first x86-64 416.41 ms 373.33 ms -10.34% (-10.35% to -10.34%)
aggregate-leanxmss-100-2to1-node arm64 771.85 ms 738.28 ms -4.35% (-4.36% to -4.35%)
aggregate-leanxmss-100-2to1-node x86-64 416.04 ms 373.00 ms -10.34% (-10.35% to -10.33%)
aggregate-leanxmss-100-4to1-first arm64 1.54 s 1.48 s -4.34% (-4.35% to -4.34%)
aggregate-leanxmss-100-4to1-first x86-64 832.31 ms 746.26 ms -10.34% (-10.34% to -10.34%)
aggregate-leanxmss-100-4to1-node arm64 1.54 s 1.48 s -4.35% (-4.35% to -4.34%)
aggregate-leanxmss-100-4to1-node x86-64 831.71 ms 745.73 ms -10.34% (-10.35% to -10.32%)
Every result

Proving time

benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 1.81 s 1.49 s -17.80% (-18.29% to -17.41%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 1.69 s 1.45 s -13.92% (-14.41% to -13.76%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 1.92 s 1.56 s -18.44% (-19.14% to -18.17%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 1.80 s 1.53 s -15.11% (-15.25% to -14.10%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 510.26 ms 420.95 ms -17.57% (-20.76% to -17.33%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 856.83 ms 731.45 ms -15.04% (-15.83% to -14.47%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 570.94 ms 446.01 ms -21.86% (-26.93% to -18.05%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 925.88 ms 772.97 ms -16.71% (-16.91% to -16.13%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 1.02 s 837.13 ms -18.00% (-22.58% to -17.79%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 1.72 s 1.45 s -15.35% (-15.54% to -15.02%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 1.13 s 910.21 ms -19.87% (-20.28% to -19.58%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 1.90 s 1.60 s -15.78% (-16.10% to -11.83%)
falcon-7 arm64 Neoverse-N2 3.22 s 2.83 s -12.03% (-12.20% to -10.56%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 5.48 s 5.06 s -7.72% (-8.14% to -7.55%)
fibonacci-asm-2000000 arm64 Neoverse-N2 4.97 s 4.38 s -11.84% (-13.17% to -11.60%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 8.45 s 7.90 s -6.53% (-7.54% to -6.10%)
flock-add-wrapping-batch-262144 arm64 Neoverse-N2 83.41 ms 74.58 ms -10.51% (-10.79% to -9.27%)
flock-add-wrapping-batch-262144 x86-64 AMD EPYC 7763 64-Core Processor 137.16 ms 130.69 ms -4.71% (-5.88% to -2.42%)
flock-hash-batch-262144 arm64 Neoverse-N2 5.00 s 4.41 s -12.11% (-12.30% to -11.47%)
flock-hash-batch-262144 x86-64 AMD EPYC 7763 64-Core Processor 8.41 s 8.00 s -4.75% (-4.92% to -4.32%)
flock-mul-widening-batch-262144 arm64 Neoverse-N2 2.24 s 1.95 s -12.97% (-13.30% to -12.53%)
flock-mul-widening-batch-262144 x86-64 AMD EPYC 7763 64-Core Processor 3.91 s 3.73 s -4.56% (-6.06% to -3.90%)
flock-mul-wrapping-batch-262144 arm64 Neoverse-N2 1.20 s 1.06 s -12.01% (-12.24% to -11.56%)
flock-mul-wrapping-batch-262144 x86-64 AMD EPYC 7763 64-Core Processor 2.06 s 1.96 s -4.80% (-7.13% to -3.76%)
hash-50000 arm64 Neoverse-N2 3.18 s 2.70 s -14.13% (-16.00% to -13.78%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 5.38 s 4.76 s -11.20% (-11.57% to -10.48%)
leansphincs-26 arm64 Neoverse-N2 1.01 s 873.93 ms -13.41% (-14.13% to -9.01%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 1.71 s 1.53 s -10.66% (-10.92% to -5.46%)
leanxmss-100 arm64 Neoverse-N2 874.34 ms 762.57 ms -12.78% (-13.16% to -7.45%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 1.49 s 1.34 s -9.93% (-14.81% to -9.83%)
leanxmss-100-1thread arm64 Neoverse-N2 3.30 s 2.80 s -15.19% (-15.98% to -12.91%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 2.99 s 2.69 s -10.27% (-10.87% to -10.04%)
pcs-commit-22 arm64 Neoverse-N2 45.49 ms 45.68 ms +0.19% (-0.78% to +0.98%)
pcs-commit-22 x86-64 AMD EPYC 7763 64-Core Processor 82.63 ms 82.03 ms -0.86% (-1.43% to +0.14%)
pcs-open-22 arm64 Neoverse-N2 59.82 ms 60.62 ms +1.40% (-0.63% to +1.81%)
pcs-open-22 x86-64 AMD EPYC 7763 64-Core Processor 104.45 ms 104.87 ms -0.15% (-12.68% to +21.09%)
shielded-258 arm64 Neoverse-N2 4.54 s 3.78 s -16.68% (-18.17% to -16.47%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 7.69 s 6.69 s -13.01% (-13.73% to -12.70%)
stateproof-5 arm64 Neoverse-N2 7.30 s 6.20 s -15.06% (-15.32% to -14.53%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 10.79 s 9.43 s -12.73% (-13.13% to -12.22%)
Prover stages
benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 1.81 s 1.49 s -17.80% (-18.29% to -17.41%)
 ↳ build-circuit 16.68 ms 16.61 ms -0.25% (-2.34% to +0.22%)
 ↳ prove-recursion 1.74 s 1.44 s -17.23% (-17.73% to -16.87%)
 ↳ reduce-claims 49.50 ms 26.36 ms -46.79% (-46.95% to -46.29%)
 ↳ reduce-in-rows 2.08 ms 2.00 ms -5.23% (-5.68% to -1.66%)
 ↳ verify 8.90 ms 8.80 ms -1.11% (-1.72% to +0.76%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 1.69 s 1.45 s -13.92% (-14.41% to -13.76%)
 ↳ build-circuit 22.19 ms 21.44 ms -3.24% (-5.28% to +1.44%)
 ↳ prove-recursion 1.61 s 1.39 s -13.38% (-13.85% to -13.26%)
 ↳ reduce-claims 47.71 ms 28.48 ms -40.31% (-40.69% to -40.01%)
 ↳ reduce-in-rows 1.83 ms 1.86 ms +1.71% (-0.65% to +7.27%)
 ↳ verify 9.19 ms 9.27 ms +0.70% (+0.06% to +1.26%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 1.92 s 1.56 s -18.44% (-19.14% to -18.17%)
 ↳ build-circuit 14.93 ms 14.92 ms -0.38% (-0.67% to +1.19%)
 ↳ prove-recursion 1.73 s 1.49 s -14.09% (-14.83% to -13.73%)
 ↳ reduce-claims 152.00 ms 49.33 ms -67.54% (-68.03% to -67.38%)
 ↳ reduce-in-rows 1.84 ms 1.84 ms -0.93% (-3.68% to +1.74%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 1.80 s 1.53 s -15.11% (-15.25% to -14.10%)
 ↳ build-circuit 17.72 ms 17.96 ms +0.70% (-3.76% to +2.14%)
 ↳ prove-recursion 1.61 s 1.45 s -9.95% (-10.13% to -8.85%)
 ↳ reduce-claims 154.70 ms 51.75 ms -66.57% (-66.67% to -66.16%)
 ↳ reduce-in-rows 1.72 ms 1.83 ms +6.27% (+1.79% to +13.21%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 510.26 ms 420.95 ms -17.57% (-20.76% to -17.33%)
 ↳ build-circuit 12.36 ms 12.21 ms -1.47% (-5.00% to -1.10%)
 ↳ prove-recursion 469.80 ms 389.40 ms -17.18% (-20.70% to -16.98%)
 ↳ reduce-claims 17.21 ms 8.68 ms -49.77% (-50.06% to -48.69%)
 ↳ reduce-in-rows 2.12 ms 2.03 ms -4.41% (-8.67% to -2.86%)
 ↳ verify 8.69 ms 8.67 ms -0.48% (-2.20% to +1.23%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 856.83 ms 731.45 ms -15.04% (-15.83% to -14.47%)
 ↳ build-circuit 17.55 ms 17.62 ms -0.80% (-9.07% to +1.16%)
 ↳ prove-recursion 800.59 ms 686.45 ms -14.57% (-15.23% to -13.93%)
 ↳ reduce-claims 28.12 ms 15.57 ms -44.62% (-48.85% to -41.84%)
 ↳ reduce-in-rows 1.90 ms 2.01 ms +4.51% (-12.19% to +6.16%)
 ↳ verify 9.16 ms 9.15 ms +0.03% (-0.81% to +1.82%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 570.94 ms 446.01 ms -21.86% (-26.93% to -18.05%)
 ↳ build-circuit 13.39 ms 13.06 ms -2.31% (-4.51% to -0.45%)
 ↳ prove-recursion 488.21 ms 406.33 ms -16.63% (-23.25% to -12.69%)
 ↳ reduce-claims 49.17 ms 16.71 ms -65.93% (-67.87% to -65.00%)
 ↳ reduce-in-rows 1.92 ms 1.88 ms -2.11% (-5.12% to +7.45%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 925.88 ms 772.97 ms -16.71% (-16.91% to -16.13%)
 ↳ build-circuit 17.44 ms 17.07 ms -2.22% (-5.21% to +3.81%)
 ↳ prove-recursion 800.49 ms 713.29 ms -10.89% (-11.12% to -10.34%)
 ↳ reduce-claims 86.44 ms 29.01 ms -66.22% (-67.17% to -64.06%)
 ↳ reduce-in-rows 1.82 ms 1.93 ms +6.51% (+3.22% to +9.26%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 1.02 s 837.13 ms -18.00% (-22.58% to -17.79%)
 ↳ build-circuit 25.84 ms 25.97 ms +0.55% (-0.57% to +2.42%)
 ↳ prove-recursion 945.01 ms 777.50 ms -17.61% (-22.51% to -17.41%)
 ↳ reduce-claims 28.89 ms 11.64 ms -59.74% (-60.33% to -59.38%)
 ↳ reduce-in-rows 4.35 ms 4.31 ms -0.76% (-3.19% to -0.21%)
 ↳ verify 17.30 ms 17.32 ms -0.04% (-0.46% to +2.03%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 1.72 s 1.45 s -15.35% (-15.54% to -15.02%)
 ↳ build-circuit 37.86 ms 37.85 ms -0.27% (-2.02% to +3.81%)
 ↳ prove-recursion 1.61 s 1.37 s -14.70% (-14.79% to -14.45%)
 ↳ reduce-claims 47.84 ms 20.43 ms -57.33% (-58.37% to -56.10%)
 ↳ reduce-in-rows 3.56 ms 3.74 ms +4.85% (+3.54% to +6.66%)
 ↳ verify 18.16 ms 18.14 ms -0.17% (-1.07% to +1.97%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 1.13 s 910.21 ms -19.87% (-20.28% to -19.58%)
 ↳ build-circuit 31.29 ms 31.19 ms -0.13% (-1.79% to +2.94%)
 ↳ prove-recursion 945.96 ms 826.89 ms -12.52% (-12.81% to -12.28%)
 ↳ reduce-claims 100.76 ms 28.51 ms -71.72% (-74.13% to -71.50%)
 ↳ reduce-in-rows 3.96 ms 3.95 ms -0.01% (-2.17% to +0.87%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 1.90 s 1.60 s -15.78% (-16.10% to -11.83%)
 ↳ build-circuit 44.80 ms 44.36 ms -0.63% (-4.05% to +3.67%)
 ↳ prove-recursion 1.61 s 1.47 s -8.47% (-8.77% to -3.65%)
 ↳ reduce-claims 176.19 ms 50.61 ms -71.15% (-71.44% to -70.12%)
 ↳ reduce-in-rows 3.59 ms 3.78 ms +4.15% (+3.38% to +9.48%)
falcon-7 arm64 Neoverse-N2 3.22 s 2.83 s -12.03% (-12.20% to -10.56%)
 ↳ build-witness 90.38 ms 90.26 ms +0.10% (-0.62% to +0.15%)
 ↳ commit 516.65 ms 517.68 ms +0.20% (+0.04% to +0.80%)
 ↳ execute-program 35.22 ms 35.14 ms -0.31% (-0.57% to +0.20%)
 ↳ flock-reductions 968.21 ms 912.57 ms -5.81% (-5.89% to -0.74%)
 ↳ pcs-open 1.40 s 1.07 s -23.89% (-24.04% to -23.50%)
 ↳ prove-bus 180.14 ms 180.47 ms +0.25% (-0.10% to +0.47%)
 ↳ prove-constraints 23.95 ms 23.85 ms -0.50% (-1.44% to +0.51%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 5.48 s 5.06 s -7.72% (-8.14% to -7.55%)
 ↳ build-witness 131.73 ms 131.99 ms +0.16% (-0.48% to +0.45%)
 ↳ commit 896.62 ms 910.01 ms +1.44% (+0.53% to +1.72%)
 ↳ execute-program 43.92 ms 43.37 ms -1.25% (-9.61% to +14.65%)
 ↳ flock-reductions 2.15 s 1.95 s -8.93% (-9.43% to -8.53%)
 ↳ pcs-open 1.86 s 1.61 s -13.41% (-13.91% to -12.88%)
 ↳ prove-bus 358.99 ms 364.59 ms +1.57% (+1.38% to +2.26%)
 ↳ prove-constraints 42.26 ms 42.25 ms -0.59% (-2.83% to +0.18%)
fibonacci-asm-2000000 arm64 Neoverse-N2 4.97 s 4.38 s -11.84% (-13.17% to -11.60%)
 ↳ build-witness 135.72 ms 136.08 ms +0.25% (-0.48% to +1.21%)
 ↳ commit 814.09 ms 812.89 ms +0.05% (-1.09% to +0.24%)
 ↳ execute-program 66.38 ms 66.62 ms +0.37% (-1.43% to +1.54%)
 ↳ flock-reductions 1.57 s 1.56 s -0.48% (-0.89% to -0.09%)
 ↳ pcs-open 2.04 s 1.46 s -28.59% (-30.75% to -28.23%)
 ↳ prove-bus 311.49 ms 310.67 ms -0.26% (-0.45% to -0.16%)
 ↳ prove-constraints 40.73 ms 40.83 ms +0.10% (-0.60% to +2.74%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 8.45 s 7.90 s -6.53% (-7.54% to -6.10%)
 ↳ build-witness 249.49 ms 252.79 ms +1.38% (-1.07% to +2.34%)
 ↳ commit 1.43 s 1.45 s +1.40% (+0.39% to +2.27%)
 ↳ execute-program 80.11 ms 84.58 ms +5.41% (-21.36% to +9.97%)
 ↳ flock-reductions 3.47 s 3.30 s -4.70% (-5.85% to -3.88%)
 ↳ pcs-open 2.53 s 2.11 s -16.75% (-17.40% to -16.38%)
 ↳ prove-bus 623.39 ms 633.61 ms +1.64% (-0.04% to +2.17%)
 ↳ prove-constraints 74.14 ms 73.33 ms -1.13% (-1.52% to -0.21%)
hash-50000 arm64 Neoverse-N2 3.18 s 2.70 s -14.13% (-16.00% to -13.78%)
 ↳ build-witness 92.51 ms 93.02 ms +1.05% (-0.55% to +1.17%)
 ↳ commit 523.16 ms 526.31 ms +0.65% (-0.00% to +8.57%)
 ↳ execute-program 26.34 ms 27.01 ms +1.60% (-0.05% to +4.57%)
 ↳ flock-reductions 941.76 ms 808.67 ms -14.09% (-14.91% to -13.52%)
 ↳ pcs-open 1.43 s 1.08 s -24.09% (-26.32% to -22.11%)
 ↳ prove-bus 144.84 ms 145.25 ms +0.22% (-3.20% to +0.64%)
 ↳ prove-constraints 20.10 ms 20.14 ms +1.23% (-1.17% to +2.18%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 5.38 s 4.76 s -11.20% (-11.57% to -10.48%)
 ↳ build-witness 155.47 ms 156.54 ms +0.81% (-0.73% to +7.64%)
 ↳ commit 897.40 ms 909.98 ms +1.48% (+1.17% to +3.54%)
 ↳ execute-program 31.56 ms 31.41 ms +3.69% (-15.68% to +10.42%)
 ↳ flock-reductions 2.12 s 1.74 s -18.04% (-18.69% to -17.70%)
 ↳ pcs-open 1.84 s 1.60 s -12.78% (-13.57% to -12.07%)
 ↳ prove-bus 282.81 ms 287.70 ms +1.70% (+1.27% to +1.89%)
 ↳ prove-constraints 33.48 ms 33.31 ms -0.62% (-3.59% to +0.63%)
leansphincs-26 arm64 Neoverse-N2 1.01 s 873.93 ms -13.41% (-14.13% to -9.01%)
 ↳ build-witness 23.79 ms 23.66 ms -0.55% (-5.99% to +1.23%)
 ↳ commit 147.96 ms 147.58 ms +0.08% (-0.26% to +0.83%)
 ↳ execute-program 12.66 ms 12.81 ms +0.18% (-0.54% to +1.72%)
 ↳ flock-reductions 321.74 ms 288.13 ms -10.27% (-10.80% to -9.87%)
 ↳ pcs-open 430.55 ms 327.63 ms -24.24% (-25.17% to -13.69%)
 ↳ prove-bus 64.81 ms 65.17 ms +0.35% (-0.18% to +0.70%)
 ↳ prove-constraints 9.84 ms 9.86 ms +0.36% (-0.22% to +1.08%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 1.71 s 1.53 s -10.66% (-10.92% to -5.46%)
 ↳ build-witness 44.67 ms 44.25 ms -0.95% (-3.08% to +1.29%)
 ↳ commit 262.57 ms 265.98 ms +1.27% (+1.14% to +1.87%)
 ↳ execute-program 15.46 ms 15.70 ms +1.68% (-3.63% to +1.93%)
 ↳ flock-reductions 696.73 ms 601.27 ms -13.69% (-14.52% to -13.58%)
 ↳ pcs-open 549.81 ms 459.64 ms -16.32% (-17.31% to +0.23%)
 ↳ prove-bus 124.07 ms 125.61 ms +1.27% (+0.96% to +1.71%)
 ↳ prove-constraints 14.62 ms 14.61 ms +0.06% (-0.86% to +1.37%)
leanxmss-100 arm64 Neoverse-N2 874.34 ms 762.57 ms -12.78% (-13.16% to -7.45%)
 ↳ build-witness 19.88 ms 19.77 ms -0.32% (-2.38% to +0.54%)
 ↳ commit 124.73 ms 124.59 ms -0.10% (-0.28% to +1.13%)
 ↳ execute-program 11.09 ms 11.10 ms -0.68% (-1.03% to +1.91%)
 ↳ flock-reductions 279.37 ms 254.75 ms -9.00% (-9.43% to +2.47%)
 ↳ pcs-open 374.30 ms 286.52 ms -23.47% (-24.30% to -23.00%)
 ↳ prove-bus 55.97 ms 56.27 ms +0.57% (-0.17% to +22.79%)
 ↳ prove-constraints 8.42 ms 8.37 ms -0.57% (-0.71% to +24.55%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 1.49 s 1.34 s -9.93% (-14.81% to -9.83%)
 ↳ build-witness 37.61 ms 37.57 ms -0.16% (-0.39% to +0.38%)
 ↳ commit 224.84 ms 228.29 ms +1.64% (-0.11% to +1.71%)
 ↳ execute-program 13.13 ms 13.31 ms +1.53% (-1.63% to +2.79%)
 ↳ flock-reductions 603.03 ms 525.92 ms -12.91% (-19.26% to -11.89%)
 ↳ pcs-open 492.46 ms 413.83 ms -16.08% (-21.49% to -15.46%)
 ↳ prove-bus 106.42 ms 108.25 ms +1.63% (+1.54% to +1.82%)
 ↳ prove-constraints 12.23 ms 12.30 ms +0.59% (-1.80% to +1.34%)
leanxmss-100-1thread arm64 Neoverse-N2 3.30 s 2.80 s -15.19% (-15.98% to -12.91%)
 ↳ build-witness 72.86 ms 71.97 ms -1.32% (-1.87% to +2.60%)
 ↳ commit 493.21 ms 492.99 ms -0.11% (-0.67% to +0.37%)
 ↳ execute-program 10.97 ms 10.91 ms -0.53% (-0.82% to +2.13%)
 ↳ flock-reductions 1.06 s 939.63 ms -11.59% (-11.68% to -10.82%)
 ↳ pcs-open 1.44 s 1.06 s -26.40% (-27.62% to -21.61%)
 ↳ prove-bus 202.81 ms 202.51 ms -0.08% (-1.11% to +1.15%)
 ↳ prove-constraints 21.37 ms 21.34 ms -0.04% (-1.52% to +1.06%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 2.99 s 2.69 s -10.27% (-10.87% to -10.04%)
 ↳ build-witness 83.58 ms 83.14 ms -0.54% (-0.97% to +0.38%)
 ↳ commit 478.95 ms 487.37 ms +1.73% (+1.42% to +4.87%)
 ↳ execute-program 13.05 ms 13.17 ms +0.87% (-8.63% to +2.17%)
 ↳ flock-reductions 1.20 s 1.04 s -13.84% (-14.59% to -13.38%)
 ↳ pcs-open 987.02 ms 833.21 ms -15.86% (-16.96% to -15.13%)
 ↳ prove-bus 207.25 ms 210.07 ms +1.34% (+0.82% to +2.06%)
 ↳ prove-constraints 21.64 ms 21.74 ms +0.50% (-1.05% to +3.36%)
shielded-258 arm64 Neoverse-N2 4.54 s 3.78 s -16.68% (-18.17% to -16.47%)
 ↳ build-witness 114.69 ms 114.22 ms -0.32% (-1.36% to -0.14%)
 ↳ commit 743.62 ms 743.79 ms +0.02% (-1.20% to +0.37%)
 ↳ execute-program 65.81 ms 65.86 ms +0.46% (-2.81% to +0.95%)
 ↳ flock-reductions 1.42 s 1.16 s -17.52% (-18.75% to -17.33%)
 ↳ pcs-open 1.86 s 1.35 s -27.43% (-29.33% to -26.90%)
 ↳ prove-bus 310.35 ms 310.38 ms -0.17% (-0.39% to +0.66%)
 ↳ prove-constraints 34.62 ms 34.77 ms +0.64% (-1.43% to +1.18%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 7.69 s 6.69 s -13.01% (-13.73% to -12.70%)
 ↳ build-witness 208.46 ms 207.75 ms -0.25% (-1.57% to +3.40%)
 ↳ commit 1.28 s 1.30 s +1.55% (+1.23% to +1.93%)
 ↳ execute-program 77.72 ms 81.32 ms +1.63% (-5.10% to +12.29%)
 ↳ flock-reductions 3.12 s 2.45 s -21.59% (-22.78% to -21.37%)
 ↳ pcs-open 2.32 s 1.96 s -15.41% (-15.81% to -14.53%)
 ↳ prove-bus 613.49 ms 623.64 ms +1.73% (-1.62% to +2.15%)
 ↳ prove-constraints 61.78 ms 61.18 ms -1.00% (-28.85% to -0.45%)
stateproof-5 arm64 Neoverse-N2 7.30 s 6.20 s -15.06% (-15.32% to -14.53%)
 ↳ build-witness 187.31 ms 186.77 ms -0.32% (-0.71% to +0.03%)
 ↳ commit 1.22 s 1.22 s -0.13% (-0.69% to +0.04%)
 ↳ execute-program 87.84 ms 87.13 ms -0.01% (-1.76% to +1.53%)
 ↳ flock-reductions 2.19 s 1.82 s -16.84% (-17.47% to -14.62%)
 ↳ pcs-open 3.08 s 2.35 s -23.76% (-23.96% to -23.35%)
 ↳ prove-bus 476.79 ms 476.83 ms +0.01% (-0.67% to +0.40%)
 ↳ prove-constraints 58.41 ms 58.48 ms -0.02% (-0.30% to +0.60%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 10.79 s 9.43 s -12.73% (-13.13% to -12.22%)
 ↳ build-witness 318.51 ms 318.04 ms +0.15% (-2.07% to +3.84%)
 ↳ commit 1.62 s 1.63 s +0.46% (-0.75% to +2.58%)
 ↳ execute-program 124.27 ms 124.19 ms +0.11% (-1.39% to +1.00%)
 ↳ flock-reductions 4.46 s 3.68 s -17.48% (-17.88% to -16.99%)
 ↳ pcs-open 3.41 s 2.80 s -17.90% (-18.57% to -17.35%)
 ↳ prove-bus 785.20 ms 787.01 ms +0.26% (-0.14% to +0.80%)
 ↳ prove-constraints 93.49 ms 92.93 ms -1.30% (-2.87% to +1.48%)

Verifying time

benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 10.74 ms 7.02 ms -34.60% (-35.45% to -34.52%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 12.62 ms 7.70 ms -38.63% (-40.31% to -37.55%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 16.70 ms 12.98 ms -22.72% (-23.38% to -21.18%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 20.78 ms 15.77 ms -24.22% (-26.03% to -22.48%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 8.76 ms 4.72 ms -46.12% (-47.50% to -44.74%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 11.36 ms 6.32 ms -44.17% (-45.34% to -43.52%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 10.15 ms 6.41 ms -39.08% (-41.97% to -35.53%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 15.71 ms 10.53 ms -32.53% (-33.25% to -31.87%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 13.96 ms 5.61 ms -59.81% (-60.63% to -59.32%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 17.82 ms 7.70 ms -56.73% (-57.31% to -56.58%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 18.06 ms 8.95 ms -50.65% (-56.61% to -49.56%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 26.67 ms 16.13 ms -39.48% (-40.89% to -39.36%)
falcon-7 arm64 Neoverse-N2 4.88 ms 4.89 ms +0.20% (-0.55% to +0.53%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 5.37 ms 5.44 ms +1.38% (+0.28% to +2.17%)
fibonacci-asm-2000000 arm64 Neoverse-N2 4.77 ms 4.79 ms +0.47% (+0.29% to +0.73%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 5.15 ms 5.20 ms +1.03% (-0.43% to +1.79%)
hash-50000 arm64 Neoverse-N2 4.81 ms 4.80 ms +0.10% (-1.10% to +1.88%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 5.09 ms 5.09 ms +0.65% (-0.73% to +1.48%)
leansphincs-26 arm64 Neoverse-N2 4.70 ms 4.71 ms +0.52% (-0.11% to +7.22%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 5.13 ms 5.11 ms +0.03% (-0.78% to +0.64%)
leanxmss-100 arm64 Neoverse-N2 4.68 ms 4.67 ms -0.10% (-0.20% to +0.29%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 5.05 ms 5.09 ms +0.53% (+0.10% to +1.20%)
leanxmss-100-1thread arm64 Neoverse-N2 4.79 ms 4.78 ms +0.11% (-1.07% to +1.36%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 5.07 ms 5.15 ms +1.63% (+0.54% to +1.99%)
shielded-258 arm64 Neoverse-N2 4.92 ms 4.90 ms -0.18% (-2.29% to +0.19%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 5.37 ms 5.38 ms +0.65% (-0.68% to +1.02%)
stateproof-5 arm64 Neoverse-N2 5.01 ms 5.03 ms +0.40% (-0.01% to +0.60%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 5.43 ms 5.38 ms -0.91% (-2.37% to +1.41%)

Time per operation

benchmark runner CPU base this PR change
blake2s-batch arm64 Neoverse-N2 15.49 ns 15.49 ns +0.05% (-0.26% to +0.11%)
blake2s-batch x86-64 AMD EPYC 7763 64-Core Processor 11.16 ns 11.18 ns +0.42% (-1.24% to +27.11%)
f192-inv arm64 Neoverse-N2 224.58 ns 224.52 ns -0.04% (-0.05% to +0.05%)
f192-inv x86-64 AMD EPYC 7763 64-Core Processor 271.82 ns 271.52 ns -0.12% (-0.24% to +0.14%)
f192-mul-latency arm64 Neoverse-N2 8.25 ns 8.25 ns -0.01% (-0.02% to +0.07%)
f192-mul-latency x86-64 AMD EPYC 7763 64-Core Processor 8.16 ns 8.15 ns -0.07% (-0.55% to +0.04%)
f192-mul-throughput arm64 Neoverse-N2 6.48 ns 6.48 ns +0.02% (+0.00% to +0.03%)
f192-mul-throughput x86-64 AMD EPYC 7763 64-Core Processor 6.59 ns 6.58 ns +0.08% (-1.79% to +4.75%)
f192-mul4-latency arm64 Neoverse-N2 25.93 ns 25.93 ns -0.05% (-0.12% to +0.09%)
f192-mul4-latency x86-64 AMD EPYC 7763 64-Core Processor 28.60 ns 27.06 ns -4.58% (-7.27% to +6.37%)
f192-mul4-throughput arm64 Neoverse-N2 25.93 ns 25.93 ns -0.01% (-0.06% to +0.02%)
f192-mul4-throughput x86-64 AMD EPYC 7763 64-Core Processor 29.35 ns 29.80 ns -1.04% (-2.51% to +9.40%)
f192-square arm64 Neoverse-N2 3.54 ns 3.54 ns -0.03% (-0.06% to +0.00%)
f192-square x86-64 AMD EPYC 7763 64-Core Processor 4.69 ns 4.69 ns -0.02% (-0.13% to +3.65%)
f64-inv arm64 Neoverse-N2 197.13 ns 197.14 ns +0.00% (-0.22% to +0.09%)
f64-inv x86-64 AMD EPYC 7763 64-Core Processor 243.54 ns 243.28 ns -0.11% (-1.18% to +0.27%)
f64-mul arm64 Neoverse-N2 1.18 ns 1.18 ns +0.00% (-0.08% to +0.08%)
f64-mul x86-64 AMD EPYC 7763 64-Core Processor 1.90 ns 1.90 ns +0.00% (-0.42% to +1.47%)
f64-square arm64 Neoverse-N2 1.18 ns 1.18 ns +0.00% (+0.00% to +0.08%)
f64-square x86-64 AMD EPYC 7763 64-Core Processor 1.61 ns 1.62 ns +0.25% (-4.38% to +1.11%)
ntt-forward-22 arm64 Neoverse-N2 25.95 ms 25.80 ms -0.77% (-1.06% to +0.82%)
ntt-forward-22 x86-64 AMD EPYC 7763 64-Core Processor 66.85 ms 66.57 ms -0.34% (-1.15% to +3.31%)
transpose-64bytes arm64 Neoverse-N2 16.06 ns 16.06 ns -0.01% (-0.34% to +0.01%)
transpose-64bytes x86-64 AMD EPYC 7763 64-Core Processor 6.02 ns 6.02 ns -0.02% (-0.18% to +0.08%)
transpose-64x64 arm64 Neoverse-N2 120.27 ns 119.95 ns -0.32% (-0.56% to -0.18%)
transpose-64x64 x86-64 AMD EPYC 7763 64-Core Processor 99.23 ns 99.38 ns +0.21% (-0.13% to +1.24%)

Proof size

benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 260,427 B 260,427 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 260,427 B 260,427 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 259,659 B 259,659 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 259,659 B 259,659 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 260,427 B 260,427 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 260,427 B 260,427 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 259,659 B 259,659 B 0 B (+0.00%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 259,659 B 259,659 B 0 B (+0.00%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 283,331 B 283,331 B 0 B (+0.00%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 283,331 B 283,331 B 0 B (+0.00%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 285,027 B 285,027 B 0 B (+0.00%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 285,027 B 285,027 B 0 B (+0.00%)
falcon-7 arm64 Neoverse-N2 326,382 B 326,382 B 0 B (+0.00%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 326,382 B 326,382 B 0 B (+0.00%)
fibonacci-asm-2000000 arm64 Neoverse-N2 366,742 B 366,742 B 0 B (+0.00%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 366,742 B 366,742 B 0 B (+0.00%)
hash-50000 arm64 Neoverse-N2 326,742 B 326,742 B 0 B (+0.00%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 326,742 B 326,742 B 0 B (+0.00%)
leansphincs-26 arm64 Neoverse-N2 319,734 B 319,734 B 0 B (+0.00%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 319,734 B 319,734 B 0 B (+0.00%)
leanxmss-100 arm64 Neoverse-N2 307,670 B 307,670 B 0 B (+0.00%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 307,670 B 307,670 B 0 B (+0.00%)
leanxmss-100-1thread arm64 Neoverse-N2 307,670 B 307,670 B 0 B (+0.00%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 307,670 B 307,670 B 0 B (+0.00%)
shielded-258 arm64 Neoverse-N2 357,614 B 357,614 B 0 B (+0.00%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 357,614 B 357,614 B 0 B (+0.00%)
stateproof-5 arm64 Neoverse-N2 350,614 B 350,614 B 0 B (+0.00%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 350,614 B 350,614 B 0 B (+0.00%)

Peak memory

benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 1800.72 MiB 1780.46 MiB -1.12% (-1.23% to +0.11%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 1142.24 MiB 1184.42 MiB +3.68% (+3.66% to +3.85%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 1800.72 MiB 1780.71 MiB -1.11% (-1.21% to +0.13%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 1142.24 MiB 1184.42 MiB +3.68% (+3.66% to +3.85%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 1840.06 MiB 1838.89 MiB +0.19% (-0.99% to +0.31%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 1169.10 MiB 1213.23 MiB +3.84% (+3.23% to +4.07%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 1848.87 MiB 1849.84 MiB +0.07% (-1.02% to +0.18%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 1185.19 MiB 1220.20 MiB +3.11% (+2.73% to +3.32%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 2340.28 MiB 2336.43 MiB -0.25% (-1.10% to +0.26%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 1209.55 MiB 1502.11 MiB +24.33% (+23.71% to +24.90%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 2349.11 MiB 2349.64 MiB +0.02% (-0.82% to +0.13%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 1226.15 MiB 1515.41 MiB +23.67% (+23.42% to +24.09%)
falcon-7 arm64 Neoverse-N2 5708.59 MiB 5708.78 MiB -0.01% (-0.12% to +0.01%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 3070.30 MiB 3532.27 MiB +15.05% (+14.71% to +15.11%)
fibonacci-asm-2000000 arm64 Neoverse-N2 8986.95 MiB 8986.20 MiB -0.01% (-0.03% to +0.02%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 4076.34 MiB 5447.41 MiB +33.65% (+33.57% to +33.77%)
hash-50000 arm64 Neoverse-N2 5656.72 MiB 5657.46 MiB -0.03% (-0.09% to +0.04%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 2922.95 MiB 3380.61 MiB +15.66% (+15.33% to +15.78%)
leansphincs-26 arm64 Neoverse-N2 1852.34 MiB 1850.90 MiB -0.16% (-0.43% to +0.06%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 916.41 MiB 1192.66 MiB +30.36% (+30.08% to +30.44%)
leanxmss-100 arm64 Neoverse-N2 1635.12 MiB 1623.27 MiB -0.63% (-0.96% to +0.00%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 784.20 MiB 1022.22 MiB +30.35% (+30.09% to +30.65%)
leanxmss-100-1thread arm64 Neoverse-N2 1612.19 MiB 1592.36 MiB -1.25% (-1.35% to +0.50%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 770.14 MiB 1006.19 MiB +30.64% (+30.00% to +31.01%)
shielded-258 arm64 Neoverse-N2 8203.56 MiB 8204.41 MiB +0.01% (-0.02% to +0.60%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 4154.67 MiB 5408.12 MiB +30.15% (+30.10% to +30.37%)
stateproof-5 arm64 Neoverse-N2 12399.45 MiB 12401.41 MiB -0.01% (-0.06% to +0.02%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 6091.15 MiB 8067.14 MiB +32.44% (+32.33% to +32.49%)

allocations

benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 23.49 µs 23.34 µs -0.63% (-0.63% to -0.63%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 23.50 µs 23.36 µs -0.63% (-0.63% to -0.63%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 26.13 µs 27.23 µs +4.21% (+4.21% to +4.21%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 26.15 µs 27.25 µs +4.20% (+4.20% to +4.20%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 23.59 µs 23.44 µs -0.62% (-0.62% to -0.62%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 23.60 µs 23.46 µs -0.62% (-0.62% to -0.62%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 26.23 µs 27.33 µs +4.19% (+4.15% to +4.19%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 26.25 µs 27.34 µs +4.19% (+4.19% to +4.19%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 42.13 µs 41.95 µs -0.43% (-0.43% to -0.43%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 42.15 µs 41.97 µs -0.43% (-0.43% to -0.43%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 48.81 µs 49.86 µs +2.15% (+2.15% to +2.15%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 48.82 µs 49.87 µs +2.15% (+2.13% to +2.15%)
falcon-7 arm64 Neoverse-N2 14.38 µs 14.75 µs +2.59% (+2.59% to +2.60%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 14.60 µs 15.01 µs +2.80% (+2.80% to +2.80%)
fibonacci-asm-2000000 arm64 Neoverse-N2 11.02 µs 11.22 µs +1.82% (+1.81% to +1.84%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 11.24 µs 11.54 µs +2.70% (+2.69% to +2.71%)
hash-50000 arm64 Neoverse-N2 15.09 µs 15.54 µs +2.97% (+2.97% to +2.97%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 15.33 µs 15.80 µs +3.08% (+3.07% to +3.08%)
leansphincs-26 arm64 Neoverse-N2 24.32 µs 24.68 µs +1.48% (+1.48% to +1.51%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 24.57 µs 24.98 µs +1.65% (+1.65% to +1.65%)
leanxmss-100 arm64 Neoverse-N2 24.95 µs 25.32 µs +1.46% (+1.31% to +1.46%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 25.20 µs 25.61 µs +1.60% (+1.60% to +1.63%)
leanxmss-100-1thread arm64 Neoverse-N2 24.68 µs 25.05 µs +1.47% (+1.47% to +1.47%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 24.93 µs 25.33 µs +1.62% (+1.62% to +1.62%)
shielded-258 arm64 Neoverse-N2 43.60 µs 44.03 µs +0.99% (+0.99% to +0.99%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 43.85 µs 44.31 µs +1.05% (+1.05% to +1.11%)
stateproof-5 arm64 Neoverse-N2 17.72 µs 18.13 µs +2.29% (+2.29% to +2.29%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 17.97 µs 18.40 µs +2.41% (+2.40% to +2.42%)

heap-peak

benchmark runner CPU base this PR change
aggregate-leanxmss-100-2to1-1thread-first arm64 Neoverse-N2 772.22 ms 738.67 ms -4.35% (-4.35% to -4.35%)
aggregate-leanxmss-100-2to1-1thread-first x86-64 AMD EPYC 7763 64-Core Processor 416.30 ms 373.29 ms -10.33% (-10.33% to -10.33%)
aggregate-leanxmss-100-2to1-1thread-node arm64 Neoverse-N2 771.88 ms 738.32 ms -4.35% (-4.35% to -4.35%)
aggregate-leanxmss-100-2to1-1thread-node x86-64 AMD EPYC 7763 64-Core Processor 415.95 ms 372.94 ms -10.34% (-10.34% to -10.34%)
aggregate-leanxmss-100-2to1-first arm64 Neoverse-N2 772.18 ms 738.62 ms -4.34% (-4.35% to -4.34%)
aggregate-leanxmss-100-2to1-first x86-64 AMD EPYC 7763 64-Core Processor 416.41 ms 373.33 ms -10.34% (-10.35% to -10.34%)
aggregate-leanxmss-100-2to1-node arm64 Neoverse-N2 771.85 ms 738.28 ms -4.35% (-4.36% to -4.35%)
aggregate-leanxmss-100-2to1-node x86-64 AMD EPYC 7763 64-Core Processor 416.04 ms 373.00 ms -10.34% (-10.35% to -10.33%)
aggregate-leanxmss-100-4to1-first arm64 Neoverse-N2 1.54 s 1.48 s -4.34% (-4.35% to -4.34%)
aggregate-leanxmss-100-4to1-first x86-64 AMD EPYC 7763 64-Core Processor 832.31 ms 746.26 ms -10.34% (-10.34% to -10.34%)
aggregate-leanxmss-100-4to1-node arm64 Neoverse-N2 1.54 s 1.48 s -4.35% (-4.35% to -4.34%)
aggregate-leanxmss-100-4to1-node x86-64 AMD EPYC 7763 64-Core Processor 831.71 ms 745.73 ms -10.34% (-10.35% to -10.32%)
falcon-7 arm64 Neoverse-N2 5.43 s 5.43 s +0.00% (-0.00% to +0.00%)
falcon-7 x86-64 AMD EPYC 7763 64-Core Processor 2.43 s 2.43 s -0.00% (-0.00% to +0.00%)
fibonacci-asm-2000000 arm64 Neoverse-N2 8.70 s 8.70 s -0.00% (-0.00% to +0.00%)
fibonacci-asm-2000000 x86-64 AMD EPYC 7763 64-Core Processor 3.95 s 3.95 s -0.00% (-0.00% to +0.00%)
hash-50000 arm64 Neoverse-N2 5.45 s 5.45 s +0.00% (-0.00% to +0.00%)
hash-50000 x86-64 AMD EPYC 7763 64-Core Processor 2.30 s 2.32 s +0.64% (+0.64% to +0.64%)
leansphincs-26 arm64 Neoverse-N2 1.72 s 1.72 s -0.00% (-0.00% to +0.00%)
leansphincs-26 x86-64 AMD EPYC 7763 64-Core Processor 776.65 ms 776.67 ms +0.01% (-0.00% to +0.01%)
leanxmss-100 arm64 Neoverse-N2 1.49 s 1.49 s -0.00% (-0.01% to +0.00%)
leanxmss-100 x86-64 AMD EPYC 7763 64-Core Processor 667.30 ms 667.34 ms +0.00% (-0.00% to +0.01%)
leanxmss-100-1thread arm64 Neoverse-N2 1.49 s 1.49 s +0.00% (+0.00% to +0.00%)
leanxmss-100-1thread x86-64 AMD EPYC 7763 64-Core Processor 667.32 ms 667.32 ms +0.00% (+0.00% to +0.00%)
shielded-258 arm64 Neoverse-N2 7.89 s 7.89 s +0.00% (-0.00% to +0.00%)
shielded-258 x86-64 AMD EPYC 7763 64-Core Processor 3.66 s 3.66 s -0.00% (-0.00% to +0.00%)
stateproof-5 arm64 Neoverse-N2 12.45 s 12.45 s -0.00% (-0.00% to +0.00%)
stateproof-5 x86-64 INTEL(R) XEON(R) PLATINUM 8573C 5.82 s 5.82 s +0.00% (-0.00% to +0.00%)

)

Upstream's one reduction API (leanEthereum#512) owns each batch's witness in `Instance`; leanEthereum#463 and the hash witness change
write `z` straight into the committed column, and padskip adds the batch's live instances. The merged `Instance`
borrows `z`, `A·z`, `B·z` and the stripes and carries `live`; `Instance::new` takes a `z` held apart (the committed
column) and the rest as `flock::Tables`, `Instance::of` a whole `Witness`, both reading the tail off `z`. The
`_into` generators return `Tables`. The prover keeps each class batch's `Tables` and the hash rows' `HashBatch`
between the commit and the reduction, as `Prepared` and `HashBatch` did.

`Fill` takes leanEthereum#463's word-level generators (`Fill::Instance` for ALU, LOAD, STORE, LD, SD, SHIFT); the clock
circuits keep theirs. The NTT's lane butterflies keep leanEthereum#464's register kernels and gain the transposed butterfly
upstream added, in registers.
# Conflicts:
#	crates/leanvm_core/src/class_flock.rs
# Conflicts:
#	crates/flock/src/reduction.rs
#	crates/leanvm_core/src/class_flock.rs
#	crates/leanvm_core/src/rec/proof.rs
PR 464 (the commit NTT plan for few workers) is open on its own, so this
branch no longer carries it. Its three files go back to upstream's
versions: pcs/src/ntt/additive_ntt_f64.rs, pcs/src/ntt.rs and
pcs/src/whir/commit.rs. That also drops the AVX-512 register kernels,
including the register version of upstream's transposed butterfly, which
belonged to PR 464's register path.

The deep-task sizing of kw/agg1-ntt-tasks goes back onto upstream's
AdditiveNttF64::transform as it was first written: a deep task takes
2^MIN_TASK_LOG (64) rows of contiguous sub-blocks and hands them to the
row sink at once. The codeword and the tree are unchanged.

Nothing else in this branch used PR 464.
@kevaundray

Copy link
Copy Markdown
Collaborator Author

@tcoratger do you think this is worth it?

@tcoratger
tcoratger merged commit a4c8699 into leanEthereum:riscv-exploration Oct 7, 2026
48 checks passed
@tcoratger

Copy link
Copy Markdown
Collaborator

@tcoratger do you think this is worth it?

Yes this is definitely important in my opinion, just merged :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants