Repository navigation
[Bugfix][Attention] Skip the FlashMLA sparse bf16 prefill workspace on the fp8 mixed-batch path - #59319
[Bugfix][Attention] Skip the FlashMLA sparse bf16 prefill workspace on the fp8 mixed-batch path#59319drakosha wants to merge 2 commits into
Conversation
|
This pull request has merge conflicts that must be resolved before it can be |
|
This pull request has merge conflicts that must be resolved before it can be |
01a4dfe to
4fe9b70
Compare
4fe9b70 to
c1e4af4
Compare
lucamotz
left a comment
There was a problem hiding this comment.
The gating looks right to me on main (2011b8f). Your serving numbers predate #61023, which sets the factor to 2 above 256K, so at 786K the buffer is 1.69 GiB on main, and the indexer's profile-run K-gather reservation in the same workspace keeps about 0.2 GiB of that (computed from the sizing code, not measured); could you re-measure on main?
| @pytest.mark.parametrize( | ||
| ("num_heads", "use_hisparse", "pcp_dcp_kv_gather", "expected"), | ||
| [ | ||
| (MIN_HEADS_FOR_BF16_PREFILL - 1, False, False, True), | ||
| (MIN_HEADS_FOR_BF16_PREFILL, False, False, False), | ||
| (MIN_HEADS_FOR_BF16_PREFILL - 1, True, False, False), | ||
| (MIN_HEADS_FOR_BF16_PREFILL - 1, False, True, False), | ||
| ], | ||
| ) | ||
| def test_fp8_mixed_batch_requires_few_heads_without_hisparse_or_kv_gather( | ||
| num_heads, use_hisparse, pcp_dcp_kv_gather, expected | ||
| ): | ||
| assert ( | ||
| FlashMLASparseImpl._use_fp8_mixed_batch( | ||
| num_heads, use_hisparse, pcp_dcp_kv_gather | ||
| ) | ||
| is expected | ||
| ) | ||
|
|
||
|
|
There was a problem hiding this comment.
test_fp8_mixed_batch_path_reserves_no_prefill_workspace covers the same cases and checks impl.fp8_use_mixed_batch, so I think this one can go.
| @pytest.mark.parametrize( | |
| ("num_heads", "use_hisparse", "pcp_dcp_kv_gather", "expected"), | |
| [ | |
| (MIN_HEADS_FOR_BF16_PREFILL - 1, False, False, True), | |
| (MIN_HEADS_FOR_BF16_PREFILL, False, False, False), | |
| (MIN_HEADS_FOR_BF16_PREFILL - 1, True, False, False), | |
| (MIN_HEADS_FOR_BF16_PREFILL - 1, False, True, False), | |
| ], | |
| ) | |
| def test_fp8_mixed_batch_requires_few_heads_without_hisparse_or_kv_gather( | |
| num_heads, use_hisparse, pcp_dcp_kv_gather, expected | |
| ): | |
| assert ( | |
| FlashMLASparseImpl._use_fp8_mixed_batch( | |
| num_heads, use_hisparse, pcp_dcp_kv_gather | |
| ) | |
| is expected | |
| ) |
…n the fp8 mixed-batch path FlashMLASparseImpl reserved the bf16 prefill KV workspace (factor * max_model_len * head_size * 2 bytes) for every quantized DS-MLA cache, but only the separate prefill/decode path reads it. The mixed-batch path taken below MIN_HEADS_FOR_BF16_PREFILL heads per rank paid for it out of the KV cache budget: 4.22 GiB per rank for GLM-5.3 at max_model_len 786432 with 16 heads per rank. Move the mixed-batch condition into a FlashMLASparseImpl static helper shared with the metadata builder, reserve the prefill KV buffers only when the separate path is selected, and assert in forward_mqa that the metadata and the impl agree on the path. The padded query and output buffers sized by max_num_batched_tokens stay on both paths: vllm-project#60220 stages the mixed-batch decode kernel's q and out in them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Mikhail Kostryukov <mike@triptrack.net>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Mikhail Kostryukov <mike@triptrack.net>
c1e4af4 to
beea735
Compare
|
@lucamotz Remeasured on nightly |
Purpose
FlashMLASparseImplreserves the bf16 prefill KV workspace even when the fp8 mixed-batch path is selected and never reads it. Gate themax_model_len-sized reservation with the same path condition used by the metadata builder. Keep the threemax_num_batched_tokensq/out buffers: the staging implementation in #60220 uses them.After #61023 the prefill factor is 2 above 256K context. At
max_model_len=786432, the unused bf16 buffer is 1.6875 GiB per rank. The net saving depends on the other users of the shared workspace; the earlier 4.22 GiB figure no longer describes main.The constructor and builder share
_use_fp8_mixed_batch;forward_mqachecks their decisions agree. The separate prefill/decode, HiSparse and PCP+DCP gather reservations remain covered by the constructor test. The redundant truth-table test was removed following review.Related work: #57575 reserved these buffers before KV sizing; #60220 stages q/out in the retained batch-sized buffers; #67510 adds HiSparse token-sharded prefill. This PR gates the unused bf16 reservation on the non-HiSparse mixed-batch path. The open-PR searches for
mixed batch prefill workspacefound no other PR implementing that gate.Test Plan
The existing
test_fp8_mixed_batch_path_reserves_no_prefill_workspacematrix covers head counts 16/32, HiSparse on/off and PCP/DCP combinations. The existing fp8 decode-correctness parametrization includes TP8.Full applicable pre-commit suite on the current rebase, including Ruff 0.17.2, mypy and test tethering: passed.
Test Result
Rebased onto main
5039f736e6. The two changed files are byte-identical to the tested pre-publication revision.Fresh A/B on nightly
615c9d6474, 4x H200 NVL,nvidia/GLM-5.3-NVFP4, TP4/DCP4/EP, MTP3,fp8_ds_mla, context 786432, batch 8192, 32 sequences, utilization 0.945; extensible KV, explicit KV memory and CPU offload disabled.Both sides carry the same serving patches (#59367, #49249, #58209, #58985 and the narrow FULL-sampling fix from #59368), plus FlashMLA
b18ed74with #27/#28/#29. This PR is the only difference between the two rows.Net saving: 1,492,123,648 bytes (1.3896484375 GiB) per rank, with 109,056 additional KV tokens on this stack.
The combined build also passed tool calls (streaming and non-streaming), reasoning, 230,456-token needle retrieval at depths 0.1/0.5/0.9, and three 544,235-token prompts cold and replayed with CPU offload (3/3 each). Fresh prefill was about 6.4k tok/s. These are serving smoke/load checks; no full GSM8K run or statistical throughput gain is claimed.
Earlier isolated CUDA coverage on
af7f9488c: 14 unit cases passed and 56 fp8 FlashMLA decode cases passed (56 unsupported-block-size skips); with #60220 applied, 72 passed/56 skipped. That GPU unit matrix was not rerun for this publication; the current evidence is the serving run and pre-commit checks.AI assistance (Claude Code and Codex) was used for the analysis, implementation, tests, measurements and description.