sglang DSA: enable PD + DP-attention + EAGLE MTP on GLM-5.2 / gfx950 (3 patches, rebased onto main) - #58
Merged
Conversation
dorado269
requested review from
JohnQinAMD,
jiejingzhangamd,
limou102 and
xiaobochen-amd
as code owners
July 31, 2026 11:00
jiejingzhangamd
approved these changes
Jul 31, 2026
dorado269
force-pushed
the
worktree-dsa-hip-dp-rows-fix.rebase
branch
2 times, most recently
from
August 1, 2026 07:37
94fbe4c to
cfd2d41
Compare
PD disaggregation with DP-attention and EAGLE MTP does not work for GLM-5.2 on
the ROCm sglang base: it crashes on the first batch, then deadlocks the whole DP
group under concurrency. Three patches against the pinned sglang tree fix it,
applied at build time by Dockerfile.sglang (APPLY_SGLANG_DSA_PATCHES=1, set 0
for a stock engine to A/B against).
01 dsa_indexer_hip_dp_padded_rows
The HIP/aiter paged-MQA branch sizes its logits from DP-PADDED rows while
`lengths` is sized to REAL rows -> "Expected lengths.size(0) == B". Slice
to the real count, the contract every CUDA backend already honours, then
restore the padding. ROCm-specific; CUDA was never affected.
02 dsa_backend_dp_sync_and_page_table_rows
(a) `seq_lens.max().item()` is a blocking D2H sync on a branch only SOME
DP ranks take, so the collectives desynchronize and the group deadlocks.
Two further unconditional .cpu() syncs sit on the same branch and are dead
for DRAFT_EXTEND_V2. (b) the page table has one row per REQUEST while
top-k has one per TOKEN under MTP, tripping an assert on every rank.
04 draft_cuda_graph_dp_vote
The draft graph/eager choice is made per rank from rank-dependent inputs
and diverges on the PD decode leg, where the DSA top-k seed arrives by
RDMA. Graph replay and the eager loop do not issue the same collectives.
Make it a group decision by adding one int64 slot to the MLP-sync
all-gather the scheduler already performs, min()-reduced, so no extra
collective is introduced.
Each .diff header is the record: what it fixes, why, how it was established, the
upstream issue / third-party PR / our own PR, how it differs from our own PR,
and whether the IndexShare configuration workaround substitutes for it. Patch 04
records a known gap against upstream #32209 -- we omit its BaseSpecWorker default,
so only the EAGLE worker family is covered. deploy/docker/patch.upstream.status.md
indexes upstream linkage for every patch in the repo, not just these.
The nextn eh_proj fix is NOT here: main's patch loop already applies it, and it
must run first, so apply_sglang_dsa_patches.sh asserts it rather than assuming
it -- that script is idempotent and would otherwise "skip" silently.
Validated on 2 x 8xMI355X (gfx950), ROCm 7.2.0, GLM-5.2-MXFP4, PD over
mooncake/mlx5 + dma-buf, --dp-size 8 --enable-dp-attention --ep-size 8 + EAGLE
MTP(3,1,4) with the draft CUDA graph ENABLED, from an image built by
Dockerfile.sglang with nothing patched in the running container:
build-time bytecode verification, both nodes 8/8 markers + prereq + patch2a
4-prompt correctness probe 4/4, acc_len 2.00-3.43
conc=32 x 512 tok 32/32
conc=128 x 512 tok, twice 128/128, 128/128
Traceback / KVTransferError, either leg 0 / 0
DP ranks serving 8, every run, 0 retries
Cumulative across arms: 2540/2540 with the fixes, 0/4 with patch 04 reverted
(same nodes, same image, deadlock at 120 s on request 1). Draft-graph replay
measured at 97.1% -- that counter is the point, because forcing the draft path
eager passes every functional test while disabling the feature under test.
Limits are recorded in patches/sglang_dsa/README.md. Chiefly: the image built
from this branch after the rebase onto main was not re-run, and main has since
added a libionic layer the measured image did not carry (orthogonal to these
patches -- RDMA ABI matching, not DSA). Performance was not measured against the
DPA-only baseline, and one hardware configuration was exercised.
Signed-off-by: yihou <yihou@amd.com>
dorado269
force-pushed
the
worktree-dsa-hip-dp-rows-fix.rebase
branch
from
August 1, 2026 08:22
79a5259 to
c91db76
Compare
6 tasks
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.
Enables PD disaggregation + DP-attention + EAGLE MTP for GLM-5.2-MXFP4 on gfx950. Without these the combination crashes on the first batch or deadlocks the whole DP group under concurrency.
Supersedes #34, which was branched from
cf85272.mainhas since moved 29 commits ahead and absorbed three of the things that branch carried; this one is rebased onto8692fb4with those dropped. See "Relationship to #34" below.The patches
dsa_indexer_hip_dp_padded_rows.difflengthsis sized to real rows →Expected lengths.size(0) == Bdsa_backend_dp_sync_and_page_table_rows.diffseq_lens.max().item()is a host sync on a branch only some DP ranks take → collectives desynchronize; (b) page table has one row per request, top-k one per token under MTP → assertdraft_cuda_graph_dp_vote.diffApplied at build time by
Dockerfile.sglang, defaulting on (APPLY_SGLANG_DSA_PATCHES=1). Build with=0for a stock engine to A/B.The apply script verifies every patch reached the bytecode, not just the source: a stale
__pycache__entry silently reverts a patch and has already invalidated one full experiment on this stack.Validation
Image built from
Dockerfile.sglangindependently on each of two nodes; nothing patched in the running container. 2 × 8×MI355X (gfx950), GLM-5.2-MXFP4, PD +--dp-size 8 --enable-dp-attention --ep-size 8+ EAGLE MTP with the draft CUDA graph enabled, mooncake RDMA over mlx5 + dma-buf.acc_len> 1Traceback/KVTransferError, either legThe draft CUDA graph was measured in use at 92.0 %, identical on all 8 ranks, on the immediately preceding build of this patch set. That measurement needs an added probe (a different image) so it is not part of the run above — but it is the criterion that matters: forcing the draft path eager passes every functional test while disabling the feature under test, so a green stress result alone cannot distinguish a fix from that workaround. Uniformity across ranks is the property patch 4 exists to produce.
Relationship to #34
#34 carried four patches and two Dockerfiles. Rebasing onto current
mainapplied with zero conflicts, which was misleading — the branch only added files, so git had nothing to compare against changesmainmade to the same problems in different files. Three overlapped:deepseek_nextn_glm52_mtp_bf16.diff—main'spatch_glm52_nextn_quark_exclude.py(0d8d0ff) makes the identical edit: same file, same line, same resulting value. Keeping both would have been actively broken, not merely redundant:main's loop runs first, so our context diff would then fail at--fuzz=0against an already-edited anchor. Dropped;apply_sglang_dsa_patches.shnow asserts it as a prerequisite, because that script is idempotent and a silent skip would surface only at runtime as GLM-5.2 dying at draft weight-load.build_mooncake_dmabuf.sh—main'sbuild_mooncake_sglang.shis a strict superset (same logic line for line, plus a HIP-transport gate check and build-tree cleanup). Dropped.Dockerfile.sglang.dmabuf—main'sDockerfile.sglangnow compiles the dma-buf branch in and selects it at runtime viaMOONCAKE_DISABLE_HIP_DMABUF, which is exactly how these runs drove it (=0). Dropped; the DSA layer moved intoDockerfile.sglang.Net: 8 files / 1181 lines → 6 files / 1048 lines, one modified file instead of two new Dockerfiles and a duplicated build script.
There is a configuration-only alternative to part of this set
Turning GLM-5.2 MTP IndexShare off avoids the same deadlock without patch 4 or patch 2's page-table half:
It works because IndexShare is the source of the divergence: the guard term
dsa_topk_indices is Noneis seeded on the PD decode leg from RDMA-shipped per-request payloads, so it is a function of which requests each rank happens to hold.eh_projMeasured with 2b and 4 asserted absent from the bytecode: 4/4, 32/32 ×2, 64/64, accept length 2.98–3.01 (no measurable cost). It needs MTP on the prefill leg too, and that arm ran conc=64, not 128.
Not adopted as the default because it is nearly free only while IndexShare's consumer stays disabled under PD by
should_use_dsa_fused_topk. Upstream #31477 removes that limitation; once it lands the override starts costing (~3 % TPOT, reported by AMD's llying — second-hand, not measured by us). Checked withghon 2026-07-31: open,REVIEW_REQUIRED, unmerged.Each diff header records where it stands relative to this, so the choice is visible at the point of use.
What this does not establish
dsa_backendon.max().item()while idle peers had already advanced into the next collective, and after the fix no rank appears there in a dump again, with PD warmup passing on all 8 ranks. Its second half was forced by experiment — with themax_seqlen_kchange alone, the hang persists. A revert control would still be a cheap addition.--disable-custom-all-reduce(required — the aiter custom all-reduce kernel deadlocks on gfx942/gfx950 during EAGLE verify), MTP on the decode leg only. With prefill MTP off, the rank-split case patch 4 is designed for has not been exercised.Base image pinning
The base tag stays pinned. These are context diffs applied at
--fuzz=0against sglang0b3bb0cbe31873994c9f989fddfe2f87ca839fdd; a base bump fails the build at the patch step rather than mis-applying silently. That is intended behaviour. Build withAPPLY_SGLANG_DSA_PATCHES=0if you need a newer base.Reproduction kits (raw per-request jsonl, both server logs, the build log, and cold-start instructions) live in the
infera.yihou.glm5.2.mxfp4workspace; the one for this run isglm52.mxfp4.spur.mooncake.packup_20260731_main_converged.🤖 Generated with Claude Code