Repository navigation
[AMD] Feat/dsv4 aiter reduce scatter decode - #29103
Conversation
…local, gatherv copy elim) DSV4 (HIP/MI300) prefill + dp-attention optimizations, validated on c512: - deepseek_v4: default-on CK w8a8-block GEMM (MLA proj) + batched/flat RoPE on HIP (set_force_ck_w8a8 / set_batched_rope in __init__; env overrides still work). - deepseek_v4_rope: flat-row attention-output RoPE kernel (row = token*n_heads+head, consecutive rows head_dim apart) -> ~2x cold HBM BW; production rope 168us -> 59us . Replaces the per-head contig kernel. - deepseek_v2/deepseek_v4: shared-expert-local computation (env-gated SGLANG_DP_SHARED_EXPERT_LOCAL, needs SGLANG_SHARED_EXPERT_TP1). Compute the replicated shared expert on LOCAL hidden (prefill AND decode) instead of the gathered global buffer -> 1/dp_size the rows; cancels the TP1 decode penalty. - parallel_state/dp_attention: all_gatherv `output=` buffer so NCCL gathers directly into the dp buffer; removes 2 full-buffer (~940MB) DtoD copies in the MoE-gather path (~700us/layer at c512). Validation (latest main + all opts, c512, 3 runs each): gsm8k 0.9568/0.9575; 1k/1k 18,088 tok/s (+-0.25%), 8k/1k 37,281 tok/s (+-0.16%) -- no regression.
…bine In the DP-attention TP-MoE decode path (MAX_LEN padding, no EP, tp==dp), the MoE combine previously did the MoE-internal post-experts all_reduce (aiter cross_device_reduce_2stage) + dp_scatter. Replace it with an equal-chunk reduce_scatter, which moves ~half the bytes, using aiter's custom (symmetric-memory) kernel so both halves of the gather/combine are aiter custom kernels (allgather_vec + reduce_scatter_first_dim) instead of falling back to RCCL. - parallel_state.py: GroupCoordinator.reduce_scatter_tensor tries an aiter custom reduce_scatter first (equal-chunk, size-bounded via should_custom_ar, cuda-graph capture aware), else RCCL. Env-gated by SGLANG_USE_AITER_RS. - deepseek_v4.py: in the MAX_LEN decode combine, skip the MoE-internal all_reduce (use_reduce_scatter=True) and call reduce_scatter_tensor directly. Env-gated (SGLANG_USE_AITER_RS), default OFF. gsm8k 5-shot flexible 0.9507 / strict 0.9515 (matches baseline). c512: 1k/1k +3.07%, 8k/1k +0.72% total tok/s; decode TPOT -4 to -6%.
Promote the aiter custom reduce_scatter toggle from a raw get_bool_env_var read to a registered EnvBool (SGLANG_USE_AITER_RS, default True) and use envs.SGLANG_USE_AITER_RS.get() at both call sites (parallel_state, deepseek_v4). The DSV4 gate still requires MAX_LEN decode + tp==dp + no EP + gatherv inactive, and the collective falls back to RCCL when the shape/size is unsupported, so default-on only activates the aiter equal-chunk reduce_scatter on the validated decode path.
… gate gatherv on SUM_LEN Follow-up to the aiter reduce_scatter decode-combine work: - environ.py: rename SGLANG_USE_AITER_RS -> SGLANG_DP_USE_REDUCE_SCATTER (platform-agnostic: aiter custom kernel on ROCm, RCCL elsewhere). Default is now platform-conditional via a lazy callable default (_default_hip): ON for HIP, OFF otherwise; EnvField.get() gains callable-default support (backward compatible). - dp_attention.py: is_dp_gatherv_active() now also requires SUM_LEN padding (not _DpGatheredBufferWrapper.is_dp_max_padding()). The gatherv pair (all_gatherv + reduce_scatterv) is only valid under SUM_LEN; this makes callers without a ForwardBatch (dp_reduce_scatter_tensor) consistent and lets the MAX_LEN decode combine route to the equal-chunk reduce_scatter. - deepseek_v4.py: rename _use_gatherv_pair -> _use_reduce_scatterv and _use_aiter_rs -> _use_reduce_scatter; the MAX_LEN decode combine now calls dp_reduce_scatter_tensor (routes to the equal-chunk reduce_scatter / aiter, since gatherv is inactive under MAX_LEN). - parallel_state.py: reduce_scatter_tensor aiter path gated by the renamed env. Validated: gsm8k 5-shot flexible 0.9545 / strict 0.9553. No perf regression at c512 (8k/1k 37,701 vs baseline 37,171; 1k/1k 18,666 vs 18,026 tok/s).
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
/tag-and-rerun-ci |
|
@amd-bot ci-status |
CI Status for PR #29103Merge verdict: Caution This PR's changed code is not exercised by any PR-CI test. The new
The Changed files: Executed CI failure attribution: AMD: 1 failure (0 related) · Others: 3 failures (0 related) · plus AMD pipeline incomplete (stage-c not reached). Aggregator/ AMD Executed Failures
Other Executed Failures
Details / what to do before merge
Generated by amd-bot using Claude Code CLI |
|
@kkHuang-amd please add follow-up PR for test cases. |
Co-authored-by: wunhuang <wunhuang@amd.com>
Use AITER for eligible reduce-scatter calls with ROCm defaults. Support unregistered capture inputs for memory-saver and an opt-in AG/RS copy-in path, retaining existing collective fallbacks. Adapt the backport to keep RS inside the registered collective boundary and check per-rank alignment, output shape/dtype/device and deterministic policy. Add CPU dispatch tests and a four-GPU collective smoke test. Only the collective portions are included; gfx950 EP decode kernels and pre-dispatch token hints are not part of this change. Adapted-from: sgl-project#29103 Adapted-from: sgl-project#34203 Adapted-from: sgl-project#43077 Signed-off-by: Richardyu114 <zhentyu@amd.com>
Use AITER for eligible reduce-scatter calls with ROCm defaults. Support unregistered capture inputs for memory-saver and an opt-in AG/RS copy-in path, retaining existing collective fallbacks. Adapt the backport to keep RS inside the registered collective boundary and check per-rank alignment, output shape/dtype/device and deterministic policy. Add CPU dispatch tests and a four-GPU collective smoke test. Only the collective portions are included; gfx950 EP decode kernels and pre-dispatch token hints are not part of this change. Adapted-from: sgl-project#29103 Adapted-from: sgl-project#34203 Adapted-from: sgl-project#43077 Signed-off-by: Richardyu114 <zhentyu@amd.com>
…00X (#39) * fix(rocm): always mask padded MoE expert IDs Mask padded top-k IDs to a valid expert even when EPLB is disabled, while retaining zero routing weights for padded rows. Add a regression for invalid padded IDs without an expert-location remap. Adapted-from: sgl-project#28378 Upstream-commit: 6309fb9 Signed-off-by: Richardyu114 <zhentyu@amd.com> * perf(moriep): skip unused expert counts in captured graphs Do not capture LocalExpertCount for the no-op recorder. Keep the count kernel for configured recorders so recording can start after capture. Cover inactive, active and capture-time recording policies. Adapted-from: sgl-project#30302 Upstream-commit: 9ddea8d Signed-off-by: Richardyu114 <zhentyu@amd.com> * feat(mimo): route MiMo MoE through MORI expert parallelism Recognize MORI in the MiMo A2A initialization and forward-path gates. Use the existing dispatcher-based forward with padded-token metadata and avoid the tensor-parallel post-expert reduction path. Add a regression for MORI forward-path selection. Signed-off-by: Richardyu114 <zhentyu@amd.com> * fix(distributed): enable custom collectives for attention TP groups Let attention TP groups inherit custom-allreduce and MSCCL++ policies and participate in graph capture. Deduplicate aliased groups and retain the existing PyNccl selection. Test policy inheritance and capture scope. Selectively adapt the attention-group changes from the upstream PRs. Adapted-from: sgl-project#31629 Adapted-from: sgl-project#35330 Signed-off-by: Richardyu114 <zhentyu@amd.com> * perf(rocm): backport AITER reduce-scatter and capture handling Use AITER for eligible reduce-scatter calls with ROCm defaults. Support unregistered capture inputs for memory-saver and an opt-in AG/RS copy-in path, retaining existing collective fallbacks. Adapt the backport to keep RS inside the registered collective boundary and check per-rank alignment, output shape/dtype/device and deterministic policy. Add CPU dispatch tests and a four-GPU collective smoke test. Only the collective portions are included; gfx950 EP decode kernels and pre-dispatch token hints are not part of this change. Adapted-from: sgl-project#29103 Adapted-from: sgl-project#34203 Adapted-from: sgl-project#43077 Signed-off-by: Richardyu114 <zhentyu@amd.com> * fix(bench): wait for idle before flushing the server cache Backport the post-warmup cache-flush race fix. Add --flush-cache-timeout with a 60-second default for SGLang and retain backend-specific endpoints. Raise on HTTP failure before issuing measured requests. Cover deferred flush completion, CLI validation and benchmark abort on flush failure. Adapted-from: sgl-project#33663 Upstream-commit: 8a1637a Signed-off-by: Richardyu114 <zhentyu@amd.com> * eval(mimo): prepare the Flash DP2 attention-TP4 EP8 launcher Configure global TP8/EP8 with DP2, MORI normal mode, dense TP1 and a DP LM head. Size and validate dispatch capacity for prefill and DFlash blocks. Default PERFORMANCE_MODE=1 to fake routing plus PD prefill; setting it to 0 selects real routing and ordinary serving. Keep TBO and fused QKV quantization disabled and leave collective workaround flags unset. The launcher prepares the target topology; DFlash DP-attention support is still pending and the existing admission guard is unchanged. Signed-off-by: Richardyu114 <zhentyu@amd.com> * eval(mimo) refine dp2_attn-tp4_ep8 prefill server secript Signed-off-by: Richardyu114 <zhentyu@amd.com> * perf(mimo): enable tuned MORI EP8 launch configs by default Add gfx942 tuning rules for FP8 dispatch and BF16 combine at 2048, 4096, and 8192 tokens per rank. Default the MiMo-V2.6-Flash DP2/attention-TP4/EP8 launcher to AUTO mode with the bundled JSON, while preserving environment overrides. Validate config readability and log the active config path. (cherry picked from commit 1c6b707) Signed-off-by: Richardyu114 <zhentyu@amd.com> * perf(mimo): pack FP8 QKV activations and scales into one all-gather Write fused QKV quantization outputs into a shared FP32 bit-view buffer and reuse the existing AITER/RCCL collective path. Keep activations as row-strided views and transpose scales once for CK/CKTile GEMMs. Enable the path through SGLANG_MIMO_FUSED_RMS_QKV_QUANT and default it on in the EP8 launcher. Add layout and 8-GPU graph replay tests. Validate DFlash GSM8K accuracy and improve input throughput by 4.86% at global chunk 32K, input 64K, and concurrency 16 on MI300X. Signed-off-by: Richardyu114 <zhentyu@amd.com> * feat(eval): enable prefill delayer in MiMo Flash DP2 launcher - Enable coordinated prefill admission by default with a configurable maximum of 100 scheduler passes and an opt-out switch. - Validate prefill delayer settings and log the resolved configuration. - Expose stable router-weight fusion as an environment override, disabled by default. Signed-off-by: Richardyu114 <zhentyu@amd.com> * Negotiate PrefillDelayer only after KV-budget admission checks (sgl-project#31835) Signed-off-by: Richardyu114 <zhentyu@amd.com> * [Bugfix] Fix prefill suspension caused by delayed negotiate_should_allow_prefill invocation (sgl-project#32389) Signed-off-by: Richardyu114 <zhentyu@amd.com> * fix(ci): run MiMo EP regression tests through pytest Add executable pytest entry points for the packed FP8 and MORI tests. Replace the partial parallel-state runner so direct CI invocation executes all cases and propagates failures. Signed-off-by: Richardyu114 <zhentyu@amd.com> --------- Signed-off-by: Richardyu114 <zhentyu@amd.com> Co-authored-by: Hanming Lu <69857889+hanming-lu@users.noreply.github.com> Co-authored-by: silencejade <222910030+silencejade@users.noreply.github.com>
Motivation
In the DeepSeek-V4 DP-attention TP-MoE decode path (MAX_LEN padding, no EP,
tp_size == attn_dp_size), the MoE combine previously did the MoE-internalpost-experts all_reduce (aiter
cross_device_reduce_2stage) followed bydp_scatter. An all_reduce moves ~2× the bytes of a reduce_scatter.This PR replaces that with an equal-chunk reduce_scatter for the MAX_LEN
decode combine, using aiter's custom (symmetric-memory) kernel on ROCm, so both
halves of the DP-MoE gather/combine are aiter custom kernels
(
allgather_vecfor the gather +reduce_scatter_first_dimfor the combine)instead of falling back to a generic RCCL collective.
This is the decode-side complement to the already-shipped SUM_LEN gatherv pair
(
all_gatherv+reduce_scatterv,SGLANG_DP_USE_GATHERV), which only appliesto prefill — decode under
SGLANG_USE_ROCM700A=0is MAX_LEN, where gatherv isinactive. Together: prefill uses
reduce_scatterv(SUM_LEN), decode uses theequal-chunk
reduce_scatter(MAX_LEN), so neither phase pays the full all_reducetraffic.
Modifications
environ.py: addSGLANG_DP_USE_REDUCE_SCATTER. Platform-agnostic(aiter custom kernel on ROCm, RCCL elsewhere) with a platform-conditional
default: ON for HIP, OFF otherwise — implemented via a lazy callable default
(
_default_hip, no torch import at module load) plus generic callable-defaultsupport in
EnvField.get()(backward compatible: non-callable defaultsunchanged).
distributed/parallel_state.py:GroupCoordinator.reduce_scatter_tensornow tries an aiter custom reduce_scatter first (equal-chunk, size-bounded via
should_custom_ar, CUDA-graph capture aware), else falls back to RCCL. Gated bySGLANG_DP_USE_REDUCE_SCATTER. Mirrors the existing_all_gather_into_tensorcustom all-gather path.
layers/dp_attention.py:is_dp_gatherv_active()now also requires SUM_LENpadding (
not _DpGatheredBufferWrapper.is_dp_max_padding()). The gatherv pair isonly valid under SUM_LEN; this keeps callers without a
ForwardBatch(e.g.dp_reduce_scatter_tensor) consistent and lets the MAX_LEN decode combine routeto the equal-chunk reduce_scatter.
models/deepseek_v4.py: in the MAX_LEN decode combine, skip theMoE-internal post-experts all_reduce (
use_reduce_scatter=True) and calldp_reduce_scatter_tensor(routes to the equal-chunk reduce_scatter / aiter,since gatherv is inactive under MAX_LEN). Renamed locals for clarity
(
_use_gatherv_pair→_use_reduce_scatterv,_use_aiter_rs→_use_reduce_scatter).Gated, falls back to RCCL when the shape/size/topology is unsupported, and only
activates on the validated path (MAX_LEN decode, no EP,
tp == dp).Test commands
Server (HIP/MI300, tp8 + dp8 dp-attention;
SGLANG_DP_USE_REDUCE_SCATTERdefaults ON on ROCm):
A/B: feature ON is the default on ROCm; force OFF with
SGLANG_DP_USE_REDUCE_SCATTER=0(decode combine reverts to all_reduce + dp_scatter).Accuracy (gsm8k 5-shot, via lm-eval):
Speed (c512, 8k/1k and 1k/1k):
Accuracy Tests
gsm8k 5-shot (DeepSeek-V4-Pro, tp8 + dp8 dp-attention, feature ON):
Matches the baseline (~0.95); no correctness regression.
Cross-platform validation — NVIDIA B200 (CUDA / NCCL path)
SGLANG_DP_USE_REDUCE_SCATTERis platform-agnostic: on non-HIP it defaults OFFand routes to the generic NCCL
reduce_scatter(not the aiter custom kernel).Validated on 8× NVIDIA B200 that explicitly enabling the feature is
numerically correct (DeepSeek-V4-Pro, tp8 + dp8 dp-attention,
flashinfer_mxfp4MoE, feature ON).
gsm8k 5-shot (lm-eval, feature ON):
Matches the baseline (~0.95); no correctness regression on the CUDA path.
Commands (B200; on CUDA the collectives default OFF, so enable explicitly — A/B by
setting
SGLANG_DP_USE_REDUCE_SCATTER=0):Speed Tests and Profiling
c512,
randomratio 1.0,num-prompts=4096,warmup=1024, tp8 + dp8dp-attention,
SGLANG_USE_ROCM700A=0,SGLANG_DP_USE_GATHERV=1,SGLANG_SHARED_EXPERT_TP1=1,SGLANG_DP_SHARED_EXPERT_LOCAL=1,--chunked-prefill-size 65536. Same-session A/B, reduce_scatter OFF vs ON:Decode TPOT improves (the combine moves ~½ the bytes); the win grows on the more
decode-bound 1k/1k workload, as expected for a decode-combine optimization.
Trace verification (decode, MAX_LEN): the per-layer combine kernel is now
aiter
reduce_scatter_first_dim(×61);cross_device_reduce_2stagedrops to 0;the gather stays aiter
allgather_vec. So both gather and combine are aiter customkernels.
Checklist
CI States
Latest PR Test (Base): ❌ Run #28071472700
Latest PR Test (Extra): ❌ Run #28071472574