Skip to content

multi-stark quotient lde bump - #544

Merged
gabriel-barrett merged 2 commits into
mainfrom
gb/multi-stark-quotient-lde
Aug 8, 2026
Merged

multi-stark quotient lde bump#544
gabriel-barrett merged 2 commits into
mainfrom
gb/multi-stark-quotient-lde

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Quotient commit from coefficient slices (multi-stark bump) + FFT cost model update

Bumps multi-stark to d85ba29, which changes how the prover commits the quotient, and updates the Aiur FFT cost statistic (#539) to model the new transforms.

multi-stark side

The quotient is the only committed data born in coefficient form, yet the prover treated it like a witness trace: DFT the coefficient slices onto the trace domain, then let Pcs::commit's coset_lde_batch immediately inverse-DFT them right back. The DFT/iDFT pair cancels exactly, so it was 2·q·D wasted size-n transforms per circuit.

Two commits:

  1. prover: commit the quotient straight from its coefficient slices — build the committed LDE directly from the slice coefficients as one zero-padded size-B·n DFT per circuit (fold the GENERATOR shift into the coefficients, pad, dft_batch; the transform's native bit-reversed storage is exactly the layout TwoAdicFriPcs::commit stores), and commit through Pcs::commit_ldes.
    An earlier per-coset variant (B separate coset_dft_batch calls) did fewer butterflies but regressed the quotient span 5.59s → 6.88s: the default coset_dft_batch pays a matrix clone, a fully serial shift-scaling pass, and two bit-reversal passes per call, which dominates at real heights (n ≈ 2²⁵) while staying invisible in small-height microbenchmarks.
  2. prover: fuse the quotient iDFT tail into the slicing gather — the iDFT post-passes (bit-reversal materialization, serial row swap, serial coset-unscale) and the serial slicing loop collapse into one parallel gather: the coset-unscale g^{−(k·n+r)} cancels the LDE pre-scale g^{r} exactly, leaving a single constant N⁻¹·g^{−k·n} per slice.

The committed matrix is value-identical to the old path — transcript, proof bytes, and verifier all unchanged. Two unit tests pin the equivalences (against coset_lde_batch ∘ coset_dft_batch, and against the naive iDFT + slice + pre-scale composition).

Benchmarks (bench-typecheck --ixe init.ixe --consts String.split --texray, 64 cores)

multi-stark rev stark/quotient prove total proof bytes
5023fee (main) 5.59s 32.1s 23139426
d85ba29 (this PR) 4.97s (−11%) 31.0s 23139426

ix side

The per-circuit FFT statistic (#539) modeled the old quotient path. Updated to the new transforms:

(B+1)·(m + s2 + q·D)·F(h) + D·F(q·h) + q·D·F(h)
→  (B+1)·(m + s2)·F(h)    + D·F(q·h) + q·D·F(B·h)

The quotient chunk columns lose the (B+1) commit transforms (commit_ldes runs no FFT) and the size-h rebase DFT, and pay the padded size-B·h DFT instead. Trace commits still go through coset_lde_batch and keep their (B+1)·F(h) shape.

- All 66 kernel-check pins and the shard pipeline pin regenerated from one lake test -- --ignored ixvm run (all execution/parity tests pass; real-circuit costs drop ~2% uniformly).
- Drive-by: the shard pin's message text had drifted from its asserted value (10817625733 vs 10_785_479_733); both now carry the same number.
- The aiur-cost hand-computed value moves 1424 → 1488: per chunk column the padded transform costs F(B·h) against the old (B+2)·F(h), which only wins for log₂(h) > 4 — a deliberate small-height loss at the test's h = 8; every real circuit clears it.

…mmit

multi-stark d85ba29 commits the quotient chunks from their coefficient
slices: the chunk LDE is ONE zero-padded size-B·h DFT per column
(`lde_from_shifted_coefficients`), the iDFT tail is fused into the
slicing gather (no extra transform), and `Pcs::commit_ldes` Merkles
the prebuilt LDE without touching the DFT. The per-circuit statistic
follows:

    (B+1)·(m + s2 + q·D)·F(h) + D·F(q·h) + q·D·F(h)
 →  (B+1)·(m + s2)·F(h)       + D·F(q·h) + q·D·F(B·h)

The quotient chunk columns lose the (B+1) commit transforms and the
size-h rebase DFT and pay the padded size-B·h DFT instead; the
forward DFT of the flattened quotient is unchanged (the old iDFT ran
the same transform), and the trace commits still go through
`coset_lde_batch`, keeping their (B+1)·F(h) shape.

All 66 kernel-check pins and the shard pipeline pin regenerated from
one `lake test -- --ignored ixvm` run (all execution/parity tests
pass; real-circuit costs drop ~2% uniformly). The shard pin's message
text had drifted from its asserted value (10817625733 in the message
vs 10_785_479_733 in the check); both now carry the same number. The
`aiur-cost` hand-computed value moves 1424 → 1488: per chunk column
the padded transform costs F(B·h) against the old (B+2)·F(h), which
only wins for log2(h) > B·log2(B)/2 — at the test's h = 8 it is a
deliberate small-height loss.
@gabriel-barrett

Copy link
Copy Markdown
Member Author

!benchmark aiur fresh

@gabriel-barrett

Copy link
Copy Markdown
Member Author

!benchmark aiur-recursive fresh

@argument-ci-bot

argument-ci-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

!benchmark — main vs 624e345

backends: aiur-recursive · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

aiur-recursive · InitStd — main from: base run @ b6f0214 (fresh — bencher bypassed)

1 constant · 0 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

constant recursive-prove-time (main) recursive-prove-time (PR) Δ% recursive-peak-ram (main) recursive-peak-ram (PR) Δ% recursive-proof-size (main) recursive-proof-size (PR) Δ% recursive-verify-time (main) recursive-verify-time (PR) Δ% recursive-execute-time (main) recursive-execute-time (PR) Δ% recursive-fft-cost (main) recursive-fft-cost (PR) Δ% prove-time (main) prove-time (PR) Δ% proof-size (main) proof-size (PR) Δ% verify-time (main) verify-time (PR) Δ% peak-ram (main) peak-ram (PR) Δ%
Nat.add_comm 38.977 s 38.116 s -2.2% 104.97 GiB 105.25 GiB +0.3% 5.60 MiB 5.60 MiB +0.0% 38.2 ms 34.1 ms -10.8% (1.12× faster) 🟢 6.337 s 6.308 s -0.5% 244.69B 241.46B -1.3% 1.169 s 1.041 s -11.0% (1.12× faster) 🟢 9.07 MiB 9.07 MiB +0.0% 53.4 ms 53.2 ms -0.4% 4.31 GiB 4.26 GiB -1.1%

Workflow logs

@argument-ci-bot

argument-ci-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

!benchmark — main vs 624e345

backends: aiur=prove · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

aiur · InitStd · prove — main from: base run @ b6f0214 (fresh — bencher bypassed)

13 constants · 1 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constant prove-time (main) prove-time (PR) Δ% throughput (const/s) (main) throughput (const/s) (PR) Δ% peak-ram (main) peak-ram (PR) Δ% execute-time (main) execute-time (PR) Δ% verify-time (main) verify-time (PR) Δ% proof-size (main) proof-size (PR) Δ% fft-cost (main) fft-cost (PR) Δ%
Array.extract_append 45.070 s 43.682 s -3.1% 🟢 34.210 35.300 +3.2% 🟢 88.35 GiB 88.61 GiB +0.3% 11.854 s 11.695 s -1.3% 132.6 ms 133.9 ms +0.9% 21.98 MiB 21.98 MiB +0.0% 184.56B 177.23B -4.0% 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append 43.847 s 42.663 s -2.7% 61.370 63.080 +2.8% 93.53 GiB 93.81 GiB +0.3% 10.450 s 10.796 s +3.3% ⚠️ 132.0 ms 131.6 ms -0.3% 22.06 MiB 22.06 MiB +0.0% 197.38B 191.35B -3.1% 🟢
Char.ofOrdinal_le_of_le 34.582 s 33.309 s -3.7% 🟢 76.510 79.440 +3.8% 🟢 72.38 GiB 72.63 GiB +0.4% 7.660 s 7.588 s -0.9% 215.9 ms 210.2 ms -2.6% 22.03 MiB 22.03 MiB +0.0% 146.27B 141.81B -3.0% 🟢
Vector.extract_append._proof_2 27.685 s 26.615 s -3.9% 🟢 47.030 48.920 +4.0% 🟢 55.59 GiB 55.82 GiB +0.4% 6.632 s 6.443 s -2.8% 134.9 ms 138.9 ms +3.0% 21.77 MiB 21.77 MiB +0.0% 108.95B 104.85B -3.8% 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq 20.913 s 20.198 s -3.4% 🟢 86.640 89.710 +3.5% 🟢 45.50 GiB 45.65 GiB +0.3% 3.958 s 3.938 s -0.5% 135.4 ms 135.3 ms -0.1% 21.86 MiB 21.86 MiB +0.0% 79.80B 77.52B -2.9%
String.split 19.662 s 18.917 s -3.8% 🟢 89.770 93.300 +3.9% 🟢 43.22 GiB 43.37 GiB +0.4% 3.606 s 3.541 s -1.8% 152.1 ms 149.2 ms -1.9% 22.07 MiB 22.07 MiB +0.0% 70.97B 68.96B -2.8%
List.mergeSort 13.835 s 13.289 s -3.9% 🟢 104.660 108.960 +4.1% 🟢 28.57 GiB 28.76 GiB +0.7% 2.591 s 2.604 s +0.5% 130.5 ms 130.2 ms -0.2% 21.92 MiB 21.92 MiB +0.0% 52.47B 51.04B -2.7%
Vector.append 4.467 s 4.130 s -7.5% (1.08× faster) 🟢 108.590 117.430 +8.1% (1.08× faster) 🟢 7.77 GiB 7.76 GiB -0.1% 694.4 ms 685.3 ms -1.3% 123.0 ms 122.2 ms -0.6% 20.43 MiB 20.43 MiB +0.0% 11.04B 10.76B -2.5%
Nat.gcd_comm 3.798 s 3.504 s -7.7% (1.08× faster) 🟢 102.680 111.300 +8.4% (1.08× faster) 🟢 7.03 GiB 6.82 GiB -3.1% 🟢 551.0 ms 560.6 ms +1.7% 129.0 ms 126.3 ms -2.1% 20.20 MiB 20.20 MiB +0.0% 8.03B 7.85B -2.3%
String.append 2.748 s 2.543 s -7.5% (1.08× faster) 🟢 110.640 119.550 +8.1% (1.08× faster) 🟢 4.76 GiB 4.72 GiB -0.7% 410.6 ms 414.9 ms +1.0% 114.4 ms 115.1 ms +0.6% 19.44 MiB 19.44 MiB +0.0% 4.41B 4.31B -2.2%
Int.gcd 2.321 s 2.104 s -9.3% (1.10× faster) 🟢 89.630 98.860 +10.3% (1.10× faster) 🟢 4.65 GiB 4.66 GiB +0.2% 361.8 ms 355.9 ms -1.6% 113.0 ms 111.1 ms -1.7% 19.00 MiB 19.00 MiB +0.0% 2.84B 2.78B -2.2%
Nat.sub_le_of_le_add 2.118 s 1.878 s -11.3% (1.13× faster) 🟢 80.280 90.520 +12.8% (1.13× faster) 🟢 4.70 GiB 4.73 GiB +0.7% 350.8 ms 351.5 ms +0.2% 114.0 ms 113.0 ms -0.9% 19.36 MiB 19.36 MiB +0.0% 2.42B 2.37B -2.2%
Nat.add_comm 1.152 s 1.063 s -7.8% (1.08× faster) 🟢 36.440 39.520 +8.5% (1.08× faster) 🟢 4.08 GiB 3.91 GiB -4.2% 🟢 252.5 ms 251.3 ms -0.5% 102.6 ms 102.3 ms -0.3% 17.52 MiB 17.52 MiB +0.0% 407.77M 400.40M -1.8%

Workflow logs

@gabriel-barrett
gabriel-barrett marked this pull request as ready for review August 7, 2026 21:30
@gabriel-barrett
gabriel-barrett merged commit 859d660 into main Aug 8, 2026
11 checks passed
@gabriel-barrett
gabriel-barrett deleted the gb/multi-stark-quotient-lde branch August 8, 2026 11:28
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