[Lightning Attention] Add Hopper SM90 CuTe DSL prefill - #111
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
|
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 |
icavan
left a comment
There was a problem hiding this comment.
One portability note regarding the TensorMap workspace indexing:
|
Follow-up after the TensorMap portability review: the PR is now resealed on exact pushed head
Final-source validation:
The PR body has been updated with the complete source-bound C++ and FLA tables and the final validation boundary. |
zheyang0825
left a comment
There was a problem hiding this comment.
One packaging compatibility issue:
|
Additional context for the dependency constraint
These are relevant risks for this kernel because the Lightning SM90 implementation relies heavily on register-resident accumulators and DSL-lowered recurrent loops. To be precise, we did not claim a Lightning-specific reproduction on 4.5.0; we conservatively excluded the known-bad compiler release and qualified 4.5.1, 4.5.2, and 4.5.3 instead. |
📌 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;
plus TMA stores for packed ragged tails;
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, stable TensorMap-slot repair, and decay-LUT
warp-ordering repair are separate commits so their implementations 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
The final evidence is bound to pushed PR head
247941ee0addb6de4c279fda31f2389fa5863c19.Validation environment:
43/43pass.38/38rows pass.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.
stateful, GVA, packed non-persistent, and packed persistent paths.
produce the same output/state hashes as commit 1.
dispatcher-visible violations.
17/17pass — 5 memcheck, 4 synccheck,and 8 racecheck attempts, with zero racecheck hazards.
10/10specializations, 9 unique cubins,exactly two new warp barriers per specialization, 24 WGMMA per
specialization, no
%smid/SR_VIRTUALSMID, and zero spill/stack/localmemory.
195/195files match locally and on H20.git diff --checkpass.🔬 Accuracy vs original C++ implementation
The source-bound comparison uses 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.
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, rotated order, 20 warmups, 100 CUDA-event timed
iterations, unique CuTe caches, and audited receipts. A CuTe/C++ ratio below
1.0xmeans CuTe is faster.f_b1_t512_z1.007817xf_b2_t512_z1.013862xf_b1_t4096_z1.023541xf_b2_t4096_z1.022250xf_b1_t16384_z1.024296xf_b1_t512_h00.991493xf_b1_t4096_h01.021695xf_b1_t16384_h01.023789xp_uniform_4096_h01.024249xp_skewed_8192_h01.012313x1.016481xThe 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.65%slower in geometric mean and within2.43%of the prepared original C++ kernel on every row of this matrix.⚡ Final-source CuTe vs FLA
This table reseals the comparison on exact pushed PR head
247941ee0addb6de4c279fda31f2389fa5863c19.The reference is FLA
chunk_simple_glaatcca521e9efa50d2859f27702923ad1ff46305dee(FLA 0.5.1, Triton 3.5.1).Both implementations ran on the same NVIDIA H20-3e GPU in BF16 with D=128 and
chunk size 64. Ratios are CuTe latency / FLA latency, so lower than 1 means
CuTe is faster.
Acceptance and protocol
output/state parity and untouched state-pool slots passed on 20/20 rows.
7.62939453e-06, relative RMS3.14672361e-04.7.86771998e-05, relative RMS7.14503476e-05.three process replicas per implementation, with fixed rows alternating
FLA/CuTe, packed rows using a three-way round-robin, and compile/first-call
latency excluded.
contention-invalid receipt, or missing row. No ratio entered the frozen
±3% band, so five-process escalation was not triggered.
the final default non-persistent scheduler. The explicit persistent scheduler
and four GVA rows are reported as secondary results.
0.638699x1.57x0.254419x0.839356x0.200602x4.98x0.085684x0.504235x0.345958x2.89x0.085684x0.839356x0.207320x4.82x0.087398x0.538515x0.404571x2.47x0.154392x0.827973x0.351705x2.84x0.085684x0.839356xThe final-source CuTe path is faster on all 34/34 primary native-MHA rows
and all 38/38 logical rows. The worst primary row is
f_ns_b2_t4096at0.839356x, or about 16.1% lower latency (1.19xreciprocal speedup).
Full fixed-length final-source results (18 rows)
f_ns_b1_t5120.254419xf_ns_b1_t10240.470259xf_ns_b1_t40960.829716xf_ns_b1_t81920.832205xf_ns_b1_t163840.816871xf_ns_b2_t5120.479273xf_ns_b2_t10240.825689xf_ns_b2_t40960.839356xf_ns_b2_t81920.816217xf_ns_b2_t163840.795113xf_st_b1_t5120.262311xf_st_b1_t40960.813494xf_st_b1_t163840.798796xf_st_b2_t5120.468393xf_st_b2_t40960.832438xf_st_b2_t163840.793222xg_ns_b1_t4096_hv0.827973xg_st_b1_t4096_h0.813302xFull packed-variable-length final-source results (20 rows)
p_uniform_n10_t40960.156928x0.159585xp_random_n10_t40960.140523x0.158614xp_skewed_n10_t40960.149307x0.151244xp_uniform_n10_t81920.266027x0.271445xp_random_n10_t81920.266710x0.284933xp_skewed_n10_t81920.268201x0.271871xp_uniform_n10_t163840.501317x0.510581xp_random_n10_t163840.487773x0.538515xp_skewed_n10_t163840.504235x0.511696xp_uniform_n20_t40960.098298x0.098807xp_random_n20_t40960.085684x0.089613xp_skewed_n20_t40960.087352x0.087398xp_uniform_n20_t81920.150148x0.152005xp_random_n20_t81920.138682x0.145848xp_skewed_n20_t81920.141078x0.141609xp_uniform_n20_t163840.254165x0.259215xp_random_n20_t163840.251966x0.268964xp_skewed_n20_t163840.258799x0.260990xg_puni_n10_t4096_hv0.154392x0.157328xg_pskew_n20_t16384_h0.257683x0.259254x⚡ Direct synchronization-cost check
The final decay-LUT synchronization commit was also compared directly against
the accepted stable-slot commit on eight fixed and packed paths, using five
fresh processes per source and alternating order.
8/880/800.999511x1.000424xThe explicit warp synchronization is therefore inside the frozen
<=1.03xgeomean and
<=1.05xper-path guardrails.This is kernel-only H20 BF16 prefill evidence. It does not claim decode,
backward, other head dimensions, other GPUs, or end-to-end serving performance.
🚀 Pull Request Checklist
git diff --check.Reviewer notes
the register-resident state lifetime, packed tail TensorMap replacement/TMA
stores, stable logical TensorMap-slot ownership, and the persistent CTA
rendezvous between work units.
sequence_idx * value_heads + value_head_idx; persistent scheduling usesstable logical
cta_idx. Device code no longer uses%smid.[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.