Add decode (flash-decoding) attention kernels to contributed/ - #129
Add decode (flash-decoding) attention kernels to contributed/#129varuntej07 wants to merge 3 commits into
Conversation
|
Thanks for this contribution! I ran both kernels on a Trainium2 instance (with the changes below) and the outputs match the NumPy reference, including the online-softmax GQA path. Before this merges, can you please make the following updates, which works with the latest version of NKI? These kernels import The change is small. Imports: The only API difference is that nisa.tensor_copy and nisa.tensor_scalar now write into a destination tile instead of returning one: The same transform applies to the remaining tensor_copy / tensor_scalar calls in both kernels (the dtype= argument moves onto the destination tile's allocation). Everything else carried over unchanged: nl.matmul(..., transpose_x=True), nl.transpose, nl.max/sum/exp/reciprocal/add, nl.load/store, and all the shapes and the online-softmax loop. Once these changes are made, I should be able to approve the merge. |
mrkcath-aws
left a comment
There was a problem hiding this comment.
Changes summarized in previous comment
|
Thanks for the review and Trainium2 validation. I’ve updated both kernels to use the top-level nki imports and converted all tensor_copy and tensor_scalar calls to the destination-style API. Ready for another review. |
Description of changes:
Adds a new community kernel file,
contributed/decode_attention.py, implementing the decode (single-query) step of autoregressive attention. This is the memory-bound complement to the compute-bound prefill kernel incontributed/pipelined_attention.py.Two kernels are included:
decode_attention_fwd- simplest correct version: one head, one KV tile,seqlen_kv <= 128. A single query position (seqlen_q = 1) attends over the full cached K/V, running QK -> scale -> softmax -> PV with the softmax scale applied.decode_attention_gqa_fwd- lifts the length limit with KV tiling and a running online softmax (state carried across tiles), and adds grouped-query attention so query heads sharing a KV head also share its K/V loads (loaded once per group).Both use the d-on-partition-axis layout from the existing attention tutorials.
IO layouts:
decode_attention_fwd: q(d, 1), k(d, seqlen_kv), v(d, seqlen_kv)-> o(1, d)decode_attention_gqa_fwd: q(d, n_q_heads), k/v(n_kv_heads, d, seqlen_kv)-> o(n_q_heads, d)Current limits:
d <= 128; GQA requiresn_q_heads % n_kv_heads == 0andseqlen_kv % TILE_KV == 0(no padding yet); single batch element. Split-KV flash-decoding for very long context is noted as planned future work.This kernel targets
contributed/, notsrc/reference/, so the baremetal /benchmark / integration requirements (which CONTRIBUTING.md scopes tosrc/reference/) do not apply. Correctness is validated on CPU vianki.simulate_kernelagainst NumPy reference implementations included in the file (numpy_decode_referenceandnumpy_decode_gqa_reference, therepeat_kv+per-head softmax oracle). Runpython contributed/decode_attention.pyto execute both checks; the GQA case exercises 4 KV tiles with group = 4 and asserts agreement withinatol = rtol = 1e-2. The kernels are not yet run on Neuron hardware; this is stated in the module docstring WARNING.