[Bugfix][Spec Decode] Validate YaRN for extended native MTP context - #2
Merged
Merged
Conversation
Assisted-by: OpenAI Codex
ga-it
marked this pull request as ready for review
August 28, 2026 18:41
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.
[Bugfix][Spec Decode] Validate YaRN for extended native MTP context
Purpose
A same-checkpoint native MTP drafter can retain the checkpoint's native
max_position_embeddingseven when the target is explicitly extended withYaRN. For Qwen3.8 this left the drafter at 262,144 while the target was served
at a larger context. Above the drafter limit, speculative decoding fell back to
target-only decoding and the changing
max_seq_lenargument defeatedwarning_once, producing one warning per output step.This PR:
rope_parameterswithrope_type: yarn;factor > 1, and anoriginal_max_position_embeddingsthat exactly matches the drafter's nativelimit;
original * factorYaRN ceiling;It does not invent RoPE scaling, change the target limit, change unrelated
draft models, or silently extend an unvalidated drafter.
Base SHA:
62ad1e02693f4c857f3b7547cef1860ee54e8053.Context relationship
The validated V100 checkpoint has a native target/drafter limit of 262,144.
Factor-4 YaRN gives a mathematical ceiling of 1,048,576. The tested service
caps both target and native drafter at 1,000,000, leaving 48,576 tokens of
margin. The former 320,000 and 512,000 values were rollout tiers, not model
limits.
Duplicate-work audit
The complete open PR list was refreshed on 2026-08-28 at the base SHA; no open
PR contains this fail-closed inheritance or stable fallback warning.
rejected aggregate. It unconditionally overwrites the
drafter length and changes automatic NTK behavior. This PR instead accepts
only an explicit, internally consistent target YaRN configuration and
otherwise fails closed.
PR 391, and
PR 399, plus open
PR 398, improve V100 MTP4
execution but do not extend the drafter's validated context.
runtime correctness, not YaRN context inheritance.
issue 93 describe separate
long-prefill and non-MTP paths and are not claimed as fixed here.
Test Plan
Local current-main checks:
Focused CPU tests were added for:
Test Result
The same formatting, lint, byte-compilation, and diff checks also pass in a
disposable Linux worktree on
gazasrv16, with the patch applied to the statedbase SHA. No production container or GPU was touched.
A focused pytest run was attempted there. An isolated editable environment
from unmodified current main first failed dependency resolution because of the
separate TokenSpeed/TVM-FFI conflict described in the companion candidate. A
test-only overlay of that companion patch allowed the precompiled editable
install (191 packages) and the full CUDA test dependency set to install. Pytest
then stopped during collection because the precompiled editable source layout
did not provide
vllm._C. A CPU-source fallback compiled most targets but wasblocked by the host's missing
numa.hdevelopment header and a Torch CPU APImismatch. The production host packages were deliberately not changed.
Accordingly, the new test cases are present but no pytest pass is claimed. The
human submitter must run them in the prescribed, fully provisioned Linux UV
environment before upstream submission:
Live V100 validation
The exact source behavior was also built and exercised in a running SM70
image. These measurements are specifically for four V100-SXM2-32GB GPUs with
TP4; they are not Blackwell results.
philbert440/Qwen3.8-27B-W4A16-AWQ1cat-vllm-sm70:qwen38-27b-awq-main-62ad1e0-mtp4-yarn-pr331-cu128sha256:d0fdeefbea5b61a12caa75e57543e06a01b2dadf3ea4eb74d0dfa0a90a48b95amax-num-seqs=2HTTP
/health,/v1/models, and/metricsall returned 200. The serviceremained healthy with zero restarts. All four V100s saturated during cold
prefill; peak observed KV occupancy was 35.1%.
Performance
At this long prompt, current MTP4 decode was 3.56x-3.66x the target-only
baseline and 1.37x-1.40x the earlier MTP2 result. The total-latency crossover
was approximately 1,800 generated tokens versus target-only and 11,000-12,000
versus MTP2 because current-main cold prefill is slower.
The current-main cold TTFT of about 691 seconds is roughly 139-146 seconds
slower than the earlier target-only/MTP2 baselines. This PR does not claim to
fix that separate prefill regression.
Tokenization and prefix cache
Backend tokenization took 2.4811-2.51695 seconds for roughly 564.6k tokens,
equivalent to 224,311-227,549 tokens/s, so tokenization was not the cold-query
bottleneck. The identical replay reused 562,368 of 564,577 queried prefix
tokens (99.6087%), reducing TTFT from about 691 seconds to 9.2287 seconds.
Warning and fallback behavior
generated 18,167 output tokens, and emitted 18,169 changing-argument
over-limit warnings.
drafter tier generated 128 tokens with zero drafts and exactly one warning.
drafts and emitted one warning.
flood. Each cold request emitted one separate Transformers advisory because
the original checkpoint metadata still declares 262,144.
Real OpenWebUI workload
A production OpenWebUI agent request on the target-only control received
733,366 prompt tokens, reused 720,000 prefix tokens, and generated 23,724
tokens at approximately 8.5-9.2 tok/s. It completed without a proxy timeout,
queue, engine error, or restart. Its long generation lies well beyond the
measured MTP4 total-latency crossover and motivated keeping the MTP4 route for
Hermes/OpenClaw workloads.
Validation boundary
The service booted with matching 1,000,000 target/drafter limits and MTP was
tested end to end through 564,580 prompt tokens. A near-1M cold prefill has not
yet been executed, so this PR does not claim an end-to-end measurement at the
absolute configured limit.
Risk and rollback
Invalid or implicit scaling fails during configuration instead of failing
mid-request. Unextended native MTP and separate draft checkpoints are unchanged.
At runtime, requests above an intentionally lower drafter cap still fall back
to target-only decoding; only repetitive logging is suppressed. Rollback is a
revert of these three files.
Essential Elements of an Effective PR Description Checklist
BEFORE SUBMITTING, PLEASE READ https://docs.vllm.ai/en/latest/contributing (anything written below this line will be removed by GitHub Actions)