[Lightning Attention] Add Hopper SM90 CuTe DSL prefill - #111
[Lightning Attention] Add Hopper SM90 CuTe DSL prefill#111Aharrypotter wants to merge 5 commits into
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
c5a534d to
c792bbe
Compare
|
Thanks for asking. I reran the comparison on the exact pushed PR head The comparison uses the shared semantic subset: BF16 Q/K/V/O, FP32 recurrent state, D=128, chunk size 64, 64-head MHA, scale=1, Accuracy:
Performance:
So on this frozen common-subset matrix, the final CuTe DSL source is about |
📌 Description
This PR adds a Hopper SM90 Lightning Attention prefill backend implemented in
CuTe DSL.
cula/ops/lightning/sm90/, with the FP32 recurrent state resident inregisters across 64-token chunks;
lightning_attn_fwdandlightning_attn_fwd_varlenAPIs with architecture dispatch across theexisting SM100/SM103 backend and the new SM90 backend;
initial/final state, MHA and GVA head mappings, explicit state-pool indices,
and persistent or non-persistent packed scheduling;
validation and host synchronization;
dispatch tests, a prefill-specific benchmark, and Hopper pipeline
documentation.
The supported SM90 specialization uses BF16 Q/K/V/O, FP32 decay and recurrent
state, key/value dimension 128, and chunk size 64. Unsupported architectures
or specializations fail explicitly rather than silently falling back.
The packed-tail TMA optimization is a separate commit so its implementation
and evidence can be reviewed independently.
🔍 Related Issues
This work is intentionally separate from #76, which tracks Gated DeltaNet
rather than Lightning Attention.
🧪 Final-source validation
Validation environment:
40/40pass.10/10precision rows and10/10timing-admission rows pass three-way checks against an independent FP32
tokenwise reference.
the affected-path matrix; unselected state-pool slots remain unchanged.
dispatcher-visible violations, including a cold TensorMap-workspace
allocation.
mode, bitwise concurrent-versus-serialized parity, and stable distinct
per-stream TensorMap workspaces.
9/9pass(5 memcheck and 4 synccheck).
10/10specializations, 9 unique cubins,24 WGMMA per specialization, and zero spill/stack/local memory.
git diff --checkpass.🔬 Accuracy vs original C++ implementation
We added a source-bound comparison against the original FlashInfer SM90
C++/CUTLASS implementation (
7086b148, CUTLASSf3fde583).The comparison freezes the common semantic subset: BF16 Q/K/V/output, FP32
state, D=V=128, C64, MHA (
H=HV=64),scale=1,lambda=exp(-slope)with exponent offset 1, unique sequential state slots,fixed/packed execution, and final-state output.
The common subset is necessary because the original and cuLA public contracts
differ in GVA ownership, non-unit scale ownership, optional final state,
packed scheduling, and indirect/shared state-pool ownership. This is therefore
a numerical comparison on the common subset, not a whole-API equivalence
claim.
The final-source comparison is bound to pushed PR head
93da019.10/101.2207e-46.6605e-50.999999997899.9409%2.4214e-82.0957e-70.999999999999985513.9045%100%The implementations are not fully bitwise identical because the recurrent
accumulations use different instruction schedules. The supported conclusion is
numerical alignment under the frozen tolerance contract, not complete bitwise
parity.
⚡ Performance vs original C++ implementation
The primary denominator is the original C++
Operation::runafter one-timeworkspace allocation and operation initialization. Every row uses five fresh
processes per implementation after triggering the pre-registered three-percent
escalation rule, rotated order, 20 warmups, 100 CUDA-event timed iterations,
unique CuTe caches, and audited receipts. A CuTe/C++ ratio below
1.0xmeansCuTe is faster.
f_b1_t512_z1.014086xf_b2_t512_z1.009814xf_b1_t4096_z1.023216xf_b2_t4096_z1.021983xf_b1_t16384_z1.023239xf_b1_t512_h01.001476xf_b1_t4096_h01.019886xf_b1_t16384_h01.022518xp_uniform_4096_h01.025548xp_skewed_8192_h01.014649x1.017616xThe pre-registered limits were a ten-row geomean
<=1.10x, every row<=1.25x, and the critical skewed packed row<=1.10x; all pass. There werezero contention-invalid receipts, fallbacks, skips, or missing rows. The final
CuTe DSL source is therefore about
1.76%slower in geometric mean and within2.56%of the prepared original C++ kernel on every row of this matrix.⚡ Canonical CuTe vs FLA baseline
Before the packed-tail TMA optimization, the canonical H20 matrix contained
38 fixed and packed-variable-length workloads: 34 native-MHA rows used for
the primary geometric mean and four GVA rows reported separately. All rows use
BF16 Q/K/V, FP32 decay/state, D=128, and chunk size 64.
This frozen P7-B matrix is retained as the broad CuTe-vs-FLA baseline. The
final packed-tail TMA source is faster on the two same-boundary packed rows
screened above, so these packed FLA numbers are conservative rather than
final-source claims.
For every row and implementation:
<= 1.10x0.487849x<= 1.25x0.960543x38/38, all ratios< 1.0x0.738844x1.35x0.278828x0.958029x0.704192x1.42x0.289854x0.960543x0.338190x2.96x0.184498x0.710279x0.350382x2.85x0.199508x0.711503x0.339864x2.94x0.193118x0.677091x0.725654x1.38x0.278828x0.960543x0.342770x2.92x0.184498x0.711503x0.487849x2.05x0.184498x0.960543x0.544746x1.84x0.257395x0.942551xFull fixed-length CuTe/FLA baseline (18 rows)
f_ns_b1_t5120.278828x3.59xf_ns_b1_t10240.514456x1.94xf_ns_b1_t40960.942691x1.06xf_ns_b1_t81920.940729x1.06xf_ns_b1_t163840.921564x1.09xf_ns_b2_t5120.536362x1.86xf_ns_b2_t10240.939967x1.06xf_ns_b2_t40960.958029x1.04xf_ns_b2_t81920.929115x1.08xf_ns_b2_t163840.921436x1.09xf_st_b1_t5120.289854x3.45xf_st_b1_t40960.929458x1.08xf_st_b1_t163840.916827x1.09xf_st_b2_t5120.560548x1.78xf_st_b2_t40960.960543x1.04xf_st_b2_t163840.916900x1.09xg_ns_b1_t4096_hv0.942551x1.06xg_st_b1_t4096_h0.924688x1.08xFull packed-variable-length CuTe/FLA baseline (20 rows)
p_uniform_n10_t40960.260871x3.83xp_uniform_n10_t81920.433846x2.30xp_uniform_n10_t163840.710279x1.41xp_uniform_n20_t40960.184498x5.42xp_uniform_n20_t81920.246745x4.05xp_uniform_n20_t163840.408822x2.45xp_random_n10_t40960.268295x3.73xp_random_n10_t81920.443471x2.25xp_random_n10_t163840.711503x1.41xp_random_n20_t40960.199508x5.01xp_random_n20_t81920.267564x3.74xp_random_n20_t163840.409454x2.44xp_skewed_n10_t40960.271807x3.68xp_skewed_n10_t81920.409844x2.44xp_skewed_n10_t163840.677091x1.48xp_skewed_n20_t40960.193118x5.18xp_skewed_n20_t81920.265651x3.76xp_skewed_n20_t163840.398264x2.51xg_puni_n10_t4096_hv0.257395x3.89xg_pskew_n20_t16384_h0.392534x2.55xThe benchmark entry point is:
🚀 Pull Request Checklist
git diff --check.Reviewer notes
the register-resident state lifetime, packed tail TensorMap replacement/TMA
stores, and the persistent CTA rendezvous between work units.
[V, K]orientation. The independentreference checks recurrence direction, same-token causality, GVA mapping,
continuation, state-pool isolation, and packed persistent parity.
Final codegen reports 24 WGMMA/HGMMA operations and zero spill/stack/local
memory for every validated specialization.
other than 128, and chunk sizes other than 64 are out of scope.