Skip to content

fix(pp): generate MTP draft tree after prefill - #28

Open
lmyybh wants to merge 4 commits into
antgroup:sglang-communiy-main-pp-mtpfrom
lmyybh:pp_mtp
Open

fix(pp): generate MTP draft tree after prefill#28
lmyybh wants to merge 4 commits into
antgroup:sglang-communiy-main-pp-mtpfrom
lmyybh:pp_mtp

Conversation

@lmyybh

@lmyybh lmyybh commented Jul 30, 2026

Copy link
Copy Markdown

Motivation

Dummy bootstrap Real draft tree
After prefill Builds a dummy tree by repeating the bonus token Runs draft() and builds a real tree
First decode step Mainly serves as a bootstrap step Can verify real draft tokens immediately
Extra work No extra draft call One extra draft call after prefill
Implementation Simpler More state handling between prefill and decode

Speed Tests and Profiling

  • environment: 16 x H800
  • model: GLM-5.2-FP8 (TP8 CP8 PP2)

sglang command

export SGLANG_ENABLE_UNIFIED_RADIX_TREE=1
export SGLANG_PP_LAYER_PARTITION=40,38
sglang serve \
    --model-path GLM-5.2-FP8 \
    --tp 8 \
    --pp-size 2 \
    --enable-prefill-cp \
    --cp-strategy interleave \
    --attn-cp-size 8 \
    --trust-remote-code \
    --disable-overlap-schedule \
    --nnodes 2 \
    --dist-init-addr ${ip}:5000 \
    --node-rank ${node} \
    --kv-cache-dtype fp8_e4m3 \
    --enable-cache-report \
    --reasoning-parser glm45 \
    --tool-call-parser glm47 \
    --mem-fraction-static 0.8 \
    --cuda-graph-max-bs-decode 64 \
    --port 8000 \
    --speculative-algorithm EAGLE \
    --speculative-num-steps 3 \
    --speculative-eagle-topk 1 \
    --speculative-num-draft-tokens 4

benchmark command

python -m sglang.benchmark.serving \
    --backend sglang-oai-chat \
    --port 8000 \
    --model GLM-5.2-FP8 \
    --dataset-name sharegpt \
    --dataset-path ShareGPT_V3_unfiltered_cleaned_split.json \
    --request-rate inf \
    --max-concurrency 16 \
    --num-prompts 100 \
    --warmup-requests 10 \
    --flush-cache
metric prefill_dummy prefill_draft change
output_throughput (tok/s) 474.836 487.109 +2.58%
mean_ttft (ms) 349.051 345.166 -1.11%
mean_tpot (ms) 30.241 27.745 -8.25%
mean_itl (ms) 29.109 28.303 -2.77%
accept_length 2.954 2.997 +1.45%

Checklist

Review and Merge Process

  1. Ping Merge Oncalls to start the process. See the PR Merge Process.
  2. Get approvals from CODEOWNERS and other reviewers.
  3. Trigger CI tests with comments or contact authorized users to do so.
    • Common commands include /tag-and-rerun-ci, /tag-run-ci-label, /rerun-failed-ci
  4. After green CI and required approvals, ask Merge Oncalls or people with Write permission to merge the PR.

CI States

Latest PR Test (Base): ⚠️ Run #30509714031
Latest PR Test (Extra): ⚠️ Run #30509713874

liuqi-1 and others added 4 commits July 29, 2026 19:04
Under PP + DP attention, an idle rank (no local requests) on a global
prefill step must follow the prefill path, not the verify path. Routing
it through verify emits speculative_num_steps extra draft-decode
collectives that desync the MoE cross-DP all-gather and hang. Gate the
prefill branch on is_extend OR (pp_enabled and idle and is_extend_in_batch),
mirroring the scheduler's is_extend_in_batch lockstep. _draft_extend_for_prefill
already short-circuits idle batches, so the target+single-draft_extend
collective sequence stays identical across DP ranks.
need_topk gated only on spec_algo would still take the topk stash path
when the payload carries no topk_p (topk_p is None), crashing at
payload.topk_p[0]. Add the payload.topk_p is not None guard, matching the
existing payload.hidden_states check for need_hidden_states.
@lmyybh

lmyybh commented Jul 30, 2026

Copy link
Copy Markdown
Author

@liuqi-1

@liuqi-1

liuqi-1 commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

@lmyybh I tested your code using GLM5.2 (PP2+TP8). An error about "pool memory leak" occurs.


[2026-08-01 12:10:03 PP1 ATTN_CP0 TP0] Scheduler hit an exception: Traceback (most recent call last):
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/managers/scheduler.py", line 4784, in run_scheduler_process
    scheduler.run_event_loop()
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/managers/scheduler.py", line 1571, in run_event_loop
    dispatch_event_loop(self)
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/managers/scheduler.py", line 4631, in dispatch_event_loop
    scheduler.event_loop_pp()
  File "/usr/local/lib/python3.12/dist-packages/torch/utils/_contextlib.py", line 124, in decorate_context
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/managers/scheduler_pp_mixin.py", line 174, in event_loop_pp
    self.on_idle()
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/managers/scheduler.py", line 3805, in on_idle
    self.invariant_checker._report_leak("pool", "\n".join(messages))
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/managers/scheduler_components/invariant_checker.py", line 428, in _report_leak
    raise_error_or_warn(
  File "/usr/local/lib/python3.12/dist-packages/sglang/srt/utils/common.py", line 4500, in raise_error_or_warn
    raise ValueError(message)
ValueError: pool memory leak detected! [full] total=2107968, available=2107712, evictable=0, protected=0, session_held=0, uncached=0

The test cli is:

NCCL_DEBUG_SUBSYS="" \
TORCHINDUCTOR_CACHE_DIR=/home/admin/inductor_root_cache \
SGLANG_PP_SKIP_PURE_CHUNKED_OUTPUT_COMM=1 \
SGLANG_PP_LAYER_PARTITION=40,38 \
nohup python -m sglang.launch_server \
  --model-path /home/models/GLM-5.2-FP8 \
  --host 0.0.0.0 --port 8076 \
  --attention-backend dsa \
  --dsa-prefill-backend flashmla_kv \
  --dsa-decode-backend flashmla_kv \
  --kv-cache-dtype fp8_e4m3 \
  --mem-fraction-static 0.83 \
  --tp-size 8 --pp-size 2 \
  --nnodes 2 --node-rank 0 \
  --dist-init-addr 10.13.2.89:25000 \
  --chunked-prefill-size 8192 \
  --enable-nsa-prefill-context-parallel \
  --nsa-prefill-cp-mode round-robin-split \
  --disable-radix-cache \
  --reasoning-parser glm45 \
  --tool-call-parser glm47 \
  --speculative-algo EAGLE \
  --speculative-num-steps 3 \
  --speculative-eagle-topk 1 \
  --speculative-num-draft-tokens 4 \
  
  python3 -m sglang.test.run_eval \
  --base-url http://localhost:8076 \
  --eval-name gsm8k \
  --num-threads 64 \
  --max-tokens 2048 \
  --temperature 0.0 \
  --num-examples 200 \
  --num-shots 5 \
  --gsm8k-data-path '/home/shared/liuqi/gsm8k_test.jsonl'

I have updated my branch onto the main. Could you fix your code, and rebase your code onto my branch?

@liuqi-1
liuqi-1 force-pushed the sglang-communiy-main-pp-mtp branch from f4df794 to a747ca5 Compare August 17, 2026 03:50
@liuqi-1
liuqi-1 force-pushed the sglang-communiy-main-pp-mtp branch 2 times, most recently from a741584 to 12abd13 Compare August 18, 2026 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants