Fix: add missing end_sync barrier in fused allreduce+rmsnorm kernel - #4346
Merged
Conversation
Contributor
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
|
yuzho-amd
marked this pull request as ready for review
July 24, 2026 09:33
Contributor
There was a problem hiding this comment.
Pull request overview
Adds the missing final cross-rank synchronization (end_sync) to the 1-stage fused allreduce+RMSNorm kernels so a rank cannot start the next fused collective (and reuse the registered buffers/signal slots) before all peers have finished the prior invocation, preventing silent cross-request corruption under certain concurrency patterns.
Changes:
- Add
end_sync<ngpus, true>(...)at kernel exit for the 1-stage fused allreduce+rmsnorm kernel. - Add
end_sync<ngpus, true>(...)at kernel exit for the per-group quant 1-stage variant. - Add
end_sync<ngpus, true>(...)at kernel exit for the MXFP4 1-stage variant (and document the rationale in-code).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
zufayu
self-requested a review
July 27, 2026 01:24
zufayu
approved these changes
Jul 28, 2026
1 task
curvedinf
added a commit
to curvedinf/int8-aiter
that referenced
this pull request
Aug 24, 2026
…al hardening Root cause (decoded from per-rank output composition across the stress matrix): the eager input pool lived in CACHED device memory. Peer GPUs' L2 lines for the pool addresses go stale between back-to-back custom-AR calls of different sizes, so a peer's kernel read its own CURRENT input but PREVIOUS-call inputs for the other ranks (deterministic own-A + peers-B sums). Single-size sequences stayed coherent; mixed-size eager sequences (the serving pattern: decode AR + prefill AR) corrupted. Flags, ordering, cookies and copy paths were all exonerated by bit- identical failures across those variants. Fix: allocate the eager input pool with hipDeviceMallocUncached (AITER_CAR_UNCACHED_POOL=0 re-enables cached for benchmarking). Hardening kept from the hunt (all verified clean together): - 2stage/2stage_naive/write_mode: trailing end_sync (the ROCm#4346 refill class) so a fast rank cannot restart its tmp region under a peer - start/end syncs accept a per-launch sequence cookie with EXACT-match waits; plain kernels carry it as a kernel arg (fused paths take the legacy counter path until threaded) - start-flag store promoted to RELEASE, wait to ACQUIRE - pool copy routed through a compute-queue kernel (car_pool_copy) so back-to-back calls serialize on one queue Verification (test_car_stress_mixed.py, ws4): mixed-size eager loop (32/64/8/1/128 rows x 5120) 100 iters CLEAN per-iteration; single-shape 50 iters CLEAN; pair isolation CLEAN. Co-authored-by: Kimi Code <kimi@moonshot.ai>
curvedinf
added a commit
to curvedinf/int8-aiter
that referenced
this pull request
Aug 24, 2026
… as the remaining corruptor
Bisect matrix in serving (coherence gate each):
- eager + AITER_CUSTOM (CGMODE=NONE, SPEC=0): COHERENT ('Paris')
- graphs + AITER_CUSTOM: salad from decode token 2 onward (first token
always correct -> prefill/eager AR fine, graph-replay AR corrupts)
- fusion on/off, spec on/off, cookie on/off, cached/uncached pool,
naive/new kernels: graph-path salad invariant
Kernel-side state after this session (all committed together):
- naive kernels forced unconditionally (use_new=false): the smem
double-buffered kernels corrupt under capture AND post-capture eager
- uncached eager input pool (default on): fixes mixed-size eager races
(peer-L2 staleness; verified by per-rank output composition decode)
- trailing end_sync on 2stage/naive/write_mode (ROCm#4346 refill class)
- release/acquire start-flag protocol
- cookie exact-match waits plumumbed but DISABLED (seq=0): graph
captures bake the cookie at capture time, replays carry stale values
- host-side meta writes removed from next_launch_cookie (segfaulted
serving; cookie now travels only as kernel arg)
- car_pool_copy kernel reverted to hipMemcpyAsync (segfaulted the
serving profile pass)
Stress harness (test_car_stress_mixed.py): 30-iter mixed-size eager
CLEAN on this build. Serving eager CAR coherent. Graph-path fix is the
remaining work item; until then graphs+CAR must not be combined.
Bench (TP4 C8, eager, CGMODE=NONE): SS 6.74 tok/s, C8 peak 56, TPOT
131ms — eager CAR is SLOWER than RCCL at these shapes; the CAR win
requires the graph path fixed or decode-sized AR re-tuning.
Co-authored-by: Kimi Code <kimi@moonshot.ai>
Richardyu114
added a commit
to sammysun0711/aiter
that referenced
this pull request
Aug 26, 2026
…turn Backport of ROCm#4346 Signed-off-by: Richardyu114 <zhentyu@amd.com>
sammysun0711
pushed a commit
to sammysun0711/aiter
that referenced
this pull request
Aug 26, 2026
…sed AR+RMSNorm (#9) * fix: synchronize custom collectives before return (ROCm#4082) Co-authored-by: ColorsWind <14761584+ColorsWind@users.noreply.github.com> Signed-off-by: Richardyu114 <zhentyu@amd.com> * fix(custom_all_reduce): synchronize fused allreduce rmsnorm before return Backport of ROCm#4346 Signed-off-by: Richardyu114 <zhentyu@amd.com> --------- Signed-off-by: Richardyu114 <zhentyu@amd.com> Co-authored-by: Yingyi Hao <42579422+jpy794@users.noreply.github.com> Co-authored-by: ColorsWind <14761584+ColorsWind@users.noreply.github.com>
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
Issue:
in sglang with fused allreduce+rmsnorm, it would have acc issue in lower concurrency(16), and the root cause is missing end_sync in all reduce fusion kernel.
How to reproduce:
image: lmsysorg/sglang-rocm:v0.5.15-rocm720-mi35x-20260713
model: amd/Qwen3.5-397B-A17B-MXFP4
start sglang server with:
CUDA_VISIBLE_DEVICES=0,1 \ SGLANG_USE_AITER=1 \ SGLANG_USE_AITER_UNIFIED_ATTN=1 \ AITER_FLYDSL_FORCE=1 \ SGLANG_MAMBA_SSM_DTYPE=bfloat16 \ SGLANG_USE_AITER_FP8_PER_TOKEN=1 \ python3 -m sglang.launch_server \ --model-path /data/amd/Qwen3.5-397B-A17B-MXFP4 \ --trust-remote-code \ --host 0.0.0.0 \ --port 6666 \ --tensor-parallel-size 2 \ --attention-backend aiter \ --mem-fraction-static 0.8 \ --model-loader-extra-config '{"enable_multithread_load": true}' \ --watchdog-timeout 7200 \ --disable-radix-cache \ --enable-aiter-allreduce-fusion \ --max-running-requests 16 \ --page-size 16send prompt with:
'python3 /home/yuzho/inferencex_perf/run_refill_sequence_check.py
--base-url http://127.0.0.1:6666
--model /data/amd/Qwen3.5-397B-A17B-MXFP4
--concurrency 16
--num-requests 160
--timeout 7200
--output /tmp/bf16_conc16_refill.json'
the content of 'run_refill_sequence_check.py' is:
`#!/usr/bin/env python3
import argparse
import asyncio
import json
import re
import time
from collections import Counter
from pathlib import Path
import aiohttp
EXPECTED = list(range(1, 101))
REPEATED_SYMBOL = re.compile(r"([^\w\s,,。;;::\-])\1{5,}")
def classify(text, finish_reason):
numbers = [int(value) for value in re.findall(r"\d+", text)]
errors = []
if not text.strip():
errors.append("empty")
if "\ufffd" in text:
errors.append("replacement_character")
if REPEATED_SYMBOL.search(text):
errors.append("repeated_symbols")
if numbers[:100] != EXPECTED:
errors.append(f"sequence_mismatch_{len(numbers)}")
if finish_reason not in ("stop", "length"):
errors.append(f"finish_reason_{finish_reason}")
return errors, numbers
async def main():
parser = argparse.ArgumentParser()
parser.add_argument("--base-url", default="http://127.0.0.1:6666")
parser.add_argument("--model", required=True)
parser.add_argument("--concurrency", type=int, required=True)
parser.add_argument("--num-requests", type=int, required=True)
parser.add_argument("--timeout", type=float, default=7200)
parser.add_argument("--output", required=True)
args = parser.parse_args()
if name == "main":
asyncio.run(main())
`
Technical Details
Test Plan
Test Result
Submission Checklist