[Perf][DSA] Token-blocked fused_q kernel and packed bf16 MQA query - #5
Open
JaredforReal wants to merge 1 commit into
Open
JaredforReal wants to merge 1 commit into
JaredforReal wants to merge 1 commit into
Conversation
`_fused_q_kernel` used one single-warp program per (token, task, head) with a grid of (tokens, 3, 32); on the bf16-query path two thirds of the programs returned immediately and each live program touched 64 or 128 elements. Make one program handle 16 tokens x one head of one task (MQA q_pe RoPE, indexer RoPE+quant, or the ql_nope pack), with per-token UE8M0 scales computed row-wise. 16k tokens on GB300: 1582 us -> 152 us. On the bf16-query path the sparse backends then concatenated (ql_nope, q_pe) per layer (`torch.cat`, 518-645 us at 16k tokens, 5 us per decode layer). Let the absorbed `q_nope @ W_UK_T` bmm write straight into a [tokens, heads, kv_lora_rank + rope] buffer and have fused_q RoPE q_pe into its tail (new `q_out` argument), so `forward_mqa` receives one packed tensor. GLM-5.3-NVFP4, TP4 on 4x GB300, FLASHINFER_MLA_SPARSE, prefix caching off, same-window A/B against main: prefill TTFT -10% (32k) / -12% (64k), decode TPOT -2% (c=1) .. -7% (c=256), 32k-context c=16 throughput +12%. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Jared Wen <jaredwen@inferact.ai>
There was a problem hiding this comment.
🟡 Changes recommended
The new packed-tensor mqa_q path is incompatible with sparse MLA backends that require a split (q_nope, q_rope) tuple (e.g. FLASH_ATTN_MLA_SPARSE, FLASHINFER_MLA_SPARSE_SM90), causing runtime NotImplementedError.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR optimizes the DeepSeek V3.2 / GLM-5.x sparse-MLA prefix path by (1) restructuring the Triton fused_q kernel launch into token-blocked, per-head “task” programs, and (2) enabling a packed bf16 MQA query buffer to eliminate per-layer concatenations on the bf16-query path.
Changes:
- Rewrite
_fused_q_kernelto processBLOCK_Ttokens per program and unify MQA RoPE, indexer RoPE+quant, and optional NoPE packing under a single(token_block, task)grid. - Extend
fused_q(..., q_out=...)to write RoPE’dq_peinto the tail of a provided bf16 packed query buffer and optionally copy/packql_nopeinto the front. - Update DeepSeek v3.2 attention to use the packed bf16 query path, and add tests covering
q_outpacking (including front-aliasing).
File summaries
| File | Description |
|---|---|
vllm/models/deepseek_v32/common/kernels.py |
Reworks Triton fused-q kernel scheduling and adds optional packed bf16 query output via q_out. |
vllm/models/deepseek_v32/attention.py |
Uses a single packed bf16 query buffer to avoid torch.cat on bf16-query sparse decode. |
tests/kernels/test_fused_deepseek_v32_norm_rope.py |
Adds coverage for packed bf16 q_out behavior, including aliasing of the front slice. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+533
to
536
| # Packed query: fp8 [ql_nope; q_pe] (FlashInfer fp8 query) or bf16 | ||
| # [ql_nope; q_pe] written by fused_q into one buffer. | ||
| mqa_q_arg = mqa_q[:num_actual] | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related changes on the DSA (DeepSeek V3.2 / GLM-5.x) attention prefix path in
vllm/models/deepseek_v32/:_fused_q_kernelrewrite (common/kernels.py): grid(cdiv(tokens, 16), tasks)— one program handles 16 tokens × one head of one task (MQAq_peRoPE, indexer RoPE+UE8M0 quant, or theql_nopepack). The old grid(tokens, 3, 32)launched one single-warp program per element group and, on the bf16-query path, two thirds of the programs returned immediately. 16k tokens on GB300: 1582 µs → 152 µs.attention.py,fused_q(..., q_out=)): the absorbedq_nope @ W_UK_Tbmm writes directly into a[tokens, heads, kv_lora_rank + rope]buffer (torch.bmm(out=strided view), verified bit-equal and not slower) andfused_qRoPEsq_peinto the tail, soforward_mqagets one contiguous tensor and the per-layertorch.catin the sparse backends (518–645 µs per layer at 16k tokens, ~5 µs per decode layer) disappears. The(ql_nope, q_pe)tuple path is no longer used by this model; backends still accept it.Results (GLM-5.3-NVFP4, TP4, 4× GB300,
FLASHINFER_MLA_SPARSE, bf16 KV, prefix caching off, same script / same window vsmain)Tests
pytest tests/kernels/test_fused_deepseek_v32_norm_rope.py -k fused_q: 30 passed (addstest_fused_q_bf16_query_packed, incl. the aliasing case whereql_nopealready lives in the buffer).notes/glm53-nvfp4-perf/bench/fused_q_bench.py.Notes
Not a duplicate of any open upstream PR (
gh pr list --search "fused_q","concat_mla_q"— none touch this). AI assistance (Claude Code) was used; the submitter reviewed every line. Model quality eval on gsm8k/aime is still to be run before an upstream submission.