An independent, single-GPU empirical characterization of ICICLE v4.0.0's NTT on a consumer NVIDIA Blackwell GPU — where time actually goes, end to end and per kernel — plus a prototype that quantifies one recoverable bottleneck.
Shared in case it is useful to the ICICLE community and others bringing GPU ZK stacks to consumer Blackwell. Methodology is empirical before theoretical: every claim is a measurement, and the negative results are reported with the same weight as the positive one.
Full write-up with all profiles and interpretation: REPORT.md.
- ICICLE runs on Blackwell only through PTX-JIT. The shipped v4.0.0 CUDA backend embeds SASS up to sm_89 (Ada) plus
compute_89PTX, but no sm_120 cubin; the driver JIT-compiles the PTX to sm_120 at first launch. This is more robust than most of the ecosystem (which ships no PTX and hard-fails on Blackwell), but it carries first-launch JIT latency and a PTX-forward-compatibility dependency. - No JIT throughput penalty on field arithmetic. A BabyBear Montgomery-modmul kernel built native sm_120 vs
compute_89-PTX-then-JIT measured within run-to-run noise (1213 vs 1257 Gmodmul/s). A native build's value is removing JIT latency and the PTX dependency, not speeding up the arithmetic. - Butterflies are already at the memory ceiling; the digit-reversal pass is the bottleneck. At 2²²,
ntt64runs at 84.7% andntt32ditat 76.5% of DRAM peak. The single largest kernel,reorder_digits_and_normalize(39% of NTT kernel time), runs at only 46% of peak with a global-store efficiency of 4 of 32 bytes per sector (12.5%) — the textbook scatter signature of digit reversal. - That headroom is recoverable (prototype). On the same GPU/size/dtype, a scattered bit-reversal reproducing ICICLE's exact 4/32 store signature runs at ~375 GB/s, while a shared-memory-staged coalesced permutation runs at ~780 GB/s (~2×). Since the reorder is 39% of NTT kernel time, a coalesced (COBRA-style) digit-reversal would translate to an estimated ~15–20% end-to-end NTT speedup.
| Measurement (RTX 5070, 2²² BabyBear) | Result |
|---|---|
| modmul — native sm_120 vs JIT compute_89 | 1212.8 vs 1256.9 Gmodmul/s (within noise) |
ntt64 DRAM throughput |
84.7% of peak |
ntt32dit DRAM throughput |
76.5% of peak |
reorder_digits_and_normalize — share / DRAM / store eff. |
39% of NTT time / 46.2% of peak / 4-of-32 bytes/sector |
| coalesced copy (bandwidth ceiling) | ~1320 GB/s |
| scattered bit-reversal (= ICICLE reorder pattern) | ~375 GB/s |
| shared-memory tiled transpose (coalesced permutation) | ~780 GB/s (~2.1×) |
| single-shot NTT over host data (2²²) | ~74% PCIe, ~12% compute |
benchmarks/
bench_modmul.cu # Finding 2: native sm_120 vs JIT compute_89 modmul throughput
ntt_bench.cpp # Findings 1 & 3: ICICLE NTT harness (links the v4 babybear frontend)
bitrev_bench.cu # Finding 4: recoverable-bandwidth prototype (copy / scatter / transpose)
REPORT.md # full characterization, profiles, and interpretation
# Finding 2 — field-arithmetic JIT vs native (no ICICLE needed)
nvcc -O3 -arch=sm_120 benchmarks/bench_modmul.cu -o bench_native
nvcc -O3 -gencode arch=compute_89,code=compute_89 benchmarks/bench_modmul.cu -o bench_jit
./bench_native 2048 ; ./bench_jit 2048
# Finding 4 — recoverable-bandwidth prototype (no ICICLE needed)
nvcc -O3 -arch=sm_120 benchmarks/bitrev_bench.cu -o bitrev_bench
./bitrev_bench
sudo -E $(which ncu) --kernel-name "regex:k_copy|k_bitrev_scatter|k_transpose_tiled" \
-c 3 --section MemoryWorkloadAnalysis ./bitrev_bench
# Findings 1 & 3 — ICICLE NTT harness (needs ICICLE v4 babybear frontend + CUDA backend)
# see header of benchmarks/ntt_bench.cpp for the exact build/link line
export ICICLE_BACKEND_INSTALL_DIR=$HOME/ingo/icicle-cuda-backend/icicle/lib/backend
./ntt_bench 24 # sweep 2^16..2^24
nsys profile --stats=true ./ntt_bench 22 22 # kernel + memcpy breakdown
sudo -E $(which ncu) --kernel-name "regex:ntt32dit|ntt64|reorder_digits" -c 6 --set basic ./ntt_bench 22 22Each harness is a single, correctness-gated file; build/run/profile commands are in its header comment.
RTX 5070 (GB205, sm_120, 48 SMs, ~672 GB/s GDDR7, ~48 MB L2) · driver 575.57.08 / CUDA 12.9 · Ryzen 7 9800X3D, 128 GB · Ubuntu 24.04 (kernel 6.8) · ICICLE v4.0.0 (frontend from source, FIELD=babybear; CUDA backend ubuntu22-cuda122). All numbers are from this single machine.
MIT — see LICENSE. The harnesses are original; they call ICICLE through its public API and do not redistribute it.