Repository navigation
[Speculative] Support block verification for the DFlash family - #43012
Merged
Qiaolin-Yu merged 2 commits intoOct 8, 2026
Merged
Conversation
Extend --speculative-use-block-verification to DFLASH and DSPARK. DSpark sampled drafts, DFlash candidate-selector drafts, and sampled LiLiCorr drafts already verify through the Triton chain sampler with their full proposal distribution; thread the flag into that shared accept path. Greedy DFlash drafts are point masses, where block and token-wise verification accept the same prefixes, so the worker warns that the flag has no effect there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maocheng23
requested review from
BBuf,
DarkSharpness,
HaiShaw,
HydraQYH,
JustinTong0323,
Qiaolin-Yu,
Ying1123,
celve,
hnyls2002,
merrymercy,
sogalin,
wisclmy0611,
yuan-luo and
zijiexia
as code owners
October 7, 2026 18:34
Collaborator
Author
|
/tag-and-rerun-ci |
Picks up sgl-project#42754, whose server-args test the Intel CPU image (built from the PR head) otherwise runs against the pre-sgl-project#42754 HiCache hook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Qiaolin-Yu
approved these changes
Oct 7, 2026
heislera763
added a commit
to heislera763/sglang-v100-plus
that referenced
this pull request
Oct 9, 2026
Share adjacent sparse queries' exact key support within the qualified short-context geometry, skip empty early tiles, and batch indexer scoring with bounded scratch. Extend FP32 mHC projection/RMS to independent 1-8-row verification batches. Add optional routed NVFP4 expert GEMV and full-snapshot GLM PP2 state commit capture. Preserve activation/rounding, state ownership and unsupported-schedule contracts; leave optional paths disabled by default where full-model gains remain unproven. Backport upstream e902207/sgl-project#43012 sampled DFlash block verification and select explicit Torch CUDA softmax on SM70. Validation: 90 CPU tests/89 subtests, 67 kernel namespace cases, 48 affected GPU cases, independent and held-native operator references, and 32 byte-exact native state checks. Repeated near-8K/512-output sampled TP8/PP2 ordinary/MTP matrix, EOS/logprob/penalty/cancel/reuse protocols, two images and a short video passed. Existing numerical bounds unchanged. Captures and benchmark tooling stay outside the fork; all private GPU workers are stopped.
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.
Motivation
#42297 added
--speculative-use-block-verification(Block Verification Accelerates Speculative Decoding, Algorithm 2) for linear EAGLE / EAGLE3 / NEXTN only. The DFlash family (DFLASH,DSPARK) already verifies sampled drafts through the same Triton chain sampler, but the flag was rejected for these algorithms at startup.Modifications
speculative_hook.py): acceptDFLASHandDSPARKwith--speculative-use-block-verificationon CUDA/ROCm. NPU stays rejected becausesgl_kernel_npu's chain sampler has no block mode. Only EAGLE/EAGLE3 still auto-enable--speculative-use-rejection-sampling. DFlash-family sampled paths always pass their proposal distribution and never read that flag.dspark_accept.py):AcceptSampling/accept_sampling/_accept_sampling_coretake an explicitblock_verificationkeyword and callchain_speculative_sampling_triton(..., block_verification=True)when it is set. The kernel is unchanged from [Speculative] Add opt-in block verification #42297.DSparkWorkerV2passes the flag toTargetVerifyExecutor, which forwards it throughaccept_draft_tokensto both the all-sampling branch and the mixed greedy/sampling branch.DFlashWorkerV2._selector_sampling_acceptforwards it. This method serves the candidate-selector drafts and the sampled LiLiCorr drafts (SGLANG_ENABLE_LILICORR_SAMPLING=1).q(x_i) = 1,r_i = prod p(x_j), and token-wise verification already reaches the per-prefix upper boundP(accept >= i) = r_i. Block verification therefore accepts the same prefixes, so these paths keep the existing target-only verifier. The worker logs a warning that the flag has no effect.cutoff_verify_lens) still truncates the sampler's result afterward, as it does in token-wise mode. A prefix of a target-distributed sample is still target-distributed, so the cutoff does not affect correctness.Accuracy Tests
test_block_verification_args.py:test_block_verification.py::test_dflash_family_accept_uses_block_verification(GPU): calls DSpark's realaccept_draft_tokens, in both the all-sampling and the mixed-greedy branches. The proposal usesq(x1) = 1, p(x1) = 1/2andq(x2) = 1/2, p(x2) = 1, sor_1 = 1/2andr_2 = 1.Local (macOS, CPU, Torch 2.14.1):
PYTHONPATH=python python -m pytest -q \ test/registered/unit/spec/test_block_verification_args.py \ test/registered/unit/spec/test_spec_registry.py \ test/registered/unit/spec/test_eagle_gate_routing.py \ test/registered/unit/spec/test_spec_cpu_overlap_constraint.py # 45 passed, 21 subtests passedGPU (one NVIDIA GB300; Torch 2.14.1+cu130, sglang-kernel 0.4.9, FlashInfer 0.7.0.post1, Triton 3.8.0, Transformers 5.17.0; source snapshot of
c8699a8046):python -m pytest -q \ test/registered/kernels/ops/speculative/test_block_verification.py \ test/registered/unit/spec/test_block_verification_args.py \ test/registered/spec/dspark/test_dspark_kernel_parity.py # 30 passed, 43 subtests passedPre-commit passed on all changed files.
Speed Tests and Profiling
Qwen3.8-27B + DFlash2 / AIME25 end-to-end
Block verification increased acceptance length on all three seed pairs, by +3.31% pooled. That is larger than the +0.88% that #42297 measured for MTP with three proposed tokens. DFlash2 proposes seven tokens per step, so there are more prefixes for block verification to rescue after an early rejection. The pooled throughput gain of +1.76% was not consistent: per seed it was +2.75%, +2.67%, and -0.29%. The accuracy and cap-hit differences are within run-to-run noise for three sampled runs.
Setup:
Qwen/Qwen3.8-27BBF16, revision1d4bf0f2ff. Draftincoai/Qwen3.8-27B-DFlash2, revision015e795645(DFlash2DraftModel: candidate selector with top-k 16, block size 8).--speculative-algorithm DFLASH --speculative-num-draft-tokens 8.--speculative-use-block-verification. The server log confirms that selector sampling is folded into the draft CUDA graph (sampling_enabled=True), and neither arm logged the no-effect warning.Protocol: same as #42297.
b4bdeba5...). Thinking is enabled at xhigh. Sampling uses temperature 1.0, top-p 0.95, and top-k 20, with at most 32,768 new tokens.Qwen3.8-27B + DSpark / AIME25 end-to-end
DSpark shows the same effect. Block verification increased acceptance length on all three seed pairs, by +3.13% pooled (+3.02%, +2.42%, +3.96% per seed). Throughput was flat at +0.54% pooled, and per seed it was +1.51%, +0.42%, and -0.45%. Other jobs were running on the same node's other GPUs during this run, so its throughput is noisier than the DFlash2 run's. The differences in score and cap hits are within run-to-run noise for three sampled runs.
Setup: same code, image, target model, server settings, and protocol as the DFlash2 run above. The differences are:
--speculative-algorithm DSPARKwith draftRadixArk/Qwen3.8-27B-DSpark, revisionb9a5dbdf03(DSparkDraftModelwith a vanilla Markov head and a confidence head). Gamma 7 is read from the checkpoint, so the verify window is 8.SGLANG_RAGGED_VERIFY_MODEis left at its default,static.--speculative-use-block-verification. Every server loggedDSpark draft proposal (greedy + sampling) folded into the draft cuda graph, so the sampling batches drafted fromsoftmax(corrected_logits / T)and verified on the eager accept path, where the flag is wired. The folded in-graph accept serves all-greedy batches only.Sampler
No kernel change. The sampler cost is the block-mode cost measured in #42297. Paths that do not opt in are unchanged: the flag defaults to off, and greedy DFlash drafts never reach the block sampler.
Checklist
🤖 Generated with Claude Code
CI States
Latest PR Test (Base): ✅ Run #37692039422⚠️ Not enabled -- add
Latest PR Test (Extra):
run-ci-extralabel to opt in.Latest PR Test (AMD ROCm 10): ❌ Run #37692039310