Skip to content

[Perf] Narrow DeepSeek V4 eager CUDA graph region - #51430

Merged
WoosukKwon merged 5 commits into
mainfrom
agent/dsv4-narrow-cudagraph
Aug 10, 2026
Merged

WoosukKwon merged 5 commits into
mainfrom
agent/dsv4-narrow-cudagraph

Conversation

@WoosukKwon

@WoosukKwon WoosukKwon commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Narrow the DeepSeek V4 eager CUDA graph region so attention input preparation remains captured, and organize the flow so the execution stages are visible in one linear forward method.

The existing attention_impl eager break includes Q up-projection, fused Q normalization/RoPE/KV insertion, indexer input preparation, and MLA/indexer compression. This change moves those producer operations into forward and keeps only the sparse indexer operation plus forward_mqa in the eager region.

The final refactor removes the tuple-of-mostly-None plumbing, gives the input-projection helper a descriptive name and explicit return type, and reuses the indexer's existing forward method. It adds no net methods.

This branch is synced with main at fac808b36f.

Parallelism

This does not reduce stream parallelism relative to main:

  • Input projections still use the default stream for fused_wqa_wkv plus three auxiliary streams for compressor KV score, indexer weights, and indexer compressor KV score.
  • The next stage still overlaps Q projection/KV insertion on the default stream with the indexer on auxiliary stream 0 and the MLA compressor on auxiliary stream 1.
  • Auxiliary stream 2 is reused by the indexer's internal Q/K overlap.

ROCm retains its existing sequential fallback.

Why this approach

An earlier DeepSeek V4 region-narrowing change was reverted after real-model output corruption. This version deliberately keeps forward_mqa eager together with the sparse indexer instead of capturing the attention backend. Persistent eager scratch workspaces also keep the tensors consumed by the eager region address-stable.

This mirrors the region boundary used by the DeepSeek V3.2 optimization while preserving the DeepSeek V4 attention execution boundary.

Duplicate-work check

I searched open vLLM PRs for DeepSeek V4 CUDA graph, DeepSeek V4 eager attention, Narrow DeepSeek V4, and eager CUDA graph region DeepSeek. No other open PR implements this DeepSeek V4 eager-region narrowing. #51425 is the analogous DeepSeek V3.2 change and does not modify DeepSeek V4.

Performance

DeepSeek-V4-Flash on 4x GB200, Rust frontend, FP8 KV cache, FP4 indexer cache, PIECEWISE breakable CUDA graphs, DeepGEMM mega-MoE, and MTP2.

Short-prefill TTFT uses 1,000 requests with 128 input tokens, 1 output token, and concurrency 1. Saturated throughput uses 4,096 requests with the same token lengths and concurrency 64. The comparison was run against main at b706fd162 before the final sync.

Metric main This PR Change
Mean TTFT 41.45 ms 19.20 ms -53.7%
P50 TTFT 41.18 ms 19.09 ms -53.7%
Request throughput 430.05 req/s 433.29 req/s +0.75%

A same-session A/B of the readability-only refactor measured 19.889 ms before and 19.742 ms after for mean TTFT (-0.74%); P50 was 19.663 ms and 19.674 ms respectively. This indicates no regression from the structural cleanup.

Validation

  • pre-commit run --files vllm/models/deepseek_v4/attention.py vllm/models/deepseek_v4/nvidia/model.py vllm/models/deepseek_v4/amd/model.py
    • passed, including Ruff and Python 3.10 mypy
  • .venv/bin/python -m pytest tests/v1/cudagraph/test_breakable_cudagraph.py -q
    • 14 passed
  • Commit-time pre-commit and sign-off hooks
    • passed

Real-weight serving completed graph capture and all evaluation requests in both requested topologies. Both used MTP2 and otherwise identical serving/evaluator settings. The DP4/EP4 run used TP1, DP4, and expert parallel across all four GPUs.

Full GSM8K, 1,319 questions, 5-shot, seed 42, greedy decoding, 128 concurrent requests:

Configuration Strict exact match Flexible exact match
TP4/EP4 + MTP2 95.30% (1,257/1,319) 95.22% (1,256/1,319)
DP4/EP4 + MTP2 95.07% (1,254/1,319) 95.00% (1,253/1,319)

No evaluation requests failed. Raw samples and aggregate result JSON were retained for both runs.

AI assistance

This PR was developed with AI assistance. The human submitter reviewed the changed code and ran the validation and model evaluations listed above.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
@mergify mergify Bot added deepseek Related to DeepSeek models nvidia labels Aug 7, 2026
Assisted-by: OpenAI Codex
Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
Assisted-by: OpenAI Codex
Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
@WoosukKwon
WoosukKwon marked this pull request as ready for review August 10, 2026 16:05
@WoosukKwon WoosukKwon added the ready ONLY add when PR is ready to merge/full CI is needed label Aug 10, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@WoosukKwon

Copy link
Copy Markdown
Collaborator Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #83167 for commit 3efc01ccee42.

@WoosukKwon
WoosukKwon merged commit 79c865b into main Aug 10, 2026
68 checks passed
@WoosukKwon
WoosukKwon deleted the agent/dsv4-narrow-cudagraph branch August 10, 2026 17:52
@github-project-automation github-project-automation Bot moved this to Done in NVIDIA Aug 10, 2026
njhill added a commit to njhill/vllm that referenced this pull request Aug 14, 2026
vllm-project#51430 narrowed the DeepSeek V4 eager cudagraph region, which corrupts
MRV1 output, and vllm-project#51768 responded by defaulting the model to MRV2 and
rejecting MRV1 + PIECEWISE. That default costs ROCm, where MRV1 is still
the faster runner for this model.

Choose the region from the runner instead: MRV1 wraps the whole
attention body in `_prepare_and_attn_eager`, restoring the pre-vllm-project#51430
region it needs, while MRV2 keeps the narrow region and its shorter
TTFT. The nested `_sparse_indexer_and_attn` break runs inline, since
`add_eager` clears `_capturing` first.

MRV1 + PIECEWISE is then correct on every platform, so drop the
rejection. CUDA still defaults to MRV2; ROCm defaults to MRV1 until MRV2
is competitive there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Signed-off-by: Nick Hill <nickhill123@gmail.com>
Fangzhou-Ai added a commit to Fangzhou-Ai/vllm that referenced this pull request Aug 16, 2026
vllm-project#51430/vllm-project#51768 moved DSV4 to MRV2 and a narrow eager region. That is a
large decode TPOT regression on ROCm. Default ROCm back to MRV1, wrap
the full attention body in the eager break for MRV1 only, and drop the
MRV1+PIECEWISE rejection. CUDA keeps MRV2 and the narrow region.

Co-authored-by: Nick Hill <nickhill123@gmail.com>
Co-authored-by: Cursor Grok 4.6 <cursoragent@cursor.com>
Signed-off-by: fai <fangzhouai@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deepseek Related to DeepSeek models nvidia ready ONLY add when PR is ready to merge/full CI is needed

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant