Repository navigation
Conversation
…uced DeepGEMM SM count Dual-batch overlap lowers DeepGEMM's SM count (deep_gemm.set_num_sms) while the microbatches run, but the DSA indexer metadata builder plans the paged-MQA-logits schedule for the whole GPU before that. The decode branch then trips DeepGEMM's "_schedule_meta_size == num_sms + 1" assertion as soon as a microbatched step contains a decode-classified request (e.g. a 1-token short extend of a prefix-cached prompt on a prefill instance). Record the SM count and block size the schedule was planned with on DeepSeekV32IndexerDecodeMetadata and re-plan it at the call site when DeepGEMM's current SM count differs, caching the result per SM count so only the first indexer layer of a forward pays. Unchanged SM counts take the existing path; XPU/ROCm are untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Anirudh Ravichandran <ani@primeintellect.ai>
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
|
why can not we build metadata based on |
@zyongye I considered that, so:
Re-planning at the call site uses the SM count DeepGEMM is actually running with (get_num_sms()), so it stays correct whichever code path changes it (The cost ofc is one small metadata kernel per microbatch, on the first indexer layer.) |
|
This pull request has merge conflicts that must be resolved before it can be |
|
Thanks for the reply. First of all, the metadata build is done at every engine step. The metadata don't reuse unless we explicitly cache them.
My sense is that for we can't get the exact SM count at metadata build time because the model runner is not exposed such value? If that's the case, I think this approach make sense to me. But I would double check if |
## Purpose Fix six pre-existing defects identified through source comparison during vLLM 0.32 validation: communication teardown, colocated service port conflicts, and DeepSeek V4 DBO execution edge cases. This PR builds on the version-upgrade PR. The alignment fix includes the reviewed input simplification: safely reuse native persistent storage for the first microbatch and omit the unused fresh slot-map reconstruction during FULL Graph replay. The second microbatch retains persistent, aligned storage. ## Issue - Related RFC: #495. - Depends on #501 (GPU vLLM 0.32 upgrade); base branch is `codex/gpu-032-upgrade-base-reviewfix`. - This PR does not close the RFC. ## Scope **In scope: one combined six-fix PR.** | Defect | Fix | | --- | --- | | Metadata receive thread blocks teardown | Cancel receives through the owned process group, join the receiver before releasing GPU resources, and destroy owned PyNccl communicators. | | Colocated Attention/FFN HTTP port conflict | Separate the service ports in six V2 recipes and the decode benchmark. | | Misaligned V4 DBO inputs | Keep positions and KV slots aligned and address-stable; include CUDA/NPU isolation and input-preparation simplification. | | Padding-only microbatch enters Attention | Skip Attention computation for zero-real-token stages while preserving mHC, FFN, EP, and handoff behavior. | | Inconsistent V4 indexer SM budget | Use the active DBO compute budget for the planner and restore the previous budget on scope exit. | | V4 workspace omitted from profiling | Reserve native FlashMLA workspace for each actual microbatch/lane before profiling. | Include the corresponding regression tests, shared fakes, design notes, recipe documentation, and upgrade lessons. **Out of scope:** - The existing V2 TP2+DBO shutdown forcekill issue remains separately tracked and is not claimed fixed here. - An NPU runtime upgrade, NPU hardware qualification, a 0.30 backport, or a new full accuracy/performance matrix. ## Implementation Notes DBO relationship: input alignment, padding-only stages, and indexer SM budgeting directly address DBO microbatch execution. Workspace reservation addresses V4 startup profiling and scratch ownership, as exposed by Graph+DBO. Metadata teardown and HTTP port separation apply independently of DBO. - Base: `aa8b687806d30f1f2b035215c3f8658df6863a69`. - Head: `82fcd01bfaffcaeae7837f0264a1625e00fccaa2`. - Target vLLM: `5df63a7203cdb9328d824a27b682e77c7b9928be` (0.32.0). - The first microbatch uses native positions storage. It reuses native slots only when the fixed row layout satisfies alignment; otherwise it retains separate staging. The second microbatch always retains persistent, aligned input storage. - FULL live replay skips only the fresh slot-map postprocessing that the model does not consume. Eager/capture preparation and input-content refresh remain intact. - Keep the required SM-budget and workspace correctness fixes. The input simplification adds no per-step device synchronization or new kernel. - CUDA V4 input handling is backend-gated. Shared NPU protocol behavior has CPU regression coverage; no NPU hardware pass is claimed. - No changes are made to the vLLM source checkout. ### Temporary V4 DBO patch integration The four V4 workarounds are grouped in `afd_plugin/compat/patches/gpu_deepseek_v4_dbo.py`. CUDA V4 preparation temporarily replaces methods on the active model-state/ubatch instances and restores them in `finally`; pre-profile reservation temporarily selects each workspace owner. The decoder explicitly calls the padding-aware attention adapter and retains mHC, Hash IDs and remote FFN ownership. These are scoped runtime adaptations, not global import-time replacements. The existing input-buffer, preparation and workspace definitions have identical ASTs after relocation. The padding-only decision and native attention call retain their existing conditions and arguments. No new class, allocation policy, synchronization, scheduler behavior or distributed protocol is introduced. | Workaround | Upstream tracking | Removal condition | | --- | --- | --- | | Input alignment | No published corresponding upstream PR | The pinned runtime satisfies the V4 metadata alignment contract and input/replay regressions pass. | | Padding-only attention | vllm-project/vllm#63823 is related FULL-graph work, not a complete eager consumer fix | Native attention supports empty padded stages in the supported execution modes and the A/F protocol regression passes. | | Indexer SM budget | vllm-project/vllm#60732 | The pinned runtime plans for the actual DBO compute budget and preparation/restoration regressions pass. | | FlashMLA workspace reservation | vllm-project/vllm#61584 supplies the all-slot reservation API | V4 also uses that API for its own FlashMLA scratch before profiling and per-owner capacity regressions pass. | An upstream merge alone does not retire a patch: the supported pinned runtime must contain the complete fix. ## Test Plan - [x] Verify source/import identity, `pip check`, and the CPU unit suite in the exact target runtime. - [x] Run the affected CPU regression selections; source-specific results and historical coverage are listed below. - [x] Run the existing H20 V4 eager+DBO and Graph+DBO E2E cases serially as short smoke tests. - [x] Check DBO/Graph evidence on every A/F rank in each window, plus paired Hash inputs and freshness across two different-input windows. - [x] Verify physical cleanup inside the allocation, host after-state, and scheduler release. - [x] Independently review the affected source and reapply the frozen runner's validation criteria to the raw GPU records. ## Test Result **Latest cleanup `82fcd01`: production code unchanged from `fe456cb`.** Remove redundant test combinations, decoder fakes and the synthetic profiling-budget simulation; consolidate teardown checks and shorten repeated design notes. The complete PR is now **28 files, +1,483 / -117**, down from 29 files, +2,176 / -125. | Cleanup snapshot / CPU job | Result | Affected checks | | --- | --- | --- | | First cleanup snapshot, job 3492 | 28 passed, 152 deselected, zero skipped | Aligned inputs and refresh, SM restoration, NPU isolation, padding guard, workspace ownership and shutdown | | Final cleanup snapshot, job 3493 | 11 passed, 200 deselected, zero skipped | Consolidated control-plane/connector tests, simplified timeout test and NPU isolation without CUDA-only state | The final selection revalidates the NPU and timeout cases changed after job 3492; the other retained tests from that run are unchanged. Both CPU-only jobs used vLLM 0.32.0 (`5df63a7`) and PyTorch 2.13.0+cu130, completed with exit 0, passed host/cleanup checks and released their allocations. Applicable pre-commit hooks, mypy and diff checks passed. No new GPU, accuracy or performance run was needed for this test/documentation-only cleanup. GPU evidence below remains tied to `93d5f89`; this is not a current-head full-matrix rerun. **Earlier patch relocation `fe456cb`: targeted CPU validation, job 3480.** - **52 passed, 124 deselected, zero skipped** in the existing target runtime: vLLM 0.32.0 (`5df63a7`), PyTorch 2.13.0+cu130, Python 3.12. - Covers input values/storage and replay freshness, odd-token and single-stage preparation, indexer budget/error restoration, NPU preparation/control isolation, padding-stage A/F behavior, workspace owner restoration and pre-profile accounting. - Applicable pre-commit hooks, mypy and diff checks passed. Host before/after checks passed; the CPU-only job completed with exit 0 and released its allocation. - This refactor has no new GPU, performance or task-accuracy run. The full-suite and GPU results below remain tied to their recorded source `93d5f89`. <details> <summary>Historical fe456cb targeted regression command</summary> ```bash python -m pytest \ tests/unit/compat/patches/test_gpu_deepseek_v4_dbo.py \ tests/unit/compat/patches/test_signatures.py \ tests/unit/model_executor/models/test_deepseek_v4_proxy.py \ tests/unit/v1/worker/test_model_runner_v2.py \ -k 'v4 or ubatch_failure_restores_native_input_binding_and_indexer_plan or profile_keeps_unaffected_workspace_owners_unreserved' ``` </details> **CPU: job 3347, exact head `93d5f89`.** - **1,358 passed, 114 skipped, 55 subtests passed.** All 27 affected checks executed and passed. - Dependency/platform skips are retained and are not counted as passes. - Source/import/runtime identity, dependency consistency, affected hooks/mypy, cleanup, and release passed. **GPU: job 3348, four H20-3e GPUs, 2A2F DP2/TP1, FP8 KV, L4096/T1024.** | Scenario | 24-question strict smoke | Execution and input checks | | --- | --- | --- | | eager + DBO | 23/24 | All A/F ranks executed two stages in all three windows; input pairing and freshness passed across the two concurrent-request windows. | | FULL_DECODE_ONLY Graph + DBO | 24/24 | All ranks met Graph/DBO criteria in all three windows; each concurrent-request window recorded 15–16 two-stage Graph replays per rank. Hash pairing and freshness passed. | - Both pytest cases passed, with no failures or skips. - GPU applications, owned PIDs, task ports, and IPC were clear. Host after-state passed; Slurm reported **COMPLETED, ExitCode 0:0**, and the allocation was released. - The allocation used four GPUs for 12 minutes 04 seconds: **48.267 GPU-minutes**. - Independent affected-source review and raw device-evidence verification passed with no new findings. **Validation boundaries:** `diagnostic_only=true` is retained. These are short correctness checks, not full-dataset accuracy or performance measurements. Earlier first300 results remain tied to their recorded source/configurations and are not a full-matrix rerun of this head. Non-eight-aligned capacity, multiple KV groups, and threshold fallback branches have CPU contract coverage; exhaustive device coverage is not claimed. Raw teardown logs retain native SIGTERM-after-grace, step cancellation, and TCPStore shutdown warnings. Final resource cleanup passed; this is not a zero-warning shutdown claim. The existing V2 forcekill issue remains unresolved separately. ### Affected-path validation matrix All validated-runtime runtime checks below used AFD `93d5f89` with native vLLM `5df63a7`. CPU contract checks and actual CUDA execution are reported separately. #### Targeted CPU checks (job 3347) | Affected behavior | Executed cases | Result | | --- | --- | --- | | Stage-view values and stable storage | 4 | PASS | | FULL-replay input refresh contract | 6 | PASS | | Odd-token input preparation | 2 | PASS | | Single-stage fallback | 6 | PASS | | Preparation/model failure restoration | 6 | PASS | | NPU native-context/control protocol isolation | 2 | PASS | | NPU error restoration | 1 | PASS | Total: **27 executed, 27 passed, zero skipped within this targeted selection**. The complete suite result remains 1,358 passed, 114 skipped and 55 subtests passed. CPU tensor/view tests establish preparation contracts; they are not CUDA Graph execution evidence. #### Six-fix coverage | Fix | CPU / static coverage | Device scope / limitation | | --- | --- | --- | | Metadata receiver / communicator lifetime | Receiver cancellation, joining before GPU release, and communicator teardown regression tests passed in job 3347 | Combined V4 cleanup passed; the separate V2 forcekill failures remain unresolved | | Colocated HTTP ports | Six recipes and one benchmark script passed `bash -n` | Full checked-in recipe deployment was not run | | V4 aligned and persistent inputs | Affected preparation, stable-view, odd-token, single-stage, freshness and restoration contracts passed | Validated-runtime eager/Graph DBO and two distinct-input windows passed | | V4 padding-only Attention stage | Zero-real-token boundary contract regression tests passed | Combined V4 DBO smoke passed; no claim of exhaustive zero-token geometry coverage | | V4 indexer SM budget | Planner/compute budget alignment and scope restoration regression tests passed | Combined V4 DBO smoke at the recorded default SM settings passed | | V4 workspace accounting | Per-microbatch/lane reservation and pre-profile accounting contracts passed; earlier focused job 3287 executed all nine workspace cases | Validated-runtime capture/DBO smoke passed; earlier first300 at `972d884` passed, not a new-head full accuracy run | #### Actual CUDA execution windows (job 3348) | Scenario | Window | All four A/F ranks | Input evidence / result | | --- | --- | --- | --- | | Eager + DBO | Concurrent round 1 | 18 live two-stage steps per rank | A/F Hash pairing PASS | | Eager + DBO | Concurrent round 2, changed input IDs | 18 live two-stage steps per rank | Pairing PASS; all four peer/stage combinations changed at the same bucket and real size | | Eager + DBO | GSM8K | 193–194 live two-stage steps per rank | 23/24 strict; no separate bounded Hash-coverage requirement for this window | | Graph + DBO | Concurrent round 1 | 15–16 completed two-stage Graph replays per rank | Live-replay A/F Hash pairing PASS | | Graph + DBO | Concurrent round 2, changed input IDs | 15–16 completed two-stage Graph replays per rank | Live-replay pairing and all four peer/stage freshness checks PASS | | Graph + DBO | GSM8K | 147–168 completed two-stage Graph replays per rank | 24/24 strict; no separate bounded Hash-coverage requirement for this window | | Both scenarios | Final cleanup and release | GPU apps, tracked PIDs, task ports and IPC clear | Host after-state PASS; Slurm COMPLETED 0:0; allocation released | Warmup, dummy and capture work do not count toward these live execution results. The two concurrency windows and GSM8K each have independent reset/report windows. The Hash freshness proof comes from the two concurrency windows, not from an unobserved third Hash window. For the broader 26-cell executed upgrade campaign, native controls/profiling, all nine representative first300 results, and known shutdown failures, see the **Validation matrix and source provenance** section in #501. Those historical rows retain their own source revisions and do not represent a full matrix rerun of this head. ## Docs Impact Document CUDA V4 patch ownership/removal conditions and FFN shutdown order. Correct the six colocated V2 recipes and benchmark ports, retain upgrade lessons, and include the affected regression tests. --- <details> <summary>Essential PR Checklist</summary> - [x] Purpose is clear and linked to public context. - [x] The six-fix scope and upgrade dependency are bounded. - [x] GPU vLLM 0.32.0 and shared NPU vLLM 0.30.0 boundaries are considered. - [x] No changes are made to the vLLM source checkout. - [x] Native storage, workspace, and execution contracts are reused where appropriate. - [x] Adaptations are scoped, documented, and covered by affected regression checks. - [x] Imports remain CPU-safe; CUDA-specific work is backend-gated. - [x] CPU/GPU evidence, skips, and qualification limits are stated. - [x] Documentation impact is stated. </details> --------- Signed-off-by: Zhou ziheng <jiaranran2@gmail.com>
Overview
With
--enable-dboand an all2all backend that reserves communication SMs (e.g. DeepEP high-throughput), DSA models (DeepSeek-V3.2, GLM-5.x) crash in the sparse-attention indexer as soon as a microbatched step contains a decode-branch request:The indexer builder plans DeepGEMM's paged-MQA-logits schedule for the whole GPU, but DBO lowers DeepGEMM's SM count (
set_num_sms(total - VLLM_DBO_COMM_SMS)) while the microbatches run. This PR re-plans the schedule at the call site when the two counts differ. No existing issue or PR covers this (searchedschedule_meta_size,dbo indexer num_sms,paged_mqa_logits set_num_sms: 0 results). Rechecked 2026-10-08 against open PRs: #56476 (DeepSeek-V4.1 per-microbatch index state) also editssparse_attn_indexer.py, in different lines, and does not touch the schedule metadata.Claims
VLLM_DBO_COMM_SMS=0), where this code path never runs.get_num_sms()per indexer layer). Under DBO, one ~9 µs metadata kernel per microbatch per forward, reused by all indexer layers. No host syncs; CUDA-graph safe.Validation
This branch is rebased onto main @ 240785b; the rebase did not change the patch (same
git patch-id). The unit and related tests below were re-run on the rebased commit (H200) with the same results. The GSM8K runs predate the rebase and used main @ 4a705c7 with and without this patch.Unit test (new),
tests/v1/attention/test_indexer_schedule_metadata.py: plans a schedule for the full GPU, lowers DeepGEMM's SM count by 20 (whatcreate_sm_control_contextdoes), and checks thatget_schedule_metadata()re-plans once, the kernel runs, and logits match the full-SM result on all valid columns; the original schedule comes back after the SM count is restored. Runs in the existing H100/B200 "V1 Attention" CI shards; skipped without DeepGEMM or below SM90.next_n1, 2, 4: 3 passednext_n1, 2: passed (next_n=4needs a newer DeepGEMM than 0.29 ships)Related existing tests on this branch (H200):
tests/kernels/attention/test_deepgemm_attention.py5 passed,test_indexer_native_next_n.py9 passed,test_sparse_indexer_decode_seq_lens.py7 passed,test_indexer_dcp_localize.py114 passed,test_sparse_mla_backends.py292 passed (1,188 skipped by hardware).test_indexer_deepseek_v4_slot_mapping.py: 30 passed, 3 could not run locally (they load the gatedmeta-llama/Meta-Llama-3-8Bconfig); they fail identically on main and do not touch the changed code.Kernel-level check (H200, DeepGEMM
fp8_fp4_paged_mqa_logits, GLM-5.3 indexer shapes: 32 heads x 128, block 64, 13 requests with contexts 1 to 32k):SMControlContextManager)End-to-end reproducer, before/after. A 4-layer GLM-5.3 (
GlmMoeDsaForCausalLM, production attention/indexer geometry, dummy weights) on 2 x H200, DP2/EP2,--all2all-backend deepep_high_throughput --enable-dbo --dbo-prefill-token-threshold 32 --dbo-decode-token-threshold 32,cudagraph_mode NONE, fp8_per_block + fp8 KV, prefix caching. Workload: random-token prompts of64*k+1tokens, then exact repeats (a full prefix-cache hit leaves a 1-token short extend at the head of the batch) mixed with fresh long prompts, pinned per DP rank. vLLM 0.29.0 with and without the backport of this patch (same two files):With the fix, DBO-on generations equal DBO-off: 944/944 identical sequences (7,440/7,440 tokens), first-token logprob difference at most 1.9e-6.
Model evaluation, GLM-5.3 FP8 (1 x 8 H200, DP4 x TP2, EP8, DeepEP high-throughput,
cudagraph_mode NONE, fp8 KV, prefix caching,VLLM_USE_DEEP_GEMM=0 VLLM_MOE_USE_DEEP_GEMM=0as on our production prefill, FlashInfer prebuilt kernels;lm_evalGSM8K 5-shot, 1,319 questions,num_concurrent=256):VLLM_DBO_COMM_SMS=0(fix path never runs)VLLM_DBO_COMM_SMS=0The fix turns the crash into a completed eval. The drop from 0.93 to ~0.6 with DBO on is not caused by it: the
VLLM_DBO_COMM_SMS=0rows never re-plan (and never crash) and land in the same range. DBO with GLM-5.x has an accuracy bug of its own that this crash has been hiding: layers that reuse another layer's top-k read it from state shared across microbatches. #60734 fixes it; with both PRs, GLM-5.3 with DBO on scores 0.922 / 0.923 (DBO off: 0.927 / 0.928).Reproduction commands
Details
Root cause (main @ 240785b):
create_sm_control_context(vllm/v1/worker/ubatch_utils.py:83-126) usesdeep_gemm.set_num_smsas the compute-SM setter wheneverhas_deep_gemm() and comm_sms > 0, so inside the microbatches DeepGEMM seestotal - VLLM_DBO_COMM_SMSSMs (132 - 20 = 112 on H100/H200). It keys on DeepGEMM being importable, not onVLLM_USE_DEEP_GEMM.comm_smsis 0 only for DeepEP low-latency and NIXL-EP.gpu_ubatch_wrapper.py:426,453; MRV2gpu/ubatch_utils.py:496), after attention metadata has been built.num_compute_unitsSMs (v1/attention/backends/mla/indexer.py:967-968,:1688-1697, MTP drafts:1782-1789), andsparse_attn_indexer.py:729/glm5next/nvidia/sparse_indexer.py:582pass it tofp8_fp4_paged_mqa_logits, which asserts it against the current SM count.query_len <= 1 + num_speculative_tokens, including 1-token short extends of prefix-cached prompts, which the reorder puts first. A step is microbatched only when every DP rank votes for it.How it was found: GLM-5.3 RL with P/D disaggregation; prefill DP32/EP32 with DeepEP high-throughput, DBO,
cudagraph_mode NONE, prefix caching, vLLM 0.29.0 on H200. One prefill rank hit the assertion after ~28 h; the other 31 then timed out in DeepEP dispatch and failed withtorch.cat(): expected a non-empty list of Tensors.Fix:
DeepSeekV32IndexerDecodeMetadatarecords the SM count and block size the schedule was planned with.get_schedule_metadata()returns the planned schedule when DeepGEMM's current SM count matches; otherwise it re-plans with the same inputs and caches the result per SM count. The planned count is stored rather than derived from the tensor shape because SM90next_n=4plansnum_sms // 2 + 1schedule rows.update_draft_decode_metadatarewritesseq_lensin place, so it clears the cache. In FULL-graph DBO capture the re-plan kernel is captured and reads the persistentseq_lens/indicesbuffers; eager warmups under the same context JIT-compile it before capture.Alternatives considered
create_sm_control_context(all2allmax_sms_used(),VLLM_DBO_COMM_SMS, the ROCm override) for both runners, and anything else that changes DeepGEMM's SM count would break it again.set_num_smsin SM control: removes DBO's compute/communication SM partitioning for every DeepGEMM GEMM.fp8_fp4_paged_mqa_logitswrapper: no per-forward object to cache on, so every indexer layer would re-plan.Not affected: the sparse-MQA schedule of DeepSeek-V4.1 (planned inside the forward), FlashMLA scheduler metadata, and prefill
fp8_fp4_mqa_logits.AI assistance: Claude Code was used to trace the root cause, write the patch and test, run the validations above, and draft this description. I reviewed every changed line, can explain and defend the change, and checked the test results above.
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.
🤖 Generated with Claude Code