Skip to content

[Qwen3.8 CP 4/4] Prefill context parallel E2E support of Qwen3.8 - #39724

Merged
Fridge003 merged 10 commits into
sgl-project:mainfrom
Shunkangz:cp/4-qwen4exp
Oct 14, 2026
Merged

Fridge003 merged 10 commits into
sgl-project:mainfrom
Shunkangz:cp/4-qwen4exp

Conversation

@Shunkangz

@Shunkangz Shunkangz commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Modifications

Accuracy Tests

Speed Tests and Profiling

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 #38520129531
Latest PR Test (Extra): ❌ Run #38520129446
Latest PR Test (AMD ROCm 10): ⏳ Run #38520129509

detain added a commit to detain/sglang that referenced this pull request Sep 17, 2026
Manifest of the nine upstream PRs and the local commits this branch
carries on top of upstream main, in build order, with the reasoning for
the CP series (sgl-project#39721-sgl-project#39724) that was evaluated and left out, the
HiCache caveat (sgl-project#39830), and the editable-install trap that makes git
worktrees useless for baselining library changes here.

Generated from git, so the SHAs match the branch exactly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Fridge003 Fridge003 added the release-highlight Candidate PR for release note highlight label Oct 8, 2026
Qwen4-Exp runs prefill CP with CP-TP group sharing (--enable-prefill-cp
--attn-cp-size N --tp-size N --cp-strategy zigzag): the residual stream,
QSA attention and the QSA indexer are zigzag CP-sharded, and the GDN and
the MoE keep their TP partition.

- Model: shard the residual after the embedding and gather it before the
  logits. The GDN gathers the sequence, sums its TP partials and keeps this
  rank's rows; the PLE gathers, runs and shards; the QSA indexer gets the
  global RoPE positions. The MoE needs no model code: the boundary's MoE-CP
  gather -> TP experts -> all-reduce -> take-back already does it, so the
  two MHC construction guards are lifted under the flag.
- PD: a sharing prefill rank r holds every KV head, the CP-replicated
  QSA/PLE state and GDN head shard r. It registers as TP rank r of a CP-1
  prefill and sends its own state, and the mamba path slices by the
  linear-attention TP width. Before, every decode rank got rank 0's shard.
- Hook: register Qwen4-Exp; allow a prefill node (mooncake only); reject a
  decode node, EP, MoE a2a and PP.
- Test: PD E2E, prefill TP4/CP4 -> decode TP4 on 8x B200, with a
  /server_info guard, a 20K-token needle at three depths, and GSM8K.

Measured on 8x B200 (NVFP4): GSM8K 0.975 (200, thinking) and needle 3/3,
the same as a plain-TP4 prefill node (0.975, 3/3). With the PD transfer
change reverted, the needle fails at two of three depths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shunkangz and others added 2 commits October 8, 2026 20:46
…he non-CP path

- Hook: reject --enable-waterfill (it switches the MoE to DeepEP + EP after
  this hook) and SGLANG_DISAGG_STAGING_BUFFER on a prefill node (decode sees
  this prefill as TP cp_size while its sender stages by attention TP 1).
- Model: shard with the existing cp_split_before_forward.
- Tests: a short-prompt E2E check of the non-CP path under the flag, plus
  CPU rows for the CP-rank-as-TP-rank registration and the state-skip rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rank pairing already lives in CommonKVManager; what stayed per backend
was the TP width the state is compared and sliced by. CommonKVManager now
names it state_tp_size (attention TP, or the TP group under CP-TP group
sharing), and mooncake, nixl and mori use it for the mamba state and the
QSA state, while KV heads keep following attention TP. The hook no longer
requires mooncake.

Verified prefill TP4/CP4 -> decode TP4 on 8x B200 over both backends:
nixl GSM8K 0.96, mooncake 0.97, needle 3/3 on each. Mori is not installed
in the test container and was only read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shunkangz and others added 3 commits October 9, 2026 01:16
Under CP-TP group sharing the GDN layer hand-wrote its collectives: gather
the zigzag shard into token order, sum the TP-partitioned heads, shard back.
A stage can now declare both facts and the boundary does the rest:

- declare_attn(sum_group=SumGroup.TP): the output owes a sum over the group
  the heads are partitioned over, here the TP group while attention TP is 1.
  An ordinary batch completes it at the next input like any attention sum.
- declare_attn(in_token_order=True): on a CP extend the stage reads the whole
  sequence in token order. Its entry reads on this rank's shard and then
  gathers in token order; the next input sums over TP, takes this rank's
  shard back, writes it into the residual there, and gathers for the MoE.

Qwen4-Exp declares both for its linear-attention layers, and its GDN layer is
back to prepare -> linear_attn -> finish. The static sum check no longer needs
the sharing exemption. Other models resolve the same plans: the new fields
default to today's behaviour, and the new entry branch only takes an edge
that raised before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The QSA indexer's CP path takes the whole sequence's RoPE positions. The
model threaded them through every layer as cp_global_positions, but the
batch keeps them whole under CP-TP group sharing: forward_batch.positions,
or forward_batch.mrope_positions when the model runs mrope. The attention
layer now reads them there, and the model keeps a plain flag for its final
gather.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's sgl-project#42044 (GLM-5.3-Flash prefill CP) added declare_attn(tp_group=)
and an ATTN_CP entry for a head-parallel mixer on full rows: the head
partition this branch declared as sum_group. The resolution uses main's
names and keeps what zigzag needs:

- The GDN declares tp_group plus the branch's in_token_order. Under
  sharing its sum is ATTN_CP, the same coordinator as TP.
- The token-order take-back is a move in main's ATTN_CP entry
  (ops.cp_take_back_in_token_order: complete the sum, then take this
  rank's zigzag shard). Main's CP moves are rank-major and would take
  back the wrong rows. prepare._cp_take_back_update_read is gone.
- _select_entry_step returns EntryStep (sgl-project#43453); the token-order gather
  is its input_move.
- _bind_stage exempts both DSA/MLA CP and CP-TP group sharing.
- _qwen4_exp_stage_facts (sgl-project#43460) declares the GDN options; the linear
  layer's stage_facts passes linear_attention=True. _ffn_exit_rows went
  with ExitRows (sgl-project#42936).
- Hook: both models registered. The EP/a2a/waterfill/PP/decode
  rejections and the PD prefill allowance are Qwen4-Exp's; GLM keeps
  main's disaggregation rejection. Qwen4-Exp keeps the plain speculative
  rejection message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Shunkangz

Copy link
Copy Markdown
Contributor Author

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci CI: run the baseline test suite on this PR label Oct 12, 2026
@Fridge003

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🚀 8-gpu-b200 (1 test): ❌ View workflow run

cd test/ && python3 registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@Shunkangz

Copy link
Copy Markdown
Contributor Author

/rerun-test test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

⛔ test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py: File not found: test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

Resolve the MoRI Mamba-state transfer conflict by retaining upstream layer-aware transfer blocks and passing the branch state TP size to the slicing helper.

Validation: 455 unit tests and 7,334 subtests passed across layer-boundary, disaggregation wire/bootstrap, and MoRI deferred-release tests; 97 focused state-transfer cases passed. Python syntax, isort, and git diff checks passed.
Include upstream 7ff3a11, which landed during merge validation. This update only changes JIT activation fast-math architecture selection and merges without conflicts.
@Fridge003

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🚀 8-gpu-b200 (1 test): ❌ View workflow run

cd test/ && python3 registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@Fridge003

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Rebase Required Before Re-run

A major update has landed on main. Your PR is diverged relative to required base commit c053fc71d3bd.

Re-run was not dispatched. What to do:

  • Rebase your branch onto the latest main and push again
  • Follow issue #21065 for context
  • CI-fix PRs may request the bypass-maintenance label to skip this check

@Fridge003

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

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

cd test/ && python3 registered/e2e/disaggregation/test_qwen4_exp_pd_prefill_cp.py

@Fridge003
Fridge003 merged commit 0d130f1 into sgl-project:main Oct 14, 2026
94 of 119 checks passed
Shunkangz added a commit to Shunkangz/sglang that referenced this pull request Oct 15, 2026
Conflict in qwen4_exp.py _compute_qsa_topk_indices_eager. Main's cp/4
(sgl-project#39724) added the cp_global_rope_positions indexer kwargs next to the
use_host_prefill_lengths override that this branch drops. Kept main's
CP kwargs and dropped the override: the QSA backend already fills
prefill_sequence_lengths_cpu for every non-speculative extend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-highlight Candidate PR for release note highlight run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants