[Test] Pin DSpark PD decode draft-input handoff regression - #34410
Phoenix3334 wants to merge 3 commits into
Conversation
|
@Ying1123 @EanWang211123 @DarkSharpness @Leoyzen could one of you please help trigger CI with This PR only adds a |
|
2026-08-11 runtime-context update: I refreshed the PR body with the full B300 stack disclosure and the follow-up D-only pressure data. The PR scope is still unchanged: test-only regression for the existing current-main DSpark PD decode handoff. The runtime data come from a separate v0.5.16 backport stack ( Newly documented follow-up: external concurrency C1280/C1536/C2048/C2560 all completed with zero request failures and no observed GPU correctness faults, but MRR stayed 1024 and per-rank running peak stayed 128. The body now explicitly labels those points as admission/queue-pressure evidence rather than a claim of >1024 true simultaneously running requests. The complete root-cause / integration / capacity map is maintained in #34297. |
Motivation
This PR adds regression coverage only for the DSpark disaggregation-decode draft-input handoff. It contains no production code — current
mainalready has the implementation:SpeculativeAlgorithm.build_disagg_draft_input()dispatches onis_dspark()python/sglang/srt/speculative/dspark_disaggregation.pybuilds the draft input and, under overlap, seedsfuture_indicesand publishes/stashes the relay stateWhat is not currently pinned is the invariant that this path must produce a non-
NoneSpecInputbefore the first decode step. An earlier stack (v0.5.16) lacked the DSPARK branch, so the call fell through toNoneand the first decode step failed with:DSpark, DP attention and disaggregation each passed independently; only the combination exposed this handoff gap. This PR pins that boundary so a future refactor cannot silently regress to
DSPARK + PD -> first decode -> spec_info == None.Design context / roadmaps
What the regression checks
test/registered/spec/dspark/test_dspark_disaggregation.py(CPU,base-a-test-cpu), scoped strictly to the handoff contract — it is not a scheduler simulation:build_disagg_draft_input()returns a non-None draft input for DSPARKfuture_indicesis seeded fromreq_pool_indicesfuture_dsa_topk_indices_available is False)FutureMapFutureMapis autospecced becausepublish()/stash()write device-side relay buffers that a CPU job cannot allocate; the calls themselves are part of the contract, so they are asserted rather than skipped. As a negative control, stubbing out theis_dspark()dispatch makes the builder returnNoneand the regression fails at the first invariant.Supporting runtime evidence (2026-08-11; not produced by this PR, not current main)
The following is supporting context only. It is an independent B300/B30Z runtime regression on a different stack, not an end-to-end result of this PR's code on current
main.Full stack disclosure:
Current
mainhas since evolved a dedicated DSpark disaggregation path, which is why this PR is regression-only.Hardware/model: 8x NVIDIA B30Z 275GB (B300-class), DeepSeek-V4-Pro-DSpark,
dspark_block_size = 5.Decode topology:
Workload: random input 60000 / output 1000 tokens, no simulated acceptance.
A locally profiled SPS table was used. Its batch-size probes are
[1, 8, 16, 32, 64, 96]; therefore the C1024 arm, which reaches per-rank batch 128, is out-of-domain and uses clamped interpolation. Its budget estimate should be treated as optimistic.Sustained decode-only regression
Totals: 18560/18560 successful requests, 0 client failures, 0 CUDA illegal-address faults, 0 device assertions, 0 scheduler exceptions, post-run
/health = 200. CUDA Graph replay was observed throughout; C1024 reached the captured per-rank batch-size 128 tier. Observed acceptance length was ~1.00–1.12.For compact ragged-verify coverage, the natural workload produced uniform verify lengths, so it does not count as ragged coverage. Using the existing budget control (
dspark_force_budget_frac = 0.5) produced a genuinely ragged window with verify lengths spanning 1–6; among fully parsed multi-request scheduling blocks, 39/43 = 90.7% hadmin(verify_len) != max(verify_len)(for example[4, 3, 3]). No GPU fault, NaN, or verify-budget violation was observed in that window.Follow-up external-concurrency / admission-pressure sweep
Same server limits (
max-running-requests=1024, per-rank CUDA-Graph max batch 128):All four arms completed with zero request failures, zero observed GPU correctness faults/retractions/preallocation warnings, CUDA Graph replay retained, and
/health = 200.Interpretation: these higher numbers are external concurrency / admission pressure, not proof of 1280–2560 simultaneously running requests.
max-running-requests=1024remains the active-running ceiling and per-rank running peak stays at 128. The next capacity phase must raise MRR / graph tiers and re-profile SPS before claiming a higher true in-flight capacity.Scope
This PR does not claim the CPU test replaces PD runtime CI and does not add or change DSpark PD support. It only pins the first-decode handoff invariant that current
mainalready implements.Related
CI States
Latest PR Test (Base): ❌ Run #34925212412
Latest PR Test (Extra): ❌ Run #34925211967
Latest PR Test (AMD ROCm 10): ❌ Run #34925212214