fix: bound DSA prefill score memory - #4896
Merged
Merged
Conversation
CUHKSZzxy
force-pushed
the
fix/glm-dsa-logits-chunking
branch
from
August 24, 2026 04:43
5bb1923 to
69dd860
Compare
Skip DSA score selection when top-k covers the full prefill context and route the equivalent dense attention through FA3 when available. Preserve MTP index reuse, default sparse MLA caches to BF16 unless FP8 is requested, and cover dispatch and cache-policy behavior.
Document DeepGEMM's dense logits allocation and the TMA reason for query-only chunking. Remove the redundant builder-level BF16 cache test.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR separates dense and sparse FlashMLA paths while bounding DSA prefill score memory and adding short-prefill optimizations.
Changes:
- Adds chunked DSA scoring and reserved workspace.
- Adds dense routing for short prefills with MTP index safeguards.
- Supports BF16 and FP8 MLA cache policies.
Review findings:
- Critical (1 vote):
sparse_mla.py:230has an invalid BF16 dense fallback when FA3 is unavailable. - Moderate (3 votes):
nsa.py:391can exceed the memory budget throughbitonic_topktemporaries. - Moderate (2 votes):
nsa.py:417can allocate the full score tensor when DeepGEMM is unavailable.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Summary |
|---|---|
tests/pytorch/spec_decode/test_glm_moe_dsa_mtp.py |
Tests MTP index-buffer behavior. |
tests/pytorch/nn/test_nsa.py |
Tests score chunking and short-prefill behavior. |
tests/pytorch/kernel/test_mla_attention.py |
Tests MLA routing and mapping. |
tests/pytorch/engine/test_executor_base.py |
Tests workspace reservation. |
lmdeploy/pytorch/nn/nsa.py |
Exposes indexer and prefill configuration. |
lmdeploy/pytorch/models/glm_moe_dsa.py |
Handles dense prefills and MTP indices. |
lmdeploy/pytorch/models/deepseek_v32.py |
Integrates indexer and MLA configuration. |
lmdeploy/pytorch/envs.py |
Adds score-memory configuration. |
lmdeploy/pytorch/engine/executor/base.py |
Reserves DSA score workspace. |
lmdeploy/pytorch/configurations/glm_moe_dsa.py |
Updates inherited cache defaults. |
lmdeploy/pytorch/configurations/deepseek_v32.py |
Defines BF16/FP8 MLA cache policy. |
lmdeploy/pytorch/backends/nsa.py |
Updates NSA interfaces. |
lmdeploy/pytorch/backends/cuda/nsa.py |
Implements bounded scoring and skip logic. |
lmdeploy/pytorch/backends/cuda/attention/sparse_mla.py |
Implements sparse FlashMLA execution. |
lmdeploy/pytorch/backends/cuda/attention/mla.py |
Implements dense FlashMLA execution. |
lmdeploy/pytorch/backends/cuda/attention/__init__.py |
Selects dense or sparse implementations. |
Suppressed comments (2)
lmdeploy/pytorch/backends/cuda/nsa.py:48
- The
max(1, ...)clamp means the claimed budget is exceeded whenever one row of FP32 logits is larger thanmax_logits_bytes(for example, a 1 MiB budget with a context wider than 262,144 tokens still allocates at least 4 MiB). Since this is configurable, either reject such a configuration with a clear error or document/account for the minimum per-row allocation instead of claiming the tensor is bounded.
_fp32_bytes = 4
return max(1, max_logits_bytes // (max_kv_seqlen * _fp32_bytes))
lmdeploy/pytorch/models/deepseek_v32.py:198
- This call leaves
allow_short_prefill_scoring_skipat its defaultFalsefor the regular Deepseek-V3.2 DSA model. As a result, prefill contexts at or belowindex_topkstill run_score_and_selectand materialize the dense logits instead of taking the newly implemented dense route; only the GLM-MoE-DSA call site enables this optimization. Enable the flag here as well so short prefills preserve the K-cache write but skip scoring.
allow_short_prefill_scoring_skip=layer_idx < config.num_hidden_layers,
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Supersedes #4892 by carrying its sparse FlashMLA refactor together with the DSA memory and short-prefill optimizations.
Summary
[M, N]FP32 logits OOM as vLLM #36178.Validation
60 passed).80/80requests with FP8 KV cache, MTP5, prefix caching, and symmetric-memory all-reduce:914.67 tok/soverall output and1425.27 tok/ssteady completion throughput.Assistance
Assisted with Codex + GPT-5.6-Sol xHigh, reviewed manually