Skip to content

[Spec] Fix CDF boundary handling in TreeSpeculativeSamplingTargetOnly - #35798

Merged
hnyls2002 merged 1 commit into
sgl-project:mainfrom
modal-projects:fix/speculative-zero-probability-boundary
Sep 18, 2026
Merged

hnyls2002 merged 1 commit into
sgl-project:mainfrom
modal-projects:fix/speculative-zero-probability-boundary

Conversation

@nanjiangwill

@nanjiangwill nanjiangwill commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

TreeSpeculativeSamplingTargetOnly draws coins from [0, 1) but selects a target CDF bucket with coin <= cumulative_probability. At the lower endpoint (coin == 0) that accepts a draft token whose target probability is zero, and exact interior CDF boundaries land in the preceding bucket instead of the next positive-mass one.

Fixes #35771.

Modifications

  • Use the half-open condition coin < prob_acc / threshold_acc and require target_prob_single > 0 before either acceptance path can take a draft, in the shared device header sgl_kernel/speculative/sampling.cuh.
  • Add regression cases for zero-mass drafts (permissive and default thresholds), an exact interior CDF boundary, and both coin endpoints; update the zero-threshold expectation, which previously encoded the zero-mass acceptance.

Single-site change: the shared header backs the CUDA/ROCm JIT launchers and the MUSA AOT build, so all three pick the fix up. Rebased onto #40033, which moved these kernels to JIT — CUDA compiles them at runtime, so the fix ships without an sgl-kernel release.

Accuracy Tests

  • test/registered/kernels/ops/speculative/test_speculative_sampling.py: 7 passed.
  • Reverting only the kernel predicate turns that into 4 failed, 3 passed — zero-mass-zero-threshold, zero-mass-default-threshold, interior-boundary, and the zero-threshold tree case all regress, confirming the new coverage is what guards the fix.

Checklist

@nanjiangwill
nanjiangwill marked this pull request as ready for review August 21, 2026 05:46
@nanjiangwill
nanjiangwill force-pushed the fix/speculative-zero-probability-boundary branch from 44f8d10 to ba34758 Compare August 21, 2026 05:55
@Qiaolin-Yu Qiaolin-Yu self-assigned this Aug 21, 2026
@hnyls2002 hnyls2002 added the run-ci CI: run the baseline test suite on this PR label Sep 17, 2026
@hnyls2002

Copy link
Copy Markdown
Collaborator

/rerun-test python/sglang/kernels/aot/tests/speculative/test_speculative_sampling.py

@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test python/sglang/kernels/aot/tests/speculative/test_speculative_sampling.py:

⛔ python/sglang/kernels/aot/tests/speculative/test_speculative_sampling.py: File not found: test/python/sglang/kernels/aot/tests/speculative/test_speculative_sampling.py

@hnyls2002 hnyls2002 changed the title [Spec] Fix target-only sampling CDF boundaries [Spec] Move CUDA speculative kernels to JIT and fix sampling CDF boundaries Sep 17, 2026
@github-actions github-actions Bot added the dependencies Pull requests that update a dependency file label Sep 17, 2026
Use half-open sampling intervals and require positive target mass before accepting a draft token in the shared target-only sampler.\n\nAdd native regression coverage for zero-mass drafts, exact CDF boundaries, and endpoint coins.\n\nFixes sgl-project#35771
@hnyls2002
hnyls2002 force-pushed the fix/speculative-zero-probability-boundary branch from 7e5c943 to 705cb5d Compare September 18, 2026 00:34
@hnyls2002 hnyls2002 changed the title [Spec] Move CUDA speculative kernels to JIT and fix sampling CDF boundaries [Spec] Fix CDF boundary handling in TreeSpeculativeSamplingTargetOnly Sep 18, 2026
@hnyls2002

Copy link
Copy Markdown
Collaborator

/rerun-test test_speculative_sampling.py

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test test_speculative_sampling.py:

🚀 1-gpu-h100 (1 test): ✅ View workflow run

cd test/ && python3 registered/kernels/ops/speculative/test_speculative_sampling.py

@hnyls2002
hnyls2002 merged commit 740f57a into sgl-project:main Sep 18, 2026
121 of 148 checks passed
@nanjiangwill
nanjiangwill deleted the fix/speculative-zero-probability-boundary branch September 18, 2026 23:41
nanjiangwill added a commit to modal-projects/sglang that referenced this pull request Sep 19, 2026
…g CDF boundaries

Backport the corrected target-only sampler through the JIT kernel path available on main. Reject zero target mass and use half-open CDF intervals for DFlash and EAGLE.

Co-authored-by: Liangsheng Yin <hnyls2002@gmail.com>
nanjiangwill added a commit to modal-projects/sglang that referenced this pull request Sep 19, 2026
…gl-project#35798)

Reject zero-probability candidates and use half-open CDF intervals in the v0.5.20 AOT sampler.
nanjiangwill added a commit to modal-projects/sglang that referenced this pull request Sep 20, 2026
…gl-project#35798)

Reject zero-probability candidates and use half-open CDF intervals in the v0.5.20 AOT sampler.
efschu pushed a commit to efschu/htsglang that referenced this pull request Sep 24, 2026
…SpeculativeSamplingTargetOnly

Upstream 740f57a (sgl-project#35798, nur main). Upstream liegt der Kernel im JIT-
Baum (kernels/jit/include/sgl_kernel/speculative/sampling.cuh), im Fork im
AOT-Baum sgl-kernel/csrc/speculative/speculative_sampling.cuh:80.

Portiert (nur Quelle, NICHT gebaut): Annahme nur mit Zielmasse
(target_prob_single > 0) und halboffene CDF-Grenze (coin < acc statt <=).
Vorher akzeptierte der Kernel bei coin == 0 einen Draft-Token, dem das Ziel
Null Masse gibt, und nahm an einer inneren Intervallgrenze das falsche
Intervall. Tests: upstream-Erwartungen fuer den threshold-0/0-Fall
angepasst und test_target_only_sampling_cdf_boundaries (5 Faelle) in
sgl-kernel/tests/speculative/test_speculative_sampling.py (CUDA + neu
gebautes sgl_kernel noetig, hier nicht lauffaehig).

Anwendbarkeit 27B: NICHT auf dem Standardpfad. D mit DFlash2 akzeptiert
T>0-Runden ueber den Selector (_selector_sampling_accept ->
dspark accept_sampling -> reject_sampling.chain_speculative_sampling_triton,
dort "coin * q < p" = strikt, Nullmasse wird nie angenommen). Der CUDA-
Kernel laeuft nur im DFLASH-Rueckfall ohne Selector
(compute_dflash_sampling_correct_drafts_and_bonus, dflash_utils.py:763;
z.B. SGLANG_DFLASH_DISABLE_SELECTOR=1 oder ein DFLASH-Draft ohne Selector)
und bei EAGLE/NEXTN mit Verify und T>0 (P ist draft-kv-only).

Pruefung ohne GPU: Python-Emulation des Annahme-Praedikats (float32) ueber
die 5 upstream-Grenzfaelle: neu = erwartete Tokens/Anzahl, alt nimmt in 3
Faellen falsch an (Nullmasse bei coin 0, innere Grenze). Kein Kernel-Lauf.

Build (NICHT ausgefuehrt): sgl-kernel-Wheel aus diesem Baum mit
SGL_KERNEL_LIMIT_CUDA_ARCHS='86;120a' (CMake-Cache, CMakeLists.txt:250)
bauen, in /spinning/htsglang-gpu/.venv ersetzen (derzeit sglang-kernel
0.4.4 aus /spinning/wt-398-wheel, 03.08.) -- ausserhalb eines Boots, danach
pytest sgl-kernel/tests/speculative/test_speculative_sampling.py auf einer
Karte (sm86 und sm120).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

amd dependencies Pull requests that update a dependency file jit-kernel mthreads run-ci CI: run the baseline test suite on this PR sgl-kernel speculative-decoding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Target-only speculative sampler can accept a zero-probability draft at RNG boundary

3 participants