Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
98ef7f6
CollectiveX: label backend maturity and correct the low-latency docs
Oseltamivir Aug 2, 2026
9423456
CollectiveX: add FlashInfer one-sided NVLink EP for the GB SKUs
Oseltamivir Aug 2, 2026
893e304
CollectiveX: give the FlashInfer communicator the whole CommBackend c…
Oseltamivir Aug 2, 2026
81efeae
CollectiveX: dispatch routing metadata so the FlashInfer oracle views…
Oseltamivir Aug 2, 2026
3ff418a
CollectiveX: complete the FlashInfer oracle view (local masking + exp…
Oseltamivir Aug 2, 2026
2f53134
CollectiveX: shape the FlashInfer combine scatter from the actual rec…
Oseltamivir Aug 2, 2026
4237e23
CollectiveX: model FlashInfer's BF16 combine accumulation instead of …
Oseltamivir Aug 2, 2026
fbadba6
CollectiveX: model FlashInfer's truncating BF16 conversion; revert bf…
Oseltamivir Aug 2, 2026
2319638
CollectiveX: truncate only where the kernel converts, not where the a…
Oseltamivir Aug 2, 2026
8799ba0
CollectiveX: sum the combine expectation in the same canonical order …
Oseltamivir Aug 2, 2026
33cd01b
CollectiveX: revert the canonical-ordering change (measured no-op)
Oseltamivir Aug 2, 2026
f4454ce
CollectiveX: reproduce FlashInfer's per-slot tree combine from the ke…
Oseltamivir Aug 2, 2026
27dfba1
CollectiveX: revert the per-slot tree combine model (measured no-op)
Oseltamivir Aug 2, 2026
78e6ad3
CollectiveX: build the expected per-rank message with the same functi…
Oseltamivir Aug 2, 2026
5e06578
CollectiveX: revert the shared _expert_transform expectation (measure…
Oseltamivir Aug 2, 2026
badb8a3
CollectiveX: drop the truncating output model for flashinfer-ep
Oseltamivir Aug 2, 2026
0d9d66f
CollectiveX: stage the flashinfer combine in place, not through a fre…
Oseltamivir Aug 2, 2026
19f0049
CollectiveX: submit the flashinfer combine payload from the workspace…
Oseltamivir Aug 2, 2026
4a34895
CollectiveX: model FlashInfer's payload-dtype combine reduction
Oseltamivir Aug 2, 2026
6e7d2fa
CollectiveX: tighten the flashinfer wheel probe and stage docstring
Oseltamivir Aug 2, 2026
92c7d0c
Merge remote-tracking branch 'origin/main' into collectivex-flashinfe…
Oseltamivir Aug 2, 2026
c12fdeb
CollectiveX: document FlashInfer EP and its payload-dtype combine
Oseltamivir Aug 2, 2026
0bef5e9
CollectiveX: drop the disproven truncating-store model
Oseltamivir Aug 2, 2026
6d05435
CollectiveX: run the unit tests on every PR
Oseltamivir Aug 2, 2026
49d25ec
CollectiveX: note the slot-tree oracle's memory scaling
Oseltamivir Aug 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/collectivex-sweep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
description: "EP library to sweep — 'all' runs every EP backend in one matrix"
type: choice
default: all
options: [all, deepep-v2, mori, uccl-ep, nccl-ep]
options: [all, deepep-v2, mori, uccl-ep, nccl-ep, flashinfer-ep]
only_sku:
description: Restrict to one GHA runner pool; blank = all
type: string
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/test-collectivex.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Test CollectiveX

# The sweep exercises the benchmark on real hardware, but nothing ran CollectiveX's own
# unit tests, so the oracle contracts they pin were unverified on every PR. Torch is
# installed CPU-only: the torch-dependent tests are combine-oracle arithmetic checks that
# never touch a device, and without it they skip silently rather than fail.

on:
pull_request:
paths:
- 'experimental/CollectiveX/**'
- '.github/workflows/test-collectivex.yml'

permissions:
contents: read

jobs:
test:
if: github.event.pull_request.draft != true
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.12'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --index-url https://download.pytorch.org/whl/cpu torch

# Every skip in this suite is torch-gated, so a missing torch turns the oracle
# checks into silent passes. Fail here instead, where the cause is obvious.
- name: Verify torch is importable
run: python -c "import torch; print(torch.__version__)"

- name: Run unit tests
run: |
cd experimental/CollectiveX
python -m unittest discover -s tests -p "test_*.py" -v
1 change: 1 addition & 0 deletions experimental/CollectiveX/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ scale-up domain.
| MoRI | `production` — vLLM `--all2all-backend mori_*`, SGLang `--moe-a2a-backend mori` | `normal` mode uses the direct `IntraNode` kernel for scale-up EP8 on every CDNA SKU and pins `InterNodeV1` for EP16 over 2x8 XGMI + RDMA. `low-latency` mode selects the `IntraNodeLL` decode kernel (single-call, pure-intranode, same compact layout and unweighted combine as `IntraNode`), decode/EP8 only. FP8 dispatch is caller-prequantized (per-SKU e4m3fnuz on gfx942, e4m3fn on gfx950); combine stays BF16 (`quant_type=none`) alongside BF16 dispatch |
| UCCL-EP | `candidate` — no engine exposes a UCCL-EP selector | [UCCL](https://github.com/uccl-project/uccl) EP: a drop-in, API-identical DeepEP replacement whose CPU proxies issue GPUDirect RDMA over plain `libibverbs` (no NVSHMEM/IBGDA), with software message ordering, atomics, and flow control; scale-up is single-node `cudaIpc` over NVLink/XGMI (never MNNVL). `normal` mode is the legacy `Buffer` `dispatch`/`combine` (unweighted rank-sum); `low-latency` reuses the legacy `low_latency_dispatch`/`low_latency_combine` decode kernels (weighted combine), decode/EP8 only. FP8 dispatch is caller-prequantized in `normal` mode (blockwise e4m3fn, per-SKU e4m3fnuz on gfx942); in `low-latency` mode the caller sends BF16 and the decode kernel quantizes to e4m3 internally (`use_fp8`). Combine is BF16. Runs on NVIDIA and AMD (H100/H200/B200 + MI300X/MI325X/MI355X), EP8 scale-up. Cross-node EP16 is functional (the internode RDMA path connects and the light case passes correctness) but its CPU-proxy throughput overruns the standardized per-case wall-clock budget on heavy token counts, so EP16 is an unsupported coverage row for now |
| NCCL EP | `candidate` — NVIDIA's own library, but no engine exposes an NCCL-EP selector | [NCCL EP](https://github.com/NVIDIA/nccl/tree/master/contrib/nccl_ep): NVIDIA's native MoE dispatch/combine on the NCCL Device API — LSA (NVLink load/store) intra-node, GIN (GPU-Initiated Networking) inter-node — driven through the `nccl4py` bindings. `normal` mode selects the `HIGH_THROUGHPUT` algorithm (FLAT `[N, hidden]` receive, unweighted rank-sum combine); the `LOW_LATENCY` algorithm carries an EP8 `ll_backends` row on all six NVIDIA SKUs, restored once the single-handle fix removed the NVIDIA/nccl#2303 signal aliasing. BF16 only: NCCL EP's FP8 machinery exists upstream but its RELEASE.md lists it unsupported/untested, so no FP8 case is emitted. NVIDIA-only and CUDA 13 only. EP8 scale-up on H100/H200/B200/B300 plus EP8 and EP16 on GB200/GB300, where EP16 stays inside the MNNVL scale-up domain. x86 EP16 scale-out is an unsupported coverage row: the cross-node GIN path faults inside `nccl_ep.cc` identically on RoCE and IB across four SKUs, a GDAKI limit rather than a fabric-selection one |
| FlashInfer EP | `production` — vLLM `--all2all-backend flashinfer_nvlink_one_sided` | [FlashInfer](https://github.com/flashinfer-ai/flashinfer) `MoeAlltoAll`: TensorRT-LLM's one-sided MNNVL all-to-all, where each rank writes tokens straight into its peers' workspace windows and combine reads them back — no send/recv pairing and no NVSHMEM. `normal` mode only (there is one kernel family; no separate decode path), BF16 only, and GB200/GB300 only, since the transport is MNNVL. EP8 and EP16, both inside the scale-up domain. Unlike every other backend here, its combine accumulates in the PAYLOAD dtype rather than FP32: wheels before 0.6.16 reduce the top-k contributions with a pairwise BF16 tree that rounds at every level, so the oracle models that reduction directly (`combine_reduction = "topk-slot-tree"`) instead of widening the tolerance. 0.6.16 moved the accumulator to FP32, and the adapter switches models on the installed version |

DeepEP V2 means the `ElasticBuffer` implementation introduced by
[DeepEP PR #605](https://github.com/deepseek-ai/DeepEP/pull/605), not a newer legacy `Buffer` build.
Expand Down
Loading