Repository navigation
[Bugfix][ROCm] Bound sparse indexer decode workspace at layer build time - #59969
Closed
Fangzhou-Ai wants to merge 1 commit into
Closed
Fangzhou-Ai wants to merge 1 commit into
Fangzhou-Ai wants to merge 1 commit into
Conversation
The ROCm sparse-MLA indexer sized its decode-logits workspace from get_current_vllm_config() inside the profiling run, where no config is set, so it fell back to max_num_batched_tokens rows. Resolve the max_num_seqs * (1 + num_speculative_tokens) bound when the indexer layer is built and pass it to the ROCm ops. Co-authored-by: Claude Signed-off-by: Fangzhou Ai <fangzhou.ai@amd.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
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.
Overview
ROCm-only alternative to #58014 for #55132. The ROCm sparse-MLA indexer works out its decode-row bound when the layer is built and passes it to the ROCm ops, instead of reading the vLLM config during the profiling run.
gpu_worker.pyis not changed.Claims
max_num_seqs * (1 + num_speculative_tokens)rows again, notmax_num_batched_tokensrows. This covers the AITER FP8 indexer (rocm_aiter_sparse_attn_indexer) and the MXFP4 indexer (rocm_mxfp4_sparse_attn_indexer/rocm_mxfp4_sparse_mqa_indexer).Validation
End-to-end on 8x MI355X (gfx950) with dummy weights:
VLLM_ROCM_USE_AITER=1 vllm serve deepseek-ai/DeepSeek-V4.1-Flash --load-format dummy -tp 8 \ --max-model-len 1048576 --max-num-seqs 16 --max-num-batched-tokens 8192 \ --attention-config '{"indexer_kv_dtype":"mxfp4"}'89439db727)The 31.97 GiB difference matches the expected saving: (8192 − 96) rows × 1M columns × 4 B ≈ 31.6 GiB. With the fix, 16 concurrent completions (prompts of 301–4801 tokens, 32 output tokens each) all finished with no workspace errors. That confirms the smaller locked workspace still covers real decode steps.
Tests:
pytest tests/kernels/attention/test_rocm_paged_mxfp4_indexer.py -k profiling_boundspasses (new test). It buildsRocmSparseAttnIndexerwhile the config is set, then runs the profiling branch with no current config and checks that the reserved rows are16 * (1 + 5).pytest tests/kernels/attention/test_rocm_paged_mxfp4_indexer.py tests/models/glm5next/test_sparse_indexer_topk_dispatch.py tests/v1/attention/test_rocm_glm5next_sparse.py tests/kernels/attention/test_rocm_aiter_mla_sparse_metadata_sync.py: 49 passed, 4 skipped, and 18 failed. The same 18 tests fail on main on this machine. The cause is the environment: AITER/FlyDSL can't write its JIT cache under a read-onlysite-packages. This PR changes nothing in those tests.pre-commit runpasses.This change only affects how much memory is reserved, not model outputs, so no accuracy eval was run.
Details
Root cause:
Worker.determine_available_memorycallsprofile_run()withoutset_current_vllm_config._max_decode_logits_rows()calledget_current_vllm_config(), which raised. Theexceptbranch then quietly returnedmax_num_batched_tokens. The workspace is locked after profiling, so the oversized reservation stayed for the life of the engine and counted as non-KV memory.#58014 fixes this by setting the config context around
profile_run()ingpu_worker.py. That is a change to the core worker for a problem that only shows up in ROCm code. This PR keeps the fix on the ROCm side instead:max_decode_logits_rows()(inrocm_aiter_mla_sparse.py) reads the bound once, when the layer is constructed. The model is built insideset_current_vllm_config, so the config is available then. This follows howSparseAttnIndexeralready handles its DCP scalars.max_decode_rows: int = 0argument, and the profiling branch reservesmin(num_tokens, max_decode_rows)rows. A value of 0 (bound unknown) keeps the old conservative behavior.SparseAttnIndexer(the shared layer) gets one new attribute, and only itsforward_hipreads it.Not in this PR: the GLM5-Next kpool profiling path (
sparse_attn_indexer_kpoolinmodels/glm5next/amd/sparse_indexer.py) has the same root cause with the opposite effect. With no config it reserves 0 decode-logits rows, so it under-reserves. That can be fixed the same way in a follow-up.Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.