Repository navigation
dsv4.1-amd: gfx950 sparse decode attention and sorted top-k - #41020
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
candidate_blocks_hip.py sits beside main's candidate_blocks.py: the level-one block scores and top blocks, the top-k within the chosen blocks and the paged top-k sorted in the AOT epilogue, all graph-safe. test_dsv41_decode_glue_hip.py pins them and this PR's attn_glue_hip builders against the torch references. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HaiShaw
left a comment
There was a problem hiding this comment.
Just a few comments to address.
| import triton.language as tl | ||
|
|
||
| from sglang.srt.utils import is_hip | ||
|
|
There was a problem hiding this comment.
Consider to move HIP out of _sm100.py, or rename file is possible.
There was a problem hiding this comment.
Done in 7055e0c: no HIP code in _sm100.py now; the gfx950 entry is swapab_gluon_hip.swapab_attention.
|
|
||
|
|
||
| @triton.jit | ||
| def _aiter_sparse_decode_reduce_kernel( |
There was a problem hiding this comment.
In-tree kernel no need to start with aiter when no origin relevant (in that case use _gfx_sparse_decode_recue_kernel), othereise we do import from it.
There was a problem hiding this comment.
Done: _gfx_sparse_decode_reduce_kernel; file renamed to sparse_decode_reduce_hip.py to match the other _hip.py kernels.
| tl.store(out_ptr + t * out_stride_t + h * out_stride_h + d, out) | ||
|
|
||
|
|
||
| def aiter_sparse_split_reduce( |
There was a problem hiding this comment.
Done: gfx_sparse_split_reduce.
… in-tree split reduce - decode_attention_sm100.py no longer branches on is_hip: swapab_attention takes an optional partial_gluon, and swapab_gluon_hip.py exports the gfx950 swapab_attention bound to its kernel. - aiter_sparse_decode_reduce.py -> sparse_decode_reduce_hip.py (_gfx_sparse_decode_reduce_kernel, gfx_sparse_split_reduce): the kernel is in-tree, only its input layout comes from aiter. - deepseek_v4_topk.cu: the wave-size, DPP/permlane and bitonic helpers and the sort_output epilogue are under USE_ROCM; a CUDA build rejects sort_output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Note on the AMD CI failure in run 36227768892 /
Review comments are addressed in 7055e0c. |
|
Just in case - to double check |
bench_dsv4_topk_transform.py times deepseek_v4_topk_transform_512 unsorted, with sort_output, and unsorted followed by torch.sort (MI350X, decode batch 1-128, 1k-32k keys: the epilogue sort adds ~3.4 us, a separate torch.sort ~17-20 us). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
https://github.com/sgl-project/sglang/actions/runs/36334848845 all PR base passed except for main failure for JIT test |
Summary
ops/attention/sparse_decode_reduce_hip.py:gfx_sparse_split_reducecombines the split-KV partials of aiter's gfx950pa_decode_sparse(..., skip_reduce=True), bitwise equal to aiter's own reduce, with the attention sink and an optional inverse RoPE of each head's tail.ops/attention/dsv4/compact_attention_hip.py: sparse decode attention that reads the compact V4.1 pages (528 B fp8 + ue8m0, 288 B e2m1 + e4m3) directly through aiter's gfx950_qkpv_fp8, with main and extra slot ranges and 16-head groups.ops/attention/dsv4/swapab_gluon_hip.py: the 16-head swap-AB Gluon kernel for HIP, argument-compatible with the SM100 kernel (CDNA4 MFMA, bf16 hi + lo compensated PV). It reuses the SM100 module's_load_v4, which is plain Gluon;swapab_attentiongainsinv_rope=None.ops/attention/dsv4/attn_glue_hip.py: single-launch Triton replacements for the torch glue around the V4.1 sparse decode metadata, each bitwise equal to the torch expression in its docstring.deepseek_v4_topk.cu,sgl_kernel/top_k.py):sort_outputsorts each row's picks ascending with a block-wide bitonic sort,-1padding last; the selected set is unchanged; the sort is ROCm-only (underUSE_ROCM). Strides below the wave width use lane shuffles and the rest LDS, so it is also right on 32-lane waves (gfx1250).benchmark/bench_dsv4_topk_transform.pytimes it: on MI350X the sort adds ~3.4 us per call, where a separatetorch.sortcosts ~17-20 us.q_rope_store.pyon HIP rounds like the batched HIP RoPE kernel.ops/attention/dsv4/candidate_blocks_hip.py, beside main'scandidate_blocks.py: the V4.1 two-level indexer's level-one block scores and top blocks, the top-k within the chosen blocks and the paged top-k sorted in the AOT epilogue, graph-safe.Changes to existing kernels
decode_attention_sm100.py:swapab_attentiontakes an optionalpartial_gluon(swapab_gluon_hip.swapab_attentionbinds the gfx950 kernel), with no HIP branch in the SM100 file;_combinecompiles the inverse RoPE out wheninv_rope=None, so SM100 output is unchanged.decode_attention_sm100_gluon.pyis untouched.q_rope_store.py: the new branch is a HIP-only constexpr; CUDA arithmetic is unchanged.setup_rocm.py); withsort_output=Falsethe kernel is the same, plus a 4 KB static LDS array. The wrapper always passessort_output, so sgl-kernel must be rebuilt from this PR.sort_output=Trueyet (the one existing caller,ops/attention/dsv4/topk.py, still uses the 6-argument form, which the default keeps working). Callers will only passsort_output=Trueafter sgl-kernel is released and thesglang-kernelpin is bumped to 0.4.8 or later, following How to update kernels in SGLang.Verification
test_swapab_attention.py(SM100 and gfx950: fp64 reference over padded and poisoned pages,-1/ out-of-range slots, sinks, graph replay, and the combine's inverse RoPE bitwise tofused_rope_inplace);test_compact_attention_hip.py(both packed layouts, a second cache,-1slots and a key-less row against a torch softmax with sink);test_topk.py::test_deepseek_v4_topk_transform_sorted_output;test_dsv41_decode_glue_hip.py(candidate blocks against main'sselect_candidate_block_idswith garbage past each row's reach, the sorted mapping, and theattn_glue_hipbuilders bitwise to their torch forms).test_dsv4_q_rope_store.pyis now also registered for AMD.test_swapab_attention.py,test_dsv4_q_rope_store.py.Stack
main. Independent of dsv4.1-amd: gfx950 MXFP8 matmul kernels and fp8-grid producers #41018 (gfx950 MXFP8 matmul kernels) and dsv4.1-amd: KV cache layouts, FP4 indexer, compressor and router kernels #41019 (KV cache layouts, FP4 indexer, compressor and router kernels).🤖 Generated with Claude Code
CI States
Latest PR Test (Base): ❌ Run #36477152106
Latest PR Test (Extra): ✅ Run #36477151594
Latest PR Test (AMD ROCm 10): ⏳ Run #36477151949