Repository navigation
perf: batch-normalized MSM and parallel-gated DoryRoutines vector ops - #27
Merged
Merged
Conversation
msm now converts bases to affine with one shared Montgomery batch inversion (normalize_batch) instead of one field inversion per point, keeping the free into_affine path when every base is already normalized (z = 1, the setup-generator shape). The vector ops (fixed_base_vector_scalar_mul, fixed_scalar_mul_bases_then_add, fixed_scalar_mul_vs_then_add, fold_field_vectors) parallelize behind the existing `parallel` feature, following ark_pairing's cfg-dispatch pattern; without the feature the sequential code is unchanged. Group results are exact either way, so proofs are byte-identical. Equivalence tests pin the optimized routines against the naive reference, including identity points (z = 0), already-normalized bases, zero scalars, and empty inputs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 5, 2026
moodlezoup
added a commit
to a16z/jolt
that referenced
this pull request
Aug 5, 2026
…utines dory-pcs 0.4.1 ships the batch-normalized MSM (with a z=1 fast path this version lacked) and the parallel fold upstreamed in a16z/dory#27, so JoltG1Routines/JoltG2Routines keep only what upstream can't provide: the GLV vector kernels from jolt-optimizations and the tracing span labels the profiling telemetry grammar addresses. Byte parity vs the legacy prover verified across the muldiv ratchet arms (both backends). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Motivation
Profiling Dory inside Jolt shows the stock arkworks
DoryRoutinesdominating the reduce-fold rounds' wall clock:msmconverts bases to affine one field inversion at a time (into_affineper point), and the vector ops run one full scalar multiplication per element in a serial loop. Jolt has been carrying optimized replacement routines (jolt-dory'sJoltG1Routines/JoltG2Routines); this PR upstreams the part that needs nothing beyond stock arkworks, so every consumer of the default backend gets it.What changed
G1Routines::msm/G2Routines::msm: bases convert to affine viaCurveGroup::normalize_batch— one shared Montgomery batch inversion — instead of one inversion per point. When every base is already normalized (z = 1, e.g. setup generators, whereinto_affineis inversion-free), a cheap all-z=1 check keeps the old path so that shape doesn't regress. Underark-ec/parallel,normalize_batch's affine transformation is itself parallel (cfg_iter!).fixed_base_vector_scalar_mul,fixed_scalar_mul_bases_then_add,fixed_scalar_mul_vs_then_add,fold_field_vectors(both groups): parallelized behind the existingparallelfeature, followingark_pairing.rs's cfg-dispatch pattern. Withoutparallel, the sequential code is exactly as before. The field fold useswith_min_len(1024)so the short vectors of late reduce-fold rounds don't pay rayon's splitting overhead.Exactness
Group results are identical to the stock routines' — batch normalization and per-point conversion produce the same affine points (including identity handling:
normalize_batchmaps z = 0 toAffine::identity(), andbatch_inversionskips zero elements), and every parallel op is an independent per-element write with no reduction-order dependence. Proofs are byte-identical. New equivalence tests (tests/arkworks/routines.rs) pin the routines against naive references across identity points, already-normalized bases, zero scalars, and empty inputs, and run in both feature modes.Numbers
n = 4096, best-of-5 (3 for the heavy ops), 12-core Linux,
--features backends,parallel:msm(z ≠ 1 bases)msm(z = 1 bases)msm(z ≠ 1 bases)fixed_base_vector_scalar_mulfixed_base_vector_scalar_mulfixed_scalar_mul_bases_then_addfixed_scalar_mul_bases_then_addfold_field_vectorsValidation
cargo fmt --check; clippy clean (-D warnings) onbackends,parallel,cache,disk-persistence,+zk,backendsalone (sequential mode — not in CI's matrix), and--no-default-features;cargo doccleanbackends,parallel,cache,disk-persistence), 142/142 (+zk), 82/82 (backends, sequential)🤖 Generated with Claude Code