perf(arithmetization): keccak optimization - #3727
Open
OlivierBBB wants to merge 6 commits into
Open
Conversation
…nction
kec_absorbing_phase was the most expensive keccak module: complexity 19987
(= sum of d^2 over its vanishing constraints) with PC_max 7.
Both figures came from its control flow rather than its arithmetic. A loop is
the only construct that survives the compiler's vectorisation pass as a distinct
PC value -- forward branches (if/else/switch/ternary) are predicated into a
single block, but back-edges are explicitly refused, since merging them would
unfold the loop indefinitely. Each surviving PC value then makes the vectoriser
duplicate the surrounding code into every block that can reach it: 55 lines of
source became ~660 micro-instructions spread over 7 blocks. On top of that,
nested loop and branch conditions multiply into the guard of every constraint
they enclose, raising its degree, and complexity weights degree quadratically.
Splitting the phase so that no function holds more than one loop removes both
effects. The five loops now live in kec_absorb_full_blocks,
kec_load_full_block, kec_absorb_final_block, kec_load_partial_words and
kec_zero_fill; kec_absorbing_phase itself becomes straight-line.
module PC_max limbs lookups complexity
before 7 439 330 19987
after (sum of 6 modules) <=2 357 295 3867
Whole-program function complexity drops from 97420 to 81300 (-17%), and the
worst PC_max in the program from 7 to 6. Trace cells for the region fall from
85698 to 16257; rows rise slightly, 207 to 234, but are far narrower.
Behaviour is unchanged. On a KECCAK_ACCEL=true workload (3 hashes, 288
keccak_f rounds) every module the split does not touch matches the parent
commit bit for bit, including value-dependent nonzero-cell counts: keccak_state
93640 lines / 1293622 nonzero, kec_theta 3168 / 738656, kec_squeezing_phase
3 / 100. Identical state contents and squeeze output mean identical hashes.
`zkc exec --check` on the same input exits 0, and `zkc format --check` is clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Olivier Bégassat <olivier.begassat.cours@gmail.com>
Same treatment as the previous commit, applied to what was the second most
expensive keccak module: complexity 9032 with PC_max 3.
kec_theta held two sequential loops -- the D[x] computation and the row mixing
-- after a straight-line block computing the column parities C[x]. Two
back-edges mean two extra PC values on top of the entry block, and the
vectoriser duplicates code into each of them.
Moving each loop into its own function leaves kec_theta straight-line:
module PC_max complexity
kec_theta (before) 3 9032
kec_theta (after) 1 492
kec_theta_d 2 779
kec_theta_mix_rows 2 2396
sum (after) <=2 3667
Whole-program function complexity drops from 81300 to 75935 (-6.6%), for a
cumulative 97420 -> 75935 (-22%) across both splits. Trace cells for the theta
region fall from 1783584 to 477792; rows rise from 3168 to 3744.
Behaviour is unchanged, verified as in the previous commit: on a
KECCAK_ACCEL=true workload every untouched module matches bit for bit,
including keccak_state (93640 lines / 1293622 nonzero), kec_chi, kec_rho,
kec_pi, kec_iota, keccak_f, keccak_f_round and kec_squeezing_phase.
`zkc exec --check` exits 0 and `zkc format --check` is clean.
Note that no PR-gating CI job currently executes this code: the keccak check in
arithmetization-simple-zkc-binary-run-and-go-corset-check.yml builds with
KECCAK_ACCEL=false, so keccak runs in guest software rather than through this
library. Tracked separately.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Olivier Bégassat <olivier.begassat.cours@gmail.com>
OlivierBBB
requested review from
letypequividelespoubelles
and removed request for
Copilot
August 5, 2026 15:17
letypequividelespoubelles
previously approved these changes
Aug 5, 2026
letypequividelespoubelles
left a comment
Contributor
There was a problem hiding this comment.
Lgtm,
Nice comment about perf.
We have an action that tests tracing performance for zkc-keccak, you can put as many keccak rounds you want.
Signed-off-by: Olivier Bégassat <olivier.begassat.cours@gmail.com>
No PR check currently executes arithmetization/src/main/lib/keccak. The existing "Trace Keccak rust and check it" step runs keccak-rust-exec, and KECCAK_ACCEL is only consulted on the zig build path in vector-build -- the rust path (cargo rustc) has no -Dkeccak-accel equivalent. So that step hashes in guest software and never reaches the zkc keccak library. Confirmed empirically: with the committed keccak input, every kec_* module reports 0 rows in `zkc trace --stats`. Only the weekly metrics workflow and the manual keccak-vs-reference benchmark exercise the library today, so library changes can merge with no automated verification -- as the two preceding commits on this branch did. Adds a parallel step using keccak-zig-exec with KECCAK_ACCEL=true, mirroring the rust step: 1 vector, ZKC_EXEC_FLAGS=--check so constraints are validated and not just execution, its own KECCAK_JSON_FILE so the two steps cannot clash, and ZKC_REF="" to avoid reinstalling zkc. Costs no new tooling: zig is already installed by setup-arithmetization-riscv via setup-zig. Measured locally at 52.6s wall including the zig build and a zkc reinstall, against the 15-minute timeout inherited from the rust step. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Olivier Bégassat <olivier.begassat.cours@gmail.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.
No description provided.