perf(prover-ray): 2x faster FRI commit - #3749
Conversation
There was a problem hiding this comment.
Pull request overview
This PR accelerates prover-ray’s KoalaBear FRI commitment path (encode + Merkle) via SIMD-batched Poseidon2 internal-node hashing, cache-friendly bit-reversal, a rate-2 LDE fast path, and reduced cold-start allocation overhead, while keeping commitment roots bit-identical to the scalar reference implementation.
Changes:
- Add a 16-lane Poseidon2 compression-chain kernel (AVX-512 with purego fallback) and use it to batch hash internal Merkle tree levels in parallel.
- Introduce COBRA-tiled bit-reversal for 4-byte field elements and a rate-2 encoder fast path (
EncodeInto/EncodeExtInto) that avoids a full-size FFT. - Reduce allocation overhead via slab-allocated codeword buffers and add optional witness consumption (
WithConsumeWitness) plus expanded benchmark tooling/docs.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| prover-ray/crypto/koalabear/poseidon2/poseidon2_batch.go | Adds public batched Poseidon2 compression-chain API + generic reference implementation. |
| prover-ray/crypto/koalabear/poseidon2/poseidon2_batch_test.go | Tests batched kernel vs scalar compression chains (including generic fallback). |
| prover-ray/crypto/koalabear/poseidon2/poseidon2_batch_noasm.go | Purego/!amd64 fallback wiring to the generic implementation. |
| prover-ray/crypto/koalabear/poseidon2/poseidon2_batch_amd64.s | AVX-512 assembly kernel for 16-lane state-seeded Poseidon2 chain compression. |
| prover-ray/crypto/koalabear/poseidon2/poseidon2_batch_amd64.go | amd64 dispatcher + AVX-512 feature gate and glue symbols for the asm kernel. |
| prover-ray/crypto/koalabear/fri/tree.go | Refactors tree construction and batches internal level hashing (with parallelism threshold). |
| prover-ray/crypto/koalabear/fri/tree_test.go | Adds scalar-reference equivalence tests covering aux/non-aux and parallel paths. |
| prover-ray/crypto/koalabear/fri/reedsolomon.go | Adds rate-2 coset fast path and EncodeInto/EncodeExtInto to support slab allocation. |
| prover-ray/crypto/koalabear/fri/reedsolomon_fastpath_test.go | Verifies rate-2 fast path matches the generic path for base/ext columns. |
| prover-ray/crypto/koalabear/fri/PERFORMANCE.md | Documents the optimization session, benchmark protocol, and remaining work. |
| prover-ray/crypto/koalabear/fri/pcs.go | Extends PCS.Commit to accept commit options. |
| prover-ray/crypto/koalabear/fri/fri.go | Zero-copy tree bottom for ext-only trees (fills tree nodes directly in parallel). |
| prover-ray/crypto/koalabear/fri/commitment.go | Adds CommitOption/WithConsumeWitness, slab codeword allocation, and zero-copy Merkleize bottom. |
| prover-ray/crypto/koalabear/fri/bitreverse.go | Adds COBRA-tiled bit reversal + out-of-place bit-reversed copy helper. |
| prover-ray/crypto/koalabear/fri/bitreverse_test.go | Correctness tests and a benchmark for the bit-reversal implementations. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/summary.csv | Captures baseline benchmark summary data. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/samples.csv | Captures baseline benchmark sample data. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/README.md | Baseline benchmark description and reproduction notes. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/plonky3-commit-shapes.rs | Plonky3 harness used for baseline measurements. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/plonky3-cargo.patch | Notes required Plonky3 dev-deps for consistent Rayon enablement. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/memory.csv | Baseline RSS + user/system timing captures. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07/environment.txt | Baseline environment/toolchain manifest. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/summary.csv | Intermediate benchmark summary for parallel-tree stage. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/samples.csv | Intermediate benchmark samples for parallel-tree stage. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/README.md | Intermediate stage benchmark write-up and reproduction steps. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/prover-ray.patch | Patch snapshot used for intermediate measurements. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/plonky3-commit-shapes.rs | Plonky3 harness used for intermediate measurements. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/plonky3-cargo.patch | Plonky3 Cargo changes for intermediate comparison. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/memory.csv | Intermediate RSS captures. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-parallel-tree/environment.txt | Intermediate environment/toolchain manifest. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-optimized/summary.csv | Optimized benchmark summary data. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-optimized/samples.csv | Optimized benchmark sample data + root markers. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-optimized/README.md | Optimized benchmark description and protocol notes. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-optimized/merkle-only.csv | Merkle-only and encode-only diagnostics for optimized stage. |
| prover-ray/crypto/koalabear/fri/benchmarks/2026-08-07-optimized/environment.txt | Optimized environment/toolchain manifest. |
| prover-ray/crypto/koalabear/fri/bench/main.go | Bench harness: adds phase selection, JSON output, consume-input mode, and CPU profiling. |
| prover-ray/crypto/koalabear/fri/bench_test.go | Adds commit/encode/merkle shape benchmarks and configuration via env var. |
YaoJGalteland
left a comment
There was a problem hiding this comment.
have you compared the performance across different FRI rates, e.g. 2, 4, 8, 16?
I remember we used rate 16 for Vortex before. Is that also a plausible parameter for FRI, or is the practical range more constrained here?
AVX-512 kernel derived from gnark-crypto's permutation16x16xN_columns with the Merkle-Damgard chain state loaded from memory instead of zeroed, so one call computes 16 direct C(left,right) compressions or C(C(left,right),aux) chains. Bit-identical to scalar Compress (lane-by-lane test, purego fallback included). Candidate for upstreaming to gnark-crypto. Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Full-commit medians vs native AVX-512+Rayon Plonky3, 96 cores, cold one-shot (was: pre-branch serial-tree baseline): 2^20x16 rate 2: 77.9 ms -> 31.8 ms (P3: 65.7 ms) 2^16x256 rate 2: 17.1 ms -> 12.0 ms (P3: 25.0 ms) 2^12x4096 rate 2: 17.9 ms -> 10.9 ms (P3: 18.5 ms) 10 GiB rate 2: 2.67 s -> 1.40 s (P3: 1.76 s) - Parallelize internal Merkle tree levels; hash them 16 nodes per call with the batched state-seeded Poseidon2 kernel, writing parents in place (scalar hashNode was 55% of the tall-shape commit). - COBRA cache-friendly bit-reversal for 4-byte elements; gnark's utils.BitReverse is always naive for sizeof<8 and burned 43% of the 4 GiB commit CPU. - Rate-2 LDE fast path: the first half of the bit-reversed codeword is exactly bitrev(input), so encode is one bit-reversed copy plus a half-size coset FFT (DIT inverse + DIF-on-coset). No full-size FFT, no standalone coefficient bit-reversal. - Hash bottom Merkle leaves directly into tree node storage (removes a leaf-array alloc+copy the size of the encoded bottom table). - Slab-allocate codewords per size bucket (EncodeInto): per-column large-object allocation under 96 threads spent 25 s in the kernel page-fault path on cold commits (372 ms -> 17.5 ms on rate-4 wide). - Opt-in WithConsumeWitness to release plaintext columns during encode; with GOMEMLIMIT this cuts 10 GiB commit peak RSS from 31.6 to ~23 GiB. Commitment roots are bit-identical throughout: deterministic root markers unchanged, fast path tested against the generic path, tree levels against a scalar reference. Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
PERFORMANCE.md: current results vs native Plonky3, what changed and why, the cold-allocation measurement trap, remaining bottlenecks and next experiments, benchmark protocol, correctness gates. benchmarks/: raw samples, medians, environment manifests for the generic-P3 baseline, the parallel-tree baseline, and the optimized run. Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com>
94acd38 to
2a57992
Compare
On AMD EPYC 9R45, for the fixed 64 MiB tall/balanced/wide workloads, rate 2 measured 31.8/12.0/10.9 ms and rate 4 measured 44.8/20.7/19.2 ms. I haven’t measured rates 8 or 16. We can tune the rate later once we benchmark representative production workflows |
| gutils "github.com/consensys/gnark-crypto/utils" | ||
| ) | ||
|
|
||
| func bitReverse[T any](v []T) { |
There was a problem hiding this comment.
Nit: seems a bit superfluous to have private wrappers for theses.
There was a problem hiding this comment.
so this is the result of a round trip of experiments ; following @YaoJGalteland review I reverted some optimizations, I will need these when we tune them depending on the size and target architecture 👍
|
You have conflicts. Let me know when they are fixed. Otherwise, I do not see any blocker. |
…kle-tree Signed-off-by: Gautam Botrel <gautam.botrel@gmail.com> # Conflicts: # prover-ray/crypto/koalabear/fri/tree.go # prover-ray/go.mod # prover-ray/go.sum
|
tests are failing independently from this PR changes , otherwise ready to merge |
FRI commit is now faster than native Plonky3 (AVX-512, Rayon, fat LTO) in every measured configuration. Roots bit-identical.
96 cores, cold one-shot processes, medians of 5.
What:
000c30b45f17).WithConsumeWitness+GOMEMLIMIT: 10 GiB peak RSS 31.6 -> ~23 GiB.Checklist