multi-stark quotient lde bump - #544
Merged
Merged
Conversation
…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.
Member
Author
|
!benchmark aiur fresh |
Member
Author
|
!benchmark aiur-recursive fresh |
|
| 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% |
|
| 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% |
gabriel-barrett
marked this pull request as ready for review
August 7, 2026 21:30
arthurpaulino
approved these changes
Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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'scoset_lde_batchimmediately inverse-DFT them right back. The DFT/iDFT pair cancels exactly, so it was2·q·Dwasted size-ntransforms per circuit.Two commits:
prover: commit the quotient straight from its coefficient slices— build the committed LDE directly from the slice coefficients as one zero-padded size-B·nDFT per circuit (fold theGENERATORshift into the coefficients, pad,dft_batch; the transform's native bit-reversed storage is exactly the layoutTwoAdicFriPcs::commitstores), and commit throughPcs::commit_ldes.An earlier per-coset variant (B separate
coset_dft_batchcalls) did fewer butterflies but regressed the quotient span 5.59s → 6.88s: the defaultcoset_dft_batchpays 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.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-unscaleg^{−(k·n+r)}cancels the LDE pre-scaleg^{r}exactly, leaving a single constantN⁻¹·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)5023fee(main)d85ba29(this PR)ix side
The per-circuit FFT statistic (#539) modeled the old quotient path. Updated to the new transforms: