Repository navigation
Conversation
salexspb
force-pushed
the
upstream/pd-eagle-draft-proposal-20260929
branch
4 times, most recently
from
October 2, 2026 22:27
044595f to
ecbb734
Compare
salexspb
marked this pull request as ready for review
October 2, 2026 22:53
salexspb
requested review from
ByronHsu,
Duyi-Wang,
HaiShaw,
Qiaolin-Yu,
ShangmingCai,
Ying1123,
hnyls2002,
merrymercy and
sogalin
as code owners
October 2, 2026 22:53
salexspb
force-pushed
the
upstream/pd-eagle-draft-proposal-20260929
branch
2 times, most recently
from
October 2, 2026 23:17
2bf5a18 to
c7e556a
Compare
…ibution With rejection sampling enabled, each draft step hands the verifier the distribution its token was drawn from (ROCm enables rejection sampling by default for EAGLE top-k 1). PD prefill sends decode the first draft token, its probability and hidden state, but not that distribution, so build_eagle_disagg_draft_input left draft_probs unset. The first decode forward then failed in EagleWorkerV2.draft_forward (torch.stack over a None proposal); under a draft CUDA graph the stale proposal buffer would have been verified instead. Decode now proposes each received token with probability one: one row per request for single-layer EAGLE, and one per chain step for multi-layer EAGLE, whose verify reads the received chain directly and otherwise fails on the missing proposal. The verify stays exact: it accepts the token with probability p(X) and otherwise resamples from the target without it. A greedy request's target is one-hot, so its acceptance does not depend on the proposal.
ShangmingCai
force-pushed
the
upstream/pd-eagle-draft-proposal-20260929
branch
from
October 6, 2026 08:35
c7e556a to
bffaf71
Compare
Collaborator
|
/tag-and-rerun-ci |
Collaborator
|
/rerun-failed-ci |
15 of 40 tasks
This branch has not been deployed
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.
PD stack
Problem
With PD and EAGLE, whenever rejection sampling is enabled, the verifier is handed each draft step's proposal distribution. ROCm enables rejection sampling by default for EAGLE top-k 1 (#37134,
_should_auto_enable_hip_rejection_sampling), which is why this crashes there out of the box.EagleWorkerV2.draft_forwardstarts that list withspec_info.draft_probs. PD prefill sends decode the first draft token, its probability and its hidden state, but not the distribution, sobuild_eagle_disagg_draft_inputleavesdraft_probsunset. The PD decode then fails on its first forward:Under a draft CUDA graph, replay skips the proposal copy, and the verify would read a stale buffer instead. This happens with PD + EAGLE (including native MTP) whenever rejection sampling is enabled. Aggregated serving is unaffected.
Fix
build_eagle_disagg_draft_inputsetsdraft_probsto a one-hot FP32 proposal at each received draft token (pd_first_draft_proposal) whenever rejection sampling is on. Single-layer EAGLE gets one (batch, vocab) row. Multi-layer EAGLE gets the (batch, num_steps, vocab) chain, because its verify reads the received chain directly and otherwise fails with "draft_probs missing".The verify stays exact. It accepts the token X with probability p(X) and otherwise resamples from the target with X removed, so the committed token is distributed as p, the verifier's target distribution. A greedy request's target is one-hot, so it accepts X exactly when X is the target argmax, with or without the true proposal, and its acceptance is unchanged. Sampled requests accept X with probability p(X) rather than Σ min(p, q), and only at their first decode step. Nothing is added to the PD wire.
#40953 instead transfers the full FP32 distribution through PD metadata, which needs a bootstrap wire change and costs vocab × 4 bytes per request. This PR is the minimal fix that restores correctness; the two could be combined.
Tests
test/registered/unit/speculative/test_pd_eagle_draft_proposal.py(CPU, 5 tests):eagle_samplerequires;On this head: 5 passed.
python -m compileallandimport sglangare clean.End-to-end validation (on a HiSparse fork build)
Before this change, a PD 4:4 decode (native MTP, EAGLE 3 steps, top-k 1, rejection sampling on) died at its first request with the
torch.stackTypeError above. After it, in every configuration tested (aggregated TP8, PD 4:4 resident decode, PD 4:4 HiSparse decode), draft CUDA-graph capture completed, every service stayed up with no traceback, and 8/8 greedy chat prompts (including two needle prompts) were answered correctly, with mean accept length in the 2.6–2.65 range across configurations, matching the aggregated baseline.These runs used single-layer EAGLE (native MTP). Multi-layer EAGLE PD is covered by the unit test only.
CI States
Latest PR Test (Base): ✅ Run #37887765090
Latest PR Test (Extra): ❌ Run #37887764918
Latest PR Test (AMD ROCm 10): ❌ Run #37887765201