Skip to content

test(gpu): make test-cuda-d1 actually exercise DECODE - #947

Open
MauroToscano wants to merge 1 commit into
decode-deep-fri-gpufrom
fix/946-d1-test-exercises-decode
Open

test(gpu): make test-cuda-d1 actually exercise DECODE#947
MauroToscano wants to merge 1 commit into
decode-deep-fri-gpufrom
fix/946-d1-test-exercises-decode

Conversation

@MauroToscano

Copy link
Copy Markdown
Contributor

Targets decode-deep-fri-gpu (#946), not main — the code it fixes only exists on that branch.

The problem

test-cuda-d1 sets LAMBDA_VM_GPU_LDE_THRESHOLD=64 on the premise that 64 is "the exact LDE size of fib_iterative_1M's DECODE ROM". It is 32, and the reasoning behind the number is also wrong: DECODE's rows come from the ELF's executable words, not from cycles.

  • fib_iterative_1M has one executable PT_LOAD of 52 bytes = 13 words (li a0, 199999 expands to lui+addi). executor/src/elf.rs iterates exact p_memszp_align is bound as _p_align and never read, so there is no page rounding.
  • 13 + 1 CPU-padding entry = 14 → next_power_of_two() = 16 rows → blowup 2 → DECODE LDE 32.
  • At threshold 64 that is below the gate, so DECODE fails the R1 split-tree commit, has no gpu_main() handle, and evaluate_dev declines. DECODE never reaches the d=1 path at all.

So the counter could only ever be fed by KECCAK_RC — the only other num_parts == 1 table (a d=1 table is one with a single bus interaction), fixed at NUM_ROWS = 32 → LDE 64, passing 64 < 64 by one unit. The make target, the test name, the module docs and the assert message all named the one d=1 table guaranteed not to be exercised.

Why the threshold alone can't fix it

DECODE (32) sits below KECCAK_RC (64), so with a fib fixture no threshold isolates DECODE: <=32 engages both, 33..=64 engages only KECCAK_RC. The fixture has to change — and no fib_iterative_* variant helps, since they differ only in the li a0, <count> immediate (fib_iterative_16M is 13 words too).

The fix

Switch to all_instructions_64 — 66 executable words → 128 rows → DECODE LDE 256 — at threshold 128. DECODE engages with 2× margin, KECCAK_RC (64) declines, so a nonzero gpu_comp_h_slabs_calls() uniquely attributes to DECODE.

128 is also higher than the previous 64, so strictly fewer tables land on the GPU-committed path: it narrows rather than widens the R4 gather_proofs_dev abort site that gpu_lde.rs warns about for lowered thresholds.

The test's own guard is tightened too. thr > 0 && thr < 1<<14 passed vacuously for any wrong value — including the 64 that caused this — so it now pins the window to (KECCAK_RC_LDE, DECODE_LDE] against named constants.

Verification

Arithmetic verified by parsing both ELFs' program headers directly and reading the sizing chain (elf.rs segment loop → decode.rs padding → with_blowup(2)). all_instructions_64 is a known-good provable fixture (prove_elfs_tests.rs, disk_spill_tests.rs).

Not executed — no GPU available here, so the change is arithmetically verified but unrun. One merge-queue Group 3 log line confirms it. Note this is also the run that settles whether KECCAK_RC currently engages at all: if it does not, the existing target has been failing, and this fix is what makes the group meaningful either way.

Trade-off worth a look

all_instructions_64 is a small program, so at threshold 128 most other tables also decline the GPU path — the test covers the d=1 wiring on a minimal proof rather than inside a steady-state prove. The full chain still runs for DECODE (de-interleave → R2 commit → R3 OOD → R4 DEEP → FRI → openings) and the final verify is real. Having both would need a new ≥32-instruction loop fixture, which felt out of scope here.

`test-cuda-d1` set LAMBDA_VM_GPU_LDE_THRESHOLD=64 on the premise that 64 is
"the exact LDE size of fib_iterative_1M's DECODE ROM". It is 32, and the
reasoning behind the number was wrong too: DECODE's rows come from the ELF's
executable words, not from cycles.

fib_iterative_1M is 13 executable words (one 52-byte executable PT_LOAD; the
variants differ only in the `li a0, <count>` immediate, so fib_iterative_16M is
13 too). 13 + 1 CPU-padding entry = 14 -> next_power_of_two() = 16 rows ->
blowup 2 -> DECODE LDE 32. At threshold 64 that is below the gate, so DECODE
failed the R1 split-tree commit, had no gpu_main() handle, and evaluate_dev
declined - DECODE never reached the d=1 path at all.

The counter could therefore only be fed by KECCAK_RC, the only other
num_parts==1 table (a d=1 table is one with a single bus interaction), whose
fixed NUM_ROWS=32 gives LDE 64 and passes `64 < 64` by one unit. So the target,
the test name, the module docs and the assert message all named the one d=1
table guaranteed not to be exercised.

No threshold fixes this with a fib fixture: DECODE (32) sits below KECCAK_RC
(64), so <=32 engages both and 33..=64 engages only KECCAK_RC. Switch to
all_instructions_64 - 66 executable words -> 128 rows -> DECODE LDE 256 - at
threshold 128, where DECODE engages with 2x margin and KECCAK_RC declines, so a
nonzero gpu_comp_h_slabs_calls() uniquely attributes to DECODE.

128 is also higher than the previous 64, so strictly fewer tables land on the
GPU-committed path: it narrows rather than widens the R4 gather_proofs_dev abort
site that gpu_lde.rs warns about for lowered thresholds.

Tighten the test's own guard while here. `thr > 0 && thr < 1<<14` passed
vacuously for any wrong value - including the 64 that caused this - so pin the
window to (KECCAK_RC_LDE, DECODE_LDE] against named constants instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant