[Bugfix][PD] Pad resumed speculative decode requests - #55126
Merged
jeejeelee merged 1 commit intoSep 4, 2026
Merged
Conversation
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Ziming Huang <48115868+ZeldaHuang@users.noreply.github.com>
ZeldaHuang
requested review from
ApostaC,
WoosukKwon,
alexm-redhat,
heheda12345,
ivanium,
njhill,
orozery,
robertgshaw2-redhat and
ywang96
as code owners
September 3, 2026 10:47
This was referenced Sep 3, 2026
Member
|
/ci run |
|
✅ Triggered Buildkite CI #87121 for commit |
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.
Purpose
Keep resumed speculative-decode requests on the uniform verifier shape when a data-parallel rank has no already-running requests.
In P/D serving, a synchronous KV connector can resolve a waiting consumer to all but the final prompt token. During that scheduling pass, the matched prefix exists in the local
num_computed_tokensvariable, whilerequest.num_computed_tokensis updated only after admission. The current padding condition also requires localscheduled_running_reqs, so this rank schedules one token even when peer ranks run the1 + num_spec_tokensverifier shape. A singleqlen=1rank then prevents the DP group from using the full decode CUDA graph.This change treats a request with resolved computed tokens as resumed and applies the existing reject-only
-1padding, provided no prefill was scheduled. Ordinary prefills and diffusion speculative decoding retain their current behavior.The regression test uses a synchronous mock KV connector with 32 matched tokens and does not manually mutate request state.
Why this is not duplicate work
I searched open PRs for speculative-decode padding, resumed KV-connector requests, P/D CUDA graphs, and the relevant scheduler condition. No open PR changes admission for a synchronously resumed request on a rank without running work.
scheduled_running_reqsrequirement.max_model_len.Tests
Full scheduler test file, using an offline model redirect and a local pytest shim selecting
CpuPlatformon the CPU-only test host:Changed-file repository hooks:
All applicable hooks passed, including Ruff check/format, mypy, SPDX, forbidden imports, and configuration validation.
git diff --check origin/main...HEADalso passed.Serving validation
The equivalent scheduler-only change was validated on four 4xGB300 nodes (DEP16/EP16). Set the model paths and host names for the target cluster before running the commands below.
Run the same server command on all four nodes, with a shared
MASTER_ADDR. Each process owns four local DP ranks:Route traffic across the four node-local API servers:
vllm-router \ --policy round_robin \ --host 0.0.0.0 \ --port 18080 \ --prometheus-port 18081 \ --intra-node-data-parallel-size 4 \ --request-timeout-secs 900 \ --worker-urls \ http://<node-0>:8000 \ http://<node-1>:8000 \ http://<node-2>:8000 \ http://<node-3>:8000The unconditional per-position acceptance rates sum to
1.5282, giving a target mean acceptance rate of50.94%and acceptance length of2.5282forK=3. Run the QPS sweep once on each revision:Apply the base scheduler for the before sweep and this PR's scheduler for the after sweep. Every point completed 480 / 480 requests with zero failures. Observed acceptance rates were
49.74%–52.80%, with acceptance lengths of2.483–2.574.The P99 benefit is large through QPS 4, narrows at QPS 5, and is no longer visible at QPS 6. This matches the scheduler mechanism: once each rank stays busy, the original
scheduled_running_reqsbranch already applies the padding. P50 remains nearly unchanged throughout the sweep.No accuracy evaluation was needed because this reuses existing reject-only placeholder semantics and does not change model outputs, draft acceptance, kernels, or graph dispatch.
AI assistance
OpenAI Codex assisted with root-cause analysis, implementation, tests, runtime experiment analysis, and PR preparation. I reviewed and understand every changed line and am responsible for the contribution.