You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Const-generic width ([F; W] instead of runtime-width slices)
PoC: exp/poseidon-perf622b4cf (bench only)
Gain: 6.82 -> 5.70 us (-16.5%), from fewer bounds checks and unrolled
loops.
Why it is safe: mechanical. The algorithm and the order of operations
stay the same; only the container type changes. The public API keeps its
runtime width.
sum_of_products for MDS rows
PoC: exp/poseidon-perf622b4cf
Gain: -10.6% on sparse rows, -2.3% on full MDS rows.
Why it is safe: arkworks' sum_of_products computes the same dot product
mod p with fewer modular reductions. Reduction does not change the field
element. BN254 qualifies for the fast path. Requires fixed-size arrays,
so it depends on item 3.
Gain: width 3, 5.58 -> 5.07 us (-9%) on top of items 3-5. Byte-identical
code measures 5.60 us generic against 4.90 us concrete, so the
genericity itself costs ~12% of a hash.
Why it is needed: rustc's MIR inliner runs before monomorphization, so <F as Field>::square through a type parameter is not inlinable.
LLVM's cost model then keeps the wide Montgomery bodies as outline
calls, and the state round-trips through memory between them. Concrete Fr code inlines everything (~2800 instructions, no calls).
Why it is safe:
Selection is TypeId equality, which is a compile-time constant for
a concrete caller; any other field takes the generic path, unchanged.
The concrete core is the same algorithm statement for statement. A
unit test runs every bundled width through both cores, with and
without the sparse factorization, and requires agreement.
The public API is unchanged.
Caveat: the concrete core duplicates the generic one. If the
permutation changes, both copies change; the parity test covers this.
ark-ffasm feature on x86_64
PoC: none. It cannot be measured on arm64.
Expected: 5-15% on field multiplication. Validators run x86_64.
Why it is safe: an arkworks feature flag with the same arithmetic.
arkworks 0.5 -> 0.6 (optional)
PoC: chore/arkworks-0.6720adb0
Gain: -0.5% to -1.3%.
Why it is safe: no source change; outputs unchanged.
Caveat: semver-breaking. arkworks types are in the public API, so solana-poseidon and Agave must bump in the same step. Only tested
stacked on item 2, not on main directly.
sol_poseidon(construct hasher, thenhash_bytes_be).main, 11.77 us.Proposed Improvements
Improvements
Zero heap allocations
perf/zero-alloc-poseidonform at compile time instead of on every hasher construction.
Vecrebuilt every round.
big integers or vectors.
conversion moves, from runtime to compile time, via the same reduction.
change.
mainacross all widths andboth endiannesses.
solana-poseidonuses are unchanged.Sparse MDS for partial rounds
worktree-poseidon-perf-followups(82e88a1,6a285aa)A partial round costs
2W - 1multiplications instead ofW^2.M = M_sparse * M',where
M'commutes with the partial-round S-box, and round-constantfolding.
checked against the matrix identities.
(https://github.com/filecoin-project/neptune) and circomlib's
optimized Poseidon, which uses precomputed
S/Pmatrices(https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom).
https://eprint.iacr.org/2019/458.
Const-generic width (
[F; W]instead of runtime-width slices)exp/poseidon-perf622b4cf(bench only)loops.
stay the same; only the container type changes. The public API keeps its
runtime width.
sum_of_productsfor MDS rowsexp/poseidon-perf622b4cfsum_of_productscomputes the same dot productmod p with fewer modular reductions. Reduction does not change the field
element. BN254 qualifies for the fast path. Requires fixed-size arrays,
so it depends on item 3.
(Use interleaving to improve performance of G2 arithmetic and pairings zkcrypto/bls12_381#84).
https://hackmd.io/@gnark/modular_multiplication.
Final round computes lane 0 only
exp/poseidon-perf622b4cfstate[0], so the finalround's MDS output for lanes 1..W is discarded.
Concretely-compiled BN254 permutation, selected by
TypeIdworktree-poseidon-perf-followups335b3c2(src/bn254.rs)code measures 5.60 us generic against 4.90 us concrete, so the
genericity itself costs ~12% of a hash.
<F as Field>::squarethrough a type parameter is not inlinable.LLVM's cost model then keeps the wide Montgomery bodies as outline
calls, and the state round-trips through memory between them. Concrete
Frcode inlines everything (~2800 instructions, no calls).TypeIdequality, which is a compile-time constant fora concrete caller; any other field takes the generic path, unchanged.
unit test runs every bundled width through both cores, with and
without the sparse factorization, and requires agreement.
permutation changes, both copies change; the parity test covers this.
ark-ffasmfeature on x86_64arkworks 0.5 -> 0.6 (optional)
chore/arkworks-0.6720adb0solana-poseidonand Agave must bump in the same step. Only testedstacked on item 2, not on
maindirectly.