perf: MSM/FFT prover optimizations, build flags, C API use-after-free fix - #49
Open
OBrezhniev wants to merge 8 commits into
Open
perf: MSM/FFT prover optimizations, build flags, C API use-after-free fix#49OBrezhniev wants to merge 8 commits into
OBrezhniev wants to merge 8 commits into
Conversation
groth16_prover_create_zkey_file loaded the zkey into a local FileLoader, passed its mmap'd buffer to groth16_prover_create, then returned -- running the FileLoader destructor and munmap-ing the buffer. BinFile stores the pointer without copying (addr = fileData), so every zkey section pointer held by the Prover dangled, causing a segfault on the first prove() call. Add a file-path constructor to Groth16Prover that builds its BinFile from the path directly. BinFile's filename ctor owns its FileLoader member for the object's lifetime, so the zkey stays mapped across every prove(). The buffer and file-path ctors now share a common init() helper. Route groth16_prover_create_zkey_file through the new ctor with matching null-arg and exception handling. Verified: create_zkey_file + two proves + snarkjs verify OK (previously crashed with SIGSEGV on the first prove). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add portable build-optimization knobs (all opt-in; default `make host` and direct cmake builds are unchanged). Measured on a 1.1GB sha256 zkey (C-API steady-state per-prove), identical RSS across configs and proofs verifying OK: host_lto -5.7% portable host_march_lto -8.3% host-CPU-locked host_pgo +2% vs march_lto (worse on this ASM-heavy workload) - CMake: USE_MARCH_NATIVE / USE_LTO options (default OFF) + PGO=generate|use two-phase support. -march=native bakes in host CPU features (SIGILL risk on older CPUs) so it is opt-in; LTO is portable. - Makefile: host_march / host_lto / host_march_lto / host_pgo targets, plus *_lto variants for android / android_x86_64 / ios. Expanded `clean` to cover the new build/package dirs. - PGO is wired but measured a ~2% regression here (the compute hot path is hand-written NASM, leaving little branchy C++ for PGO); kept as documented opt-in. Mobile LTO targets are config-validated for the cross toolchain; on-device build/benchmark still pending (no NDK/Xcode in this environment). - binfile_utils.hpp: add #include <cstdint> (GCC 16 build fix; the header uses uint32_t/uint64_t without including it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps ffiasm to the scalar-size partitioned MSM with wall-clock-aware window selection, and adds test_msm: correctness of multiMulByScalarMSM against the independent ParallelMultiexp across witness-like scalar distributions and boundary values, plus a benchmark mode (test_msm bench). Measured G1 n=2^20 on 20 cores: uniform -14%, iden3-realistic witness -14%, all-binary -87%. End to end: sha256_test proof 2.41s -> 1.85s (-23%); small identity circuits unchanged (dominated by zkey load). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq
Bumps ffiasm to the task-based MSM and, on pools of 12+ threads, prepares the A, B1, B2 and C multiexponentiations up front and runs all their bucket tasks in a single parallel region (G1 and G2 tasks mixed, G2 first as the heaviest), so no MSM's straggler tail leaves cores idle. Below 12 threads the sequential path is kept: the batch holds every MSM's scratch at once, a poor trade on mobile. test_msm gains a batch correctness test mirroring the prover phase. Measured on 20 cores, interleaved, thermally controlled: identity circuits (authV3, sigV2, mtpV2, OnChain variants, V3) -5..-9% proof time end to end; sha256 unchanged on top of the previous -23%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq
Bumps ffiasm to batch-affine bucket accumulation and adapts the prover's batched MSM phase and test harness to the byte-based task arena. test_msm gains infinity-base and duplicate-point-pool tests covering the new accumulator's special-case paths. Measured on 20 cores, interleaved: sha256 proof 1.89 -> 1.59 s (-16%), OnChain identity circuits -9..-10%, others -6%. Cumulative over the three MSM waves: sha256 2.41 -> 1.59 s, identity circuits -10..-18%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq
Replaces the ifft/shift/fft trio with DIF-iFFT -> one fused coset pass -> DIT-FFT. The coset table (omega_2n^BR(i) with 1/n folded in, bit-reverse indexed) is precomputed once in the Prover constructor and reused by every proof. The coset stays the odd powers of omega_2n that snarkjs bakes into the zkey's H points, so zkey compatibility is untouched and the evaluations return in natural order for the H MSM. Eliminates six bit-reversal permutation passes and three reindex/scale passes per proof. test_msm gains a unit test asserting the new pipeline reproduces ifft+shift+fft exactly. Measured interleaved on 20 cores: sha256 -8.6%, sigV2/v3/authV2 -6%. Cumulative over the four optimization waves: sha256 2.41 -> 1.38 s (-43%), identity circuits -11..-18%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq
Fixes the iOS simulator Debug dylib link on CI (undefined BATCH_SIZE for arm64): the MSM class constants are now a typed enum, never ODR-used. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq
Bumps ffiasm to the int16-digit / indexed-partition / halved-roots MSM+FFT, and: - the batched A/B1/B2/C phase uses one shared bucket arena for both curves (a thread runs one task at a time; a common stride keeps the per-thread rows disjoint) instead of separate G1 and G2 arenas; - the Prover builds FFT(domainSize) instead of FFT(domainSize*2), deriving omega_2n via FFT::higherRootOfUnity and computing the bit-reverse-indexed coset table from a chunked power scan. Measured interleaved on 20 cores: peak RSS -15..-25% on the identity circuits (authV2 84 -> 63 MB), -9.7% on sha256 (1444 -> 1304 MB); proof times unchanged or slightly better (sha256 -1.4%, OnChain circuits -3.4/-3.8%). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq
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.
Groth16 prover performance work plus two smaller items that were already on this branch.
Prover optimizations (bumps ffiasm to iden3/ffiasm#7)
Four waves, each committed and benchmarked separately (interleaved old/new binaries, thermally controlled, 20-core x86-64):
ee122b8) — witness scalars classified by bit-length; 0/1 wires cost ~one addition instead of ~16 window additions. Addstest_msm, a correctness/benchmark harness (ctest target) comparing against the independentParallelMultiexpimplementation.184a656) — on pools of 12+ threads, the A/B1/B2/C multiexponentiations execute as one task set in a single parallel region (G2 first), removing four sequential barriers and straggler tails. Below 12 threads the sequential path is kept (mobile memory).0f2412b) — ~5M+1S per bucket addition instead of 8M+2S, batches of ≤512 additions per field inversion.98edc5c) — DIF-iFFT → fused coset pass → DIT-FFT with a per-prover precomputed bit-reverse-indexed coset table; eliminates six permutation passes and three scaling passes per proof. The coset stays the odd powers of ω_2n baked into snarkjs zkeys, so zkey compatibility is unchanged (unit test asserts exact equivalence with the old ifft/shift/fft).Measured end-to-end (median of interleaved rounds)
Every wave was verified by proving and verifying on nine production circuits plus the
test_msmsuite (scalar distributions, boundary values, infinity bases, duplicate points, mixed-curve batching, FFT equivalence).Also on this branch
4af8b85— opt-in-march=native/LTO/PGO build targets and mobile-LTO targets212bff8— fix use-after-free ingroth16_prover_create_zkey_file🤖 Generated with Claude Code
https://claude.ai/code/session_01JpMJeCdh75Shs3hBRFFLkq