Repository navigation
[XPU] Support decode context parallelism (DCP) on Intel XPU - #34355
Merged
Merged
Conversation
AnuSajikumar6264
requested review from
Fridge003,
HaiShaw,
JustinTong0323,
Qiaolin-Yu,
Ying1123,
alphabetc1,
ch-wan,
fzyzcjy,
hanming-lu,
hebiao064,
hnyls2002,
hzh0425,
ispobock,
merrymercy,
sogalin,
wisclmy0611,
xiezhq-hermann,
yizhang2077 and
zijiexia
as code owners
August 11, 2026 04:17
Contributor
|
/tag-run-ci-label |
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
September 11, 2026 04:28
9a7a1eb to
e5d1a81
Compare
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
September 11, 2026 06:20
e5d1a81 to
488ebc6
Compare
AnuSajikumar6264
requested review from
Kangyan-Zhou and
bingxche
as code owners
September 11, 2026 06:20
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
September 11, 2026 06:30
488ebc6 to
1e59980
Compare
siju-samuel
approved these changes
Sep 15, 2026
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
October 3, 2026 02:19
08e81db to
97386f3
Compare
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
October 7, 2026 05:53
6c11f30 to
a53ed01
Compare
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
4 times, most recently
from
October 7, 2026 14:21
1a1eeae to
2b7edb2
Compare
sunjiweiswift
approved these changes
Oct 8, 2026
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
October 8, 2026 05:26
d40e149 to
4abf439
Compare
mingfeima
requested changes
Oct 8, 2026
Collaborator
|
also please rebase to master. |
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
3 times, most recently
from
October 8, 2026 17:01
432f7d6 to
0a0c1fa
Compare
mingfeima
approved these changes
Oct 9, 2026
mingfeima
requested changes
Oct 9, 2026
siju-samuel
approved these changes
Oct 9, 2026
Enable --dcp-size > 1 on Intel XPU with the intel_xpu attention backend. KV is sharded by token position: the owner of a position (pos % dcp_size) stores it at slot loc // dcp_size, every rank attends over its own shard, and the partial outputs are merged by log-sum-exp. The DCP path runs only XPU-native kernels (sgl-kernel-xpu and torch ops): * Write: rows another rank owns get index -1, which store_cache_xpu skips, so each layer writes through the native store with no owner mask. The slots are built once per batch from the padded positions. * Decode: all-gather the query heads across the DCP group and attend over this rank's shard through a per-rank page table. The partials are exchanged with one all_to_all_single and merged with sgl-kernel-xpu merge_state_v2, the new XPU default for --dcp-comm-backend; ag_rs stays selectable. Rows a rank holds no keys for are zeroed first, because the FMHA returns NaN there. * Extend: the sharded prefix runs non-causal over the gathered queries and is merged with cp_lse_ag_out_rs_mha; the new tokens run causal off k/v, and merge_state_v2 combines the two. sgl-kernel-xpu's varlen prefill hangs at seqlen_q == 1, so a 1-token chunk uses the closed form (output v, LSE the single score). The rest of the change enables the shared DCP plumbing on XPU: parallel_state admits XPU, and the allocator uses the physical page size. attention_hook refuses what DCP on XPU cannot run, at startup: a backend other than intel_xpu, MLA models, unequal K and V head dims, dcp_size not dividing tp_size, models whose ranks would not share a DCP group's KV heads (all but Qwen3.5 when total_num_kv_heads > tp / dcp), a decode GQA group above the 16 the XPU kernel is built for, speculative decoding, chunked local attention and encoder-decoder models. xpu_backend refuses what only the loaded model settles: sliding-window layers, a quantized KV cache (including one auto resolves to fp8) and captured graphs. Docs: the XPU page documents DCP, and the --dcp-comm-backend help and the DCP docs list the a2a default on XPU. Tests: test_xpu_dcp.py checks the DCP decode (under both merges) and extend paths, including the KV write through a real pool, across threaded ranks against full attention on one XPU, plus the startup checks. test_xpu_dcp_gsm8k.py gates GSM8K on Qwen3.5-4B at TP=2/DCP=2 on two XPUs. test_server_args pins is_xpu in its platform-faked comm-backend tests and adds the XPU default; test_encoder_decoder_varlen_gather sets dcp_size on its stubbed backend. test_xpu_int4_dense: since sgl-project#42588 the GPTQ XPU kernel reads tp_size from the layer's tp_group rather than get_parallel(), so the split-group test sets tp_group on its layer to get the --tp-size hint. This unblocks XPU CI. Co-authored-by: Siju Samuel <siju.samuel@intel.com>
mingfeima
approved these changes
Oct 9, 2026
AnuSajikumar6264
force-pushed
the
xpu-dcp-support
branch
from
October 9, 2026 05:21
ac093e5 to
2a5d3eb
Compare
siju-samuel
approved these changes
Oct 9, 2026
Contributor
|
@AnuSajikumar6264 |
Liwansi
added a commit
to Liwansi/sglang_vans
that referenced
this pull request
Oct 13, 2026
…n_allgather * 'main' of https://github.com/sgl-project/sglang: (236 commits) [NPU] Stabilize HiCache and registered CI tests (sgl-project#43308) [Docs] Cookbook: refresh SemiAnalysis AgentX launches (GLM-5.2 B300, DeepSeek-V4.1 GB300) (sgl-project#43799) [Docs] Update GLM-5.3-Flash playground: B300 default, CP8, EP and PD (sgl-project#43802) [DSV4.1][PD][1/N] Support prefill node use cp parallel strategy (sgl-project#40323) [BCG][DSV4-Flash][CP] Support DeepSeek V4 prefill with interleave CP and breakable CUDA graphs (sgl-project#38603) [XPU] Support decode context parallelism (DCP) on Intel XPU (sgl-project#34355) Keep NIXL Mamba checkpoint keys separate by TP rank (sgl-project#43594) Capture KV host transfer buffers (sgl-project#43711) [CI] Move tests that do not need GB300 off the per-PR GB300 suite (sgl-project#43784) [HiCache] Preserve all MTP KV and recurrent state (sgl-project#40223) [HiCache] Support Mamba in buffer-only host memory mode (sgl-project#36345) [PD] Poison the deferred abort ack when a Mooncake send fails (sgl-project#43719) [Perf] Route BF16 mixed-batch decode tails through decode attention (sgl-project#43238) [Fix] Link cuda_ipc JIT against CUDA driver stubs dir (sgl-project#43764) docs: clarify prefill CP terminology and simplify wording (sgl-project#43787) [diffusion][xpu] FLUX.2: enable the bit-exact Triton SwiGLU on XPU (sgl-project#41940) [Fix] Adapt to transformers 5.18 / 5.19 changes (sgl-project#43688) [XPU CI] Optimize PR CI per-file timeouts and fail hanging tests fast (sgl-project#42048) [Deps] Bump FlashInfer to 0.7.1 (sgl-project#43494) docs: sync LMSYS SGLang blog cards (sgl-project#43462) ...
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
Enable
--dcp-size > 1(decode context parallelism) on Intel XPU in theintel_xpuattention backend, as requested in review. DCP shards the KV cache across the ranks of a TP group by token position, and merges each rank's partial attention output by log-sum-exp. It grows the servable context whentp_sizeexceeds the model's KV heads, which TP would otherwise replicate.Modifications
DCP lives in
xpu_backend.pyand uses only XPU-native kernels (sgl-kernel-xpu and torch ops). There is no Triton on the DCP path.pos % dcp_size) stores it atloc // dcp_size. Rows other ranks own get index -1, whichstore_cache_xpuskips, so every layer uses the native store. The slots are built once per batch.flash_attn_with_kvcache(return_softmax_lse=True)) over this rank's shard. Merge with oneall_to_all_singleplus sgl-kernel-xpumerge_state_v2. This is the new XPU default,--dcp-comm-backend a2a;ag_rs(cp_lse_ag_out_rs_mha) stays selectable.flash_attn_varlen_func). The sharded prefix runs over the gathered Q and is merged withcp_lse_ag_out_rs_mha.merge_state_v2combines the two.req_to_token, one gather and one divide.Sharding and merge follow the shared DCP path the Triton backend runs on CUDA/ROCm, and a2a stays decode-only, as upstream's is.
Two XPU-specific details:
seqlen_q == 1, so a 1-token chunk uses the closed form (outputv, LSE the single score).Shared plumbing, all XPU-gated:
parallel_stateadmits XPU._alloc_page_sizeuses the physical allocator page._dcp_comm_backend_defaultresolvesa2aon XPU; the help text and DCP docs are updated to match.Startup checks (XPU only)
attention_hook._check_xpu_dcprefuses each of these at startup, naming the flag to change:intel_xpu;--dcp-sizenot dividing--tp-size;total_num_kv_heads > tp / dcp);xpu_backendrefuses what only the loaded model settles: sliding-window layers, a quantized KV cache, and captured graphs.No code path off XPU changes.
Changes since the previous revision
These address the review by @mingfeima:
store_cache_xpuskips, instead of slot 0, which a live token can map to. The parity test now places live tokens at local slot 0: the old code fails 10 of its subtests, the fix passes.--kv-cache-dtype bf16is accepted, and an fp8 cache (explicit, or an fp8 checkpoint underauto) is still refused.replicatedis nowkv_head_layout_supported.Earlier, from the review by @rahulvijayaraghavan:
merge_state_v2, 2.3-5.4x faster than the torch merge. The fp32 casts now happen only where the merge needs them.forward_batch_info.py: no longer changed.Rebased onto main
8ad24fb560.Accuracy Tests
Setup: Qwen3.5-4B, 2x Arc Pro B60, TP=2,
intel_xpu, sglang-kernel-xpu 0.3.0,--disable-radix-cache --chunked-prefill-size 256.GSM8K, all 1319 questions, 5-shot, same workload:
Greedy parity vs dcp=1 (12 requests, 64 new tokens each). The mean logprob gap over the agreeing tokens is 0.0028 with a2a and 0.0025 with ag_rs, vs 0.0027 before. Every divergence is a near-tie between two tokens, e.g. 0.29 vs 0.30.
Speed Tests and Profiling
Decode tok/s for Qwen3.5-4B, TP=2, 4096-token prompts, 64 new tokens; median of 5 interleaved runs:
Prefill is 0.2-0.8% faster. DCP trades decode speed for context. Qwen3.5-4B has 4 KV heads, so TP=2 does not replicate them: at dcp=2 each rank holds all 4 heads for half the positions, and the per-rank KV pool goes from 340,864 to 170,112 tokens. The total context is unchanged, so this model checks correctness, not the context gain. The gain shows when heads are replicated: GLM-4.1V-9B (2 KV heads) at TP=4 kept the same per-rank capacity at dcp=2, which doubles the servable context (measured on an earlier revision).
Tests
test/registered/xpu/test_xpu_dcp.py(1 XPU,stage-b-test-1-gpu-xpu). It runs decode (under ag_rs and a2a) and extend on threaded ranks against full attention at dcp 2 and 4, including ranks that hold no keys. The new tokens are written through the backend into a realMHATokenToKVPool, so a wrong KV slot shows up as wrong attention output. The file also covers the startup checks.test/registered/xpu/test_xpu_dcp_gsm8k.py(2 XPUs,nightly-xpu-2-gpu): a GSM8K gate at 0.80 on Qwen3.5-4B, TP=2/DCP=2. Local run: 0.885, passed.test_server_argsgains an XPU comm-backend default case, and its platform-faked cases now pinis_xpu.test_encoder_decoder_varlen_gathersetsdcp_sizeon its stubbed backend.test_xpu_int4_densesetstp_groupon its layer. Since [Refactor] Retain process groups in parallel linear layers #42588 the GPTQ XPU kernel reads tp_size from it, so the split-group test was failing XPU CI on main.How to test
Or by hand, launching once with
--dcp-size 1and once with--dcp-size 2:Not covered here
all_to_all_singlecan't be captured on XPU (all_gatherandall_reducecan). Planned as a follow-up.--disable-radix-cache, independently of DCP.Checklist
CI States
Latest PR Test (Base): 🚫 Run #38197433978
Latest PR Test (Extra): ❌ Run #38197433448
Latest PR Test (AMD ROCm 10): ❌ Run #38197433838