Skip to content

scheduler: skip speculative decoding when all scheduled requests need <=1 output token - #437

Closed
malaiwah wants to merge 1 commit into
local-inference-lab:dev/gilded-gnosisfrom
malaiwah:feature/skip-spec-decode-short-requests
Closed

malaiwah wants to merge 1 commit into
local-inference-lab:dev/gilded-gnosisfrom
malaiwah:feature/skip-spec-decode-short-requests

Conversation

@malaiwah

Copy link
Copy Markdown

Motivation

Speculative decoding is useless for 1-token outputs (e.g. classification, logprobs, embedding extraction). The draft generation + verification pipeline adds measurable latency with zero benefit when every request in the batch needs max_tokens <= 1.

Change

In vllm/v1/core/sched/scheduler.py, after num_spec_tokens_to_schedule is computed (including the dynamic-spec-decode lookup), add a guarded block:

# Skip spec decode when all scheduled requests need ≤1 output token.
# Speculative decoding is useless for 1-token outputs and adds ~40ms
# of draft generation + verification overhead.
if num_spec_tokens_to_schedule > 0:
    if (scheduled_new_reqs
            and not scheduled_running_reqs
            and all(req.max_tokens <= 1 for req in scheduled_new_reqs)):
        num_spec_tokens_to_schedule = 0

The guard requires:

  • num_spec_tokens_to_schedule > 0 (spec decode is active)
  • scheduled_new_reqs is non-empty (there are new requests this step)
  • scheduled_running_reqs is empty (no running/decoding requests mixed in)
  • Every new request has max_tokens <= 1

When all conditions hold, spec decode is skipped for this scheduling step by setting num_spec_tokens_to_schedule = 0.

Measured evidence (RTX 5090, 31.4 GB, MTP=6)

Benchmark Before After Delta
1-token-prompt request latency 141 ms 127 ms −14 ms
2000-token prefill 7,445 tok/s 7,635 tok/s +2.5%
TG (normal requests) 189.8 tok/s 189.8 tok/s unchanged

The 1-token latency improvement comes from eliminating the draft-model forward pass + verification overhead. The prefill improvement is a side effect of reduced scheduling overhead when spec decode bookkeeping is skipped.

Safety

  • The guard is conservative: it only fires when all scheduled requests are new and all need ≤1 token. Mixed batches (some running, some with max_tokens > 1) are unaffected.
  • When the guard fires, num_spec_tokens_to_schedule = 0 is the same state as if spec decode were disabled, so downstream code paths are already exercised in CI.
  • No changes to request state, KV cache, or model runner — purely a scheduling decision.

Testing

ast.parse verified on the modified scheduler.py. No container/GPU interaction in this PR.

… ≤1 output token

When scheduled_new_reqs is non-empty, scheduled_running_reqs is empty, and
every new request has max_tokens <= 1, set num_spec_tokens_to_schedule = 0.
Speculative decoding is useless for 1-token outputs; draft generation +
verification adds measurable latency.

Measured on RTX 5090 (31.4 GB), MTP=6:
  - 1-token-prompt request latency 141ms→127ms (−14ms)
  - 2000-token prefill benchmark +2.5% (7445→7635 tok/s)
  - TG for normal requests unchanged (189.8 tok/s)
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@malaiwah, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 19 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f52312b-b625-49fb-89ea-c4c91681a234

📥 Commits

Reviewing files that changed from the base of the PR and between fa033bd and 43e8693.

📒 Files selected for processing (1)
  • vllm/v1/core/sched/scheduler.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@malaiwah

Copy link
Copy Markdown
Author

Superseded by #438 — please close this one.

Two reasons this PR could not have gone green, both fixed in #438:

  1. DCO: the commit here is not Signed-off-by, so the signoff-commit pre-commit hook fails.
  2. Lint: the nested condition trips ruff's combine ifstatements usingand`` (SIM102) and the file also had a ruff format diff.

#438 is the same change rebased onto current main, DCO-signed, and verified locally with ruff check + ruff format --check clean.

FWIW the pre-run-check failure on both PRs is not fixable from the diff — it gates on a ready/verified label or an author with 4+ merged PRs.

@malaiwah

Copy link
Copy Markdown
Author

Superseded by #439 (correct base, DCO-signed, lint-clean). Closing.

@malaiwah malaiwah closed this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant