Skip to content

Commit 75d7e55

Browse files
authored
CollectiveX: add UCCL-EP as a third pluggable EP backend (#2288)
1 parent 5a6f2fa commit 75d7e55

15 files changed

Lines changed: 906 additions & 53 deletions

File tree

.github/workflows/collectivex-sweep.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
description: "EP library to sweep — 'all' runs every EP backend in one matrix"
1111
type: choice
1212
default: all
13-
options: [all, deepep-v2, mori]
13+
options: [all, deepep-v2, mori, uccl-ep]
1414
only_sku:
1515
description: Restrict to one GHA runner pool; blank = all
1616
type: string
@@ -84,10 +84,12 @@ jobs:
8484
if: ${{ fromJSON(needs.setup.outputs.n) > 0 }}
8585
strategy:
8686
fail-fast: false
87-
# Fixed global cap; real throttling is each SKU pool's runner count and its
88-
# cluster's Slurm partition. setup interleaves shards across SKUs, so the
89-
# first jobs under this cap spread over pools instead of queuing on one.
90-
max-parallel: 10
87+
# Global cap; real throttling is each SKU pool's runner count and its cluster's
88+
# Slurm partition. setup interleaves shards across SKUs so the cap spreads over
89+
# pools instead of queuing on one. Kept above the total per-pool runner count so a
90+
# saturated pool's dispatched-but-waiting legs cannot starve pools that have free
91+
# runners (10 was too low when the shared fleet is busy with concurrent sweeps).
92+
max-parallel: 30
9193
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
9294
runs-on: ${{ matrix.sku }}
9395
timeout-minutes: 350

experimental/CollectiveX/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ unsupported/
55
.shards/
66
.collx_workloads/
77
.collx_backend/
8+
.collx_sources/
89
/matrix_full.json
910
gpucore.*
1011

experimental/CollectiveX/README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@ responsibility. The full measurement methodology is in [docs/methodology.md](doc
1313

1414
The workload uses packed placement and one pinned `fixed-profile` resource configuration per
1515
backend/topology; there is no tuning sweep. Combine is always BF16; dispatch precision is a swept
16-
dimension — a BF16 control plus a caller-prequantized FP8 dispatch on every backend. Coverage is
17-
uniform routing only. Cases run in one of two modes:
16+
dimension — a BF16 control plus an FP8 dispatch on every backend, caller-prequantized in `normal`
17+
mode (in `low-latency` the DeepEP and UCCL-EP kernels quantize internally from BF16; MoRI stays
18+
caller-prequantized). Coverage is uniform routing only. Cases run in one of two modes:
1819

1920
- `normal` uses `layout-and-dispatch-v1`, rank-deduplicated token payloads, and activation-only,
2021
unweighted rank-sum combine. It runs the full decode and prefill ladders.
2122
- `low-latency` uses each backend's decode-optimized kernel family: on DeepEP the legacy
2223
`deep_ep.Buffer` IBGDA `low_latency_dispatch`/`low_latency_combine` (a per-expert padded receive
23-
and a source-side gate-weighted combine); on MoRI the `IntraNodeLL` kernel (single-call,
24+
and a source-side gate-weighted combine); on UCCL-EP the same legacy `Buffer` low-latency kernels
25+
over its CPU-proxy transport; on MoRI the `IntraNodeLL` kernel (single-call,
2426
pure-intranode, same compact layout and unweighted rank-sum combine as `IntraNode`). It is a
2527
decode-phase-only, per-SKU-capability-gated addition whose runnable set differs from `normal`'s, so
26-
it is enabled from each SKU's `ll_backends` registry entry (currently DeepEP V2 EP8 on H100/H200/B200
27-
and MoRI EP8 on MI300X/MI325X/MI355X). Scoped single-node EP8 runs over the intra-node NVLink/XGMI
28+
it is enabled from each SKU's `ll_backends` registry entry (currently DeepEP V2 EP8 on H100/H200/B200,
29+
MoRI EP8 on MI300X/MI325X/MI355X, and UCCL-EP EP8 on H100/H200/B200 only — UCCL's low-latency kernel
30+
trips a warp-group assertion on AMD's CU count, so the AMD SKUs keep UCCL-EP normal mode without LL).
31+
Scoped single-node EP8 runs over the intra-node NVLink/XGMI
2832
low-latency path (no `/dev/gdrdrv` needed — validated on H200 with it absent); NVSHMEM/IBGDA on the
2933
wire is only a multi-node scale-out (EP16) concern.
3034

@@ -63,6 +67,7 @@ scale-up domain.
6367
|---|---|
6468
| DeepEP V2 | `normal` mode is PR #605 `ElasticBuffer` plus exact upstream #630 and #640 fixes: LSA for scale-up and GIN for x86 EP16 scale-out. FP8 dispatch via `use_fp8_dispatch` (blockwise e4m3fn) alongside BF16. `low-latency` mode is the legacy `deep_ep.Buffer` IBGDA decode kernels (per-expert padded layout, weighted combine, `use_fp8` e4m3fn), decode/EP8 only |
6569
| 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 |
70+
| UCCL-EP | [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 |
6671

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

0 commit comments

Comments
 (0)