Each linear layer now folds the constant of the round that follows it into
its final deferred-carry reduction (or, for the internal rounds, into the
element-0 multiply-add), removing the per-element gf_add before every S-box.
Parity verified. On benjy the effect is within run-to-run noise: three
interleaved rounds gave medians of 418.5 vs 409.7 MH/s against the previous
default, with SM clock swinging 1935-2025 MHz across rounds. Kept on as
LAIR_FOLD_RC=1 for the instruction count; not claimed as a measured gain.
bench.yaml: crates/engine-cuda/** now triggers the harness on PRs. The
previous PR's kernel changes did not run it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CBgs2nSi4H2mdh8kD8vMX5
quantus/miner#3 step 5, measured on benjy (RTX 4090, 250 W, miner paused,
interleaved rounds, parity verified on every variant):
variant MH/s
straight port (PR #16) 297-305
+ grid cap 32768 threads/SM 304 (1 nonce per thread up to 4M)
+ deferred-carry linear layers 344 (+13%)
+ carry-flag gf_add / gf_reduce (PTX) 385 (+12%)
+ carry-flag accumulators 414 (+7%)
414 MH/s is 2.86x origin's wgpu build (144.4) on the same card and limit.
Fewer instructions per hash also let the power-capped card clock higher
(1920 -> 1995 MHz), which is part of the gain.
Rejected by measurement: __noinline__ permute (-13%: code size was not the
limit, the call convention was), -maxrregcount 80/64 (flat), internal-round
unroll 1 or 22 (flat, within noise of 2).
The batch sweep found batch size irrelevant once the grid keeps one nonce
per thread (304-306 MH/s from 1M to 16M); batch stays at 1M for the
smallest stale cost. All knobs remain as -D macros and MINER_NVCC_FLAGS
so the harness can keep testing variants.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CBgs2nSi4H2mdh8kD8vMX5