[Kernel] Rewrite JIT custom all-reduce (v2) with a decoupled kernel/storage design - #31049
Merged
BBuf merged 5 commits intoJul 17, 2026
Merged
Conversation
DarkSharpness
requested review from
BBuf,
HydraQYH,
celve,
ch-wan,
merrymercy,
yizhang2077 and
yuan-luo
as code owners
July 13, 2026 16:46
Contributor
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
…torage design Storage and compute are now independent pieces: - `Communicator` (C++): a thin pointer holder over Python-owned buffers; no allocation, IPC, or graph bookkeeping in C++ anymore. - Workspaces live in torch symmetric memory (which also provides the multicast address), sliced in Python into push buffers / pull buffer / semaphores; push counters are a local tensor. - One kernel file with three algorithms (1shot_push lamport, 1shot_pull, 2shot_pull) and three pull data sources (eager workspace, CUDA-graph pointer table, multimem multicast) plus a PDL memcpy kernel. An f16x2 multimem.ld_reduce variant is added so fp16 instantiates; multimem asm is preprocessed out below sm90 so sm80 still compiles. - CUDA-graph inputs are exchanged from Python after capture (batched cudaIpc handles via the new IPCManager; VMM-backed pointers keep the fabric/posix-fd path through VmmGraphInputManager) and written into a device-side graph_params pointer table dereferenced at replay time. - Tuned thresholds and block counts (B200/H200, graph vs eager, multicast windows) move to device_communicators/configs/custom_all_reduce_v2.py. - Sizing API: `max_size` (default SGLANG_CUSTOM_ALL_REDUCE_V2_MAX_SIZE_KB, 16 MB) caps the tuned per-direction workspaces; explicit max_pull_size/max_push_size are respected verbatim. - tp_qknorm is ported onto the Communicator push plane; the benchmark gains separate jit-eager / jit-graph providers and allocates its NCCL reference group independently (tests likewise). - test_custom_all_reduce drops from 213s to ~3.4s by replacing triton's numpy-based assert_close with torch.testing.assert_close (on-device).
DarkSharpness
force-pushed
the
jit-custom-all-reduce-decoupled
branch
from
July 13, 2026 16:48
c523c2f to
320af53
Compare
Replace the hand-rolled shape/dtype/device/contiguity checks in the CommunicatorObj constructor with TensorMatcher: shared SymbolicSize and SymbolicDevice bindings enforce cross-rank consistency, and the matcher enforces contiguity and uint8 dtype.
# Conflicts: # test/registered/jit/test_custom_all_reduce.py
…all-reduce
ptxas rejects .f32 ("=f") destination registers for
multimem.ld_reduce.*.v4.f16x2/bf16x2 with "Arguments mismatch": .acc::f32
only raises the accumulation precision, the packed half results still live
in b32 registers. Use uint4 with "=r" constraints for the two half branches.
Caught by base-c-test-8-gpu-h200 (MiniMax-M2.5 e2e, fp16, tp8) — the
test_custom_all_reduce unit test is registered in stage extra-b and its CI
dtype sweep is bf16-only, so neither half variant had been compiled in CI.
Verified locally: the broken constraint reproduces the exact ptxas error at
sm_90 (CUDA 13.2) and the fixed kernel compiles for fp16/bf16/fp32 at world
sizes 2/4/8, with multimem.ld_reduce present in the emitted PTX.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pk3EdEe2mHeP9ZLQF9nio
BBuf
approved these changes
Jul 17, 2026
5 tasks
Chronostasys
pushed a commit
to MindLab-Research/sglang
that referenced
this pull request
Aug 24, 2026
…torage design (sgl-project#31049) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: root <root@GPUC5A6.maas>
36 tasks
jakki-amd
pushed a commit
to jakki-amd/sglang
that referenced
this pull request
Sep 9, 2026
…torage design (sgl-project#31049) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: root <root@GPUC5A6.maas>
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
The JIT custom all-reduce (v2) previously coupled compute and storage in one C++ object:
CustomAllReduceBaseowned acudaMallocarena (signal buffers + graph-param slots + pull/push buffers), shared it via rawcudaIpcMemHandleexchange, and tracked CUDA-graph capture inputs inside C++. Every kernel had to inherit from it, which made the kernels hard to reuse (e.g.tp_qknorm), the storage lifecycle opaque to Python, and graph-input registration split across three layers.This PR rewrites it with a fully decoupled design: storage is owned in Python, kernels are pure functions of
(input, Communicator, algo, pull_arg).Design
Storage plane (Python-owned)
[2 * world_size push buffers | pull buffer | pull semaphores]; push counters are a plain local tensor. Symmetric memory also provides the multicast address of the pull workspace for free.Communicator(C++) is a thin pointer holder: it validates the tensor views and records raw pointers plus grid-size knobs. No allocation, no IPC, no graph bookkeeping.Kernels (one file, three algorithms)
1shot_push: lamport-style push to every peer's push workspace, then a local polling reduce (best at small sizes).1shot_pull/2shot_pull: semaphore-synchronized pull with three data sources: eager workspace, CUDA-graph pointer table, ormultimem.ld_reducemulticast. 2shot fuses reduce-scatter with the broadcast by writing shards back to all peers.f16x2multimem.ld_reducevariant is added so fp16 instantiates in multicast mode; all multimem asm is preprocessed out below sm90, so the module still compiles for sm80 (verified).CUDA-graph inputs
graph_paramspointer table; the captured kernel dereferences its row at replay time.cudaIpchandles via a newIPCManagerfor cudaMalloc-backed pointers, and the existing fabric/posix-fd VMM path (expandable segments) viaVmmGraphInputManager, whose base-range walk moved to Python (compute_graph_capture_bases).Dispatch config
device_communicators/configs/custom_all_reduce_v2.py.2shot_pullnow has a tuned ceiling: above the NCCL crossover,should_custom_arreturns False. Benchmarks/tests that must keep every size on the custom-AR path calluncap_pull_thresholds().CustomAllReduceV2(group, device, max_size=..., *, max_pull_size=None, max_push_size=None, ...). Explicit per-direction sizes are respected verbatim; unset directions takemin(tuned_bytes, max_size).max_sizedefaults toSGLANG_CUSTOM_ALL_REDUCE_V2_MAX_SIZE_KB(16 MB), keeping the previous default memory footprint.Downstream
tp_qknormis ported onto theCommunicatorpush plane (no more base-class inheritance); the MiniMax-M2 call sites are unchanged.CustomAllReduceV2surface (capture(),should_custom_ar,custom_all_reduce,override_algo,close,.obj) is preserved;parallel_state/ the v1 wrapper need no changes. The unusedoverride_shothook is removed.jit-eager/jit-graphproviders, and both the benchmark and the tests now allocate their NCCL reference group independently (dist.new_group) instead of reaching intoparallel_stateinternals.test_custom_all_reducewall time drops from 213 s to ~3.4 s:triton.testing.assert_closecompares via numpy on the host (~0.6 s per 32 MB tensor);torch.testing.assert_closecompares on device (~2 ms) with better mismatch reporting.Performance (B200, bf16, us per all-reduce)
world_size = 8:
world_size = 2: 3.0 us at 4 KB (vs 10.3 nccl / 6.0 v1), 579 GB/s bus bandwidth at 64 MB. The new
jit-eagerline additionally exposes the Python dispatch floor (~36 us) separately from kernel cost.Verification (8x B200)
test_custom_all_reduce.py: 180/180 at world size 2 and 8 (all sizes x fp16/bf16/fp32 x 3 algos x eager/graph, exact-equality against NCCL).test_tp_qknorm.py: 42/42 at world sizes 2/4/8.override_jit_cuda_arch(8, 0)for all dtypes.bench_custom_all_reduce.pyfull sweep at world sizes 2/4/8.CI States
Latest PR Test (Base): 🚫 Run #29559587415
Latest PR Test (Extra): 🚫 Run #29559587350