Skip to content

GLM-5 DSA indexer fusion on ROCm (diff vs upstream main) - #1

Draft
Jacob0226 wants to merge 311 commits into
base/upstream-main-glm5-indexerfrom
jacob/glm5-dsa-indexer-fusion-unified
Draft

Jacob0226 wants to merge 311 commits into
base/upstream-main-glm5-indexerfrom
jacob/glm5-dsa-indexer-fusion-unified

Conversation

@Jacob0226

@Jacob0226 Jacob0226 commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Self-review only, not for upstream. Base is the branch behind sgl-project#34394, so this shows exactly what has changed since that PR was last pushed.

Commits

  1. Pass fp32 LayerNorm params to the aiter fused indexer kernel — aiter post-[Bug] Error while serving deepseek-ai/DeepSeek-V2-Lite in NVIDIA A40-48Q sgl-project/sglang#3451 requires norm_weight/norm_bias as fp32 and aborts at the host check otherwise. _k_norm_params() loses its dtype argument and always widens to fp32, so the contract lives in the code instead of in the caller remembering to pass the right thing. Without this the server SIGABRTs on the first decode against current aiter.

  2. Ask the model whether the indexer merged weights_proj — replaces the module-level _use_dsa_indexer_fusion mirror with indexer_merges_weights_proj(model), which queries the built Indexer instances. The mirror read the env through get_bool_env_var() while the instance read it through envs.…get() (these disagree on values like yes), and it dropped is_neox_style, so neox models were wrongly rejected by the LoRA validation.

  3. Collapse the indexer fusion flags into oneuse_dsa_indexer_fusion, merge_wk_weights_proj and use_aiter_indexer_fusion all answered "is the indexer q/k path fused?" from three angles. They also disagreed: the merged GEMM was on for every ROCm device while only gfx95 had a fused kernel to feed it. Now one flag, ROCm opts in only where aiter can actually run; the platform split moves to the two call sites that need it. is_aiter_gfx950 becomes aiter_indexer_qk_fusion_available.

Reviewing tips

k_norm moved ahead of the projections (the fusion decision reads its type), which shifts a block of lines — use "Hide whitespace" and read dsa_indexer.py by commit rather than as a combined diff.

Known scope

Non-gfx95 ROCm loses the merged GEMM. That configuration was never validated end to end, but it does mean parameter layout is now tied to kernel availability, so the merged GEMM can no longer be A/B'd on its own without reinstating an override env.

Prefill still excluded

Measured on MI355X TP4, GLM-5.2-MXFP4, extend chunk 7679 tokens: the fused kernel is 228.8 us/layer against 99.5 us for the split kernels it replaces, while in decode it is 5.6 vs 30.4. The cause is aiter's launch geometry (grid(num_tokens, n_heads), block(head_dim)): one 128-thread workgroup per (token, head) with one bf16 per thread, so block_reduce goes through LDS and every wave moves 128 B per memory instruction. It sustains ~430 GB/s, about 5% of HBM peak, so this is a kernel-tuning problem on the aiter side rather than a reason prefill cannot be fused.

Made with Cursor


CI States

Latest PR Test (Base): ❌ Run #32316103572
Latest PR Test (Extra): ❌ Run #32316103421

zijiexia and others added 30 commits August 14, 2026 15:42
)

Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
Co-authored-by: yhyang201 <yhyang201@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: hjzhang <76768149+1e4ves@users.noreply.github.com>
Co-authored-by: YAMY <74099316+YAMY1234@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ect#34781)

Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
Co-authored-by: sglang-bot <sglang-bot@users.noreply.github.com>
… MTP notation (sgl-project#31554)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Vedant Jhaveri <vjhaveri@linkedin.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…dels (sgl-project#32414)

Co-authored-by: Ryan Lucas <ryanluc@mit.edu>
Co-authored-by: Kayhan Behdin <kbehdin@linkedin.com>
Co-authored-by: Zhipeng Wang <zwanga@wustl.edu>
…structural tags (sgl-project#34778)

Co-authored-by: James Liu <jamesl@modal.com>
…per (sgl-project#34771)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: weireweire <20922698+weireweire@users.noreply.github.com>
…ject#34877)

Co-authored-by: Zhiyao Jiang <jessicajiang324@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Michael <michaelzhang-ai@users.noreply.github.com>
…-project#34789)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
michaelzhang-ai and others added 15 commits August 19, 2026 00:17
…mos3-Nano startup) (sgl-project#34485)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Michael <michaelzhang-ai@users.noreply.github.com>
Co-authored-by: bingxche <bingxche@users.noreply.github.com>
Co-authored-by: Jimmy Shong <69131491+Jiminator@users.noreply.github.com>
Co-authored-by: Brayden Zhong <brayden.zhong@radixark.ai>
Co-authored-by: BBuf <1182563586@qq.com>
Co-authored-by: Zijie Xia <zijie.xia@radixark.ai>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Qiaolin Yu <liin1211@outlook.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: HeYao <heyao@example.com>
…ched_gemm_bf16 (sgl-project#33313)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Thomas Wang <thomawan@amd.com>
…els (sgl-project#32611)

Co-authored-by: Singh <rohitsi2@iil-login.iind.intel.com>
…ernel

ROCm ran the DSA indexer q/k preparation as a chain of separate kernels:
k LayerNorm, RoPE, fp8 quant into the paged index-k cache, then q Hadamard
and quant, then the head-gate scale. aiter's indexer_qk_rope_quant_and_cache
covers all of it in one launch, and fusing lets the Hadamard rotation go
entirely -- the indexer logits are invariant to it, so dropping it is safe as
long as the write and the read back agree on the basis.

ROCm now shares upstream's use_dsa_indexer_fusion flag rather than carrying a
separate opt-in. On gfx95 the flag additionally requires a LayerNorm k_norm,
head_dim 128, rope_head_dim 64 and block_size == head_dim, which is what the
kernel accepts. The flag also folds wk and weights_proj into one bf16
wk_weights_proj parameter, so the weight loader fills it from either shard and
indexer LoRA, which wraps modules that no longer exist, now raises instead of
being silently dropped.

Two places needed the platform test that the flag used to imply: the k-only
prefill path, which has no aiter counterpart, and the graph head-gate scale,
whose custom op is CUDA-only.

Measured on MI355X, GLM-5.2-MXFP4 TP4, 8k prefill, per indexer layer per
forward: 189.3 -> 55.3 us, a 3.4x cut worth ~2.8 ms per forward across the 21
indexer layers. Needs an aiter carrying the vectorized form of the kernel; the
earlier scalar one runs at 228 us and is slower than the unfused path.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Jacob0226
Jacob0226 force-pushed the jacob/glm5-dsa-indexer-fusion-unified branch from 249b762 to 82bd89f Compare August 20, 2026 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.