Repository navigation
Description
[Proposal]: libfabric-CXI backend for UCCL-EP on HPE Slingshot
Hi UCCL team,
We're from the Apertus / Swiss AI training effort, working on large-scale open MoE training on Alps (using HPE's Slingshot-11 Cassini NIC). For Apertus 2 we're evaluating replacements for the default NCCL all-gather-style MoE dispatcher, and UCCL-EP looks like a strong fit because Slingshot does not provide IBGDA and we can only use some CPU-proxy design for all2all communication.
On Alps the network interface uses libfabric's cxi provider, not typical ibverbs. Before we start prototyping, we'd like to ask:
- Does UCCL-EP currently have a libfabric transport path? I saw EFA, Broadcom, and CX7 mentioned and supported. Is EFA implemented via libfabric (
efaprovider), and if so, is the transport layer abstracted enough that adding acxiprovider would be mostly provider substitution? - Is any CXI / Slingshot work already underway or planned? If so, we'd be glad to test on our platform for debugging and help with performance benchmarking.
- If not, would a libfabric/CXI backend be welcomed? Our intent is to keep the UCCL-EP API unchanged and map proxy operations to libfabric RMA, starting with low-latency mode. This might be useful because, as far as we know, many EU data centers actually use Slingshot because they were initially built for HPC, not exactly LLM training. If we can demonstrate performance gains, it would benefit many users.
What we'd contribute
Assuming the answer to (3) is yes, we'd plan to upstream:
- A libfabric/CXI transport backend (low-latency mode first, then normal/high-throughput).
- Validation on real Apertus MoE training on Alps Slingshot
- Benchmarks vs. all-gather performances.
What we plan to verify first currently
The main open questions on the CXI side are CUDA HMEM registration, MR-mode handling (FI_MR_ENDPOINT / FI_MR_PROV_KEY), the write-data / immediate-data path (FI_CXI_ENABLE_WRITEDATA, cq_data_size, FI_REMOTE_CQ_DATA), and ordering between payload writes and control notifications on CXI. We plan to work through these in standalone libfabric tests before touching UCCL — starting with fi_info -p cxi -v on the actual training container, then host-memory RMA, CUDA-memory RMA, a write-data test, and a payload+control ordering stress test. Happy to share the full plan if useful.
From my understanding of the paper, UCCL-EP uses immediate-data control messages to emulate ordering semantics for EP modes. Correct me if wrong. This means the write-with-immediate number perf matters a lot which we have to test. If performance is low, we need to think of design changes.
Why we think this can be useful for both sides
- For UCCL: real Slingshot/CXI deployment and validation on an open large-scale MoE workload.
- For Apertus: a reusable open-source EP layer instead of an internal one-off.
- For the broader community: other EU data centers that want to train or serve large MoE models on Slingshot NICs.
Finally, thanks for building UCCL-EP, which benefits many people not use ib nics
Activity
PanJason commentedon May 21, 2026
At people related to this issue: @FFGGSSJJ @andresnowak @youliang-zhu @haodong98
MaoZiming commentedon May 21, 2026
@PanJason Thanks for reaching out! We are definitely interested.
We don’t currently have a generic libfabric backend in UCCL-EP, and there isn't ongoing CXI / Slingshot work on our side. That said, we would definitely welcome contributions toward a CXI / Slingshot backend and would be happy to work with you on it!
Could I confirm with you whether CXI supports AMO writes, and whether RDMA writes and AMO writes are ordered with respect to each other in send order?
If both are supported, UCCL-EP may be able to bypass the write-with-immediate path. We mainly use write-with-immediate when the network does not provide such guarantees. We have not observed write-with-immediate to be the bottleneck in practice.
cc @YangZhou1997
PanJason commentedon May 21, 2026
@MaoZiming Thanks for your feedback. On paper, CXI does support AMO, but whether our provider (HPE Slingshot 11 Cassini) supports it needs some experimentation. I am testing them now and will come back to you tmr.
PanJason commentedon May 26, 2026
@MaoZiming I was doing a bit of investigation over the weekend. Here is what I found for your question:
Support for AMO writes
TL;DR: CXI with the implementation on our slingshot NIC supports AMO writes. The following operations are supported for both host memory (local DRAM to remote DRAM) and Device memory (local HBM to remote HBM)
fi_writeIBV_WR_RDMA_WRITEfi_readIBV_WR_RDMA_READfi_atomic(..., FI_ATOMIC_WRITE)fi_atomic(..., FI_SUM)fi_fetch_atomic(..., FI_ATOMIC_READ)fi_fetch_atomic(..., FI_SUM)fi_writedataIBV_WR_RDMA_WRITE_WITH_IMMSupport for ordering
TL;DR from my results,
if AMO is usingif AMO is usingfi_atomic(..., FI_ATOMIC_WRITE)then no (at least not between DRAM, works on my HBM test but I am not sure if that usage pattern is what UCCL needs).[This is wrong because of a bug in my benchmark code, which changes the src mem before the previous fi_atomic is acked from cq on the sender side]fi_atomic(..., FI_ATOMIC_WRITE)orfi_atomic(..., FI_SUM)then yes, at least on the same endpoint / TX context / transmit queue. This result holds empirically on our slingshot nic, which is not guaranteed by the docRelevant interfaces
The two basic interfaces are:
The question is whether this sender-side order:
implies this receiver-side visibility:
Host-Memory Workflow
Sender:
Receiver:
Result:
FI_ATOMIC_WRITEFI_SUMcounterFI_ATOMIC_WRITEFI_ATOMIC_WRITEFI_DELIVERY_COMPLETEbefore controlDevice-memory payload + DRAM control word
Sender:
Receiver:
Result:
FI_ATOMIC_WRITEFI_SUMFI_ATOMIC_WRITEFI_ATOMIC_WRITEFI_DELIVERY_COMPLETEbefore controlDevice-memory payload + control word
Sender:
Receiver variants:
Result:
fi_writefi_writeFI_ATOMIC_WRITEcontrolFI_ATOMIC_WRITEcontrolNote: this device-memory control test was mainly control-style, not the full per-sequence UCCL queue protocol.
FI_SUMtargeting GPU HBM was tested as an atomic capability, but not yet as the full payload-write + GPU-HBM-control ordering pattern.Conclusion
Empirically yes on Alps CXI backed by slingshot. We did not see any write/AMO reordering with any of the configuration combination shown in appendix in any of the 5 runs each of which contains 1m iterations. When the AMO/control was observed, the payload write was visible on host or GPU.
Nevertheless, I would not make it as an unqualified libfabric generic assumption.
It would also be good if you can share with me some pseudo code about how UCCL can possibly utilize this write + AMO pattern so I can do some more accurate tests. I can check the code by myself as well.
Appendix:
Different Configurations I have tested for the empirical results:
Memory:
Receiver Validation:
MR Layout:
Operation Pattern:
1 fi_write(payload) -> fi_atomic(FI_ATOMIC_WRITE control)1 fi_write(payload) -> fi_atomic(FI_SUM control)N fi_write(payload) -> fi_write(control)N fi_write(payload) -> fi_atomic(FI_ATOMIC_WRITE control)API Spelling:
fi_write + fi_atomicfi_writemsg + fi_atomicmsgfi_write + fi_writedataHMEM / Registration:
2.
FI_HMEM_SYSTEMfor host memoryFI_HMEM_CUDAfor GPU HBMOrdering Request:
tx_order=0FI_ORDER_RMA_WAW(fi_writeonly)FI_ORDER_WAW(more general forfi_writeanffi_atomic)All the combo passed the tests on the same endpoint / TX context / transmit queue.
PS: By the doc, both
FI_ORDER_RMA_WAWandFI_ORDER_WAWactually just preserves the order of operations over the same mem addresses not operations across different mem addresses but both work empirically, even without negotiation ini initialization.Concurrency / Stress Shape:
PanJason commentedon Jun 9, 2026
@MaoZiming I am working on porting UCCL now and I am checking the code. I have some questions:
Why do we have to use amo here to increment the tail here ? What are the issues if we replace this with a raw write of the tail to the remote? Because in my understanding, the
rdma_channel_taillayout is(channel_id, src_rdma_rank)and eachnvl_rankonly writes to the correspondingnvl_rank, so only onelanein the senderwarpof the cuda block with the specificchannel_idwill write to this remote?fergusfinn commentedon Jun 10, 2026
hi @PanJason. We're working on the Isambard cluster in the UK, from what i can tell it has a similar shape - libfabric/CXI/Slingshot etc. We've been working on an internal experimental UCCL-EP fork (for wideEP inference, mostly) - it's pretty AI-driven, at the moment, but it is up and serving well in vLLM and SGLang benchmarks. I put our working (messy) version up here doublewordai#1
Design-wise it matches what you measured: we skip write-with-immediate entirely and use fi_write plus libfabric atomic adds for the tail/control path, leaning on the same-TX-context write→AMO ordering you measured.
would be good to compare notes or to work from either base to get libfabric/CXI support upstreamed to UCCL.
PanJason commentedon Jun 10, 2026
@fergusfinn Hi, we have made fi_write + fi_atomic work as well. The problem is non-ideal performance. On our configuration, 4 GPUs per node, each GPU has 1 200Gb/s Slingshot NIC, the UCCL benchmark only give 70% of the NIC bw:
The benchmark shape follows the DeepSeek-V3 pretraining-style configuration where possible.
The command we are using:
Benchmark configuration:
(200 Gb/s).
The table reports the bottleneck bandwidth and transmit latency across node-local benchmark summaries. Internode rows report RDMA bandwidth; the intranode row reports NVL bandwidth. These are fresh validation runs with proxy command tracing disabled (
UCCL_PROXY_TRACE=0), not reused allocation data.We also did some porting on
fi_writedatabut I got mysteriousENTRY_NOT_FOUNDerrors from slingshot, which indicates event buffer on the NIC is overflowing. Did you ever see this?fi_write+fi_writebut have some data corruption. This is why I was asking the question before .fergusfinn commentedon Jun 11, 2026
Current analogous numbers:
Hey - cluster is pretty congested at the moment, so i couldn't do the larger benchmarks. The measured ceiling we get from fi_write is something like ~24.3GB/s/NIC. I think amplification over the line rate is basically because the benchmarking script here has the denominator as the kernel time. Which then inflates the bandwidth since transfers are asynchronous with regards to the kernels? when using wall time we get something more like 21GB/s/NIC for the EP8 config.
Re. perf we got quite a bit faster by posting the writes asynchronously and then queueing the AMOs until their writes completed.
Haven't seen this, we had some problems that i can't quite remember getting fi_writedata working (might have been this) so we dropped it. Will look into it again if i get a chance
There's some arcane stuff in the CXI spec about ordering of fi_writes, other writes and amos with respect to each other, from what i can tell, in principle they're unordered, which could cause corruption. https://ofiwg.github.io/libfabric/main/man/fi_cxi.7.html. it could be that the empirics above are just an artifact of the small-ish payload sizes. In practise, we wait for CQ completions before posting AMOs, which i think gives ordering. we saw exactly this with immediately-posted AMOs, it was clean at small token counts, corrupted output at ≥1024 tokens. Gating the AMO on the write's CQ completion seemed to fix it. I think this could have something to do with FI_CXI_RDZV_THRESHOLD changing behaviour at different message sizes.
PanJason commentedon Jun 11, 2026
Thanks a lot for the performance numbers. I also ran your code here doublewordai#4 but got very poor performance. Could you please let me know which code you used to generate the numbers above? The number I got is as below:
uccl/epI am now checking what is going wrong here. If you can share your commit, it would great to debug. The code we used is here https://github.com/swiss-ai/uccl/tree/slingshot-dev
One more thing I would like to ask is whether you have some raw performance numbers of
fi_atomicIt seems on our platform thefi_atomicis extremely slow. I tried another version of batching the AMOs like what you have done but I got almost the same performance. Since we are using almost the same hardware, it would be really helpful if we could do some AB testing over the network primitives as well to check the slingshot/CXI configuration correctness.I can provide scripts if you need for testing
fi_writedatafergusfinn commentedon Jun 11, 2026
great - yes i will test out your branch!
The tuning variables we have for FI_CXI_* are:
https://docs.isambard.ac.uk/user-documentation/guides/nccl/ (from here, for reference).
I guess this could explain differences in perf numbers. Let me run w/ your branch and get back to you. (my numbers were from this branch doublewordai#1 - but it has the one you used at its tip basically, so it should have the same perf)
Happy to run any testing scripts for the raw writedata etc. versions.
fergusfinn commentedon Jun 11, 2026
doublewordai/uccl@cxi-ep(373ce5d)swiss-ai/uccl@slingshot-dev(1da9b40)I think it might indeed be cluster tuning - it looks like the two branches are within a hair of one another
PanJason commentedon Jun 11, 2026
Ah thanks a lot for the prompt response and numbers, which narrows the investigation scope a lot.
fi_write/fi_writedata performance test code:
https://pastebin.com/RVK5QD5L
And the slurm scripts we used to test the performance:
https://pastebin.com/yUnVBESL
You can adapt from here to see whether
fi_writedataworks on your cluster.I am also doing another AB test now with your FI_CXI configs and your code and see what the results will look like.
PanJason commentedon Jun 11, 2026
I tried with your
FI_CXI_*configuration and what I got is still quite low.One thing I found not working on our cluster is
FI_THREAD_ENDPOINTand my run had to fall back toFI_THREAD_DOMAIN. I guess likely this is not where the perf diff lies.So likely this is a slingshot configuration issue. Given that we have the same hardware, a very next step is to compare the raw performance numbers of
fi_*primitives such asfi_writeandfi_atomicto see where the differences are coming from.fergusfinn commentedon Jun 12, 2026
ok, so with
API_KIND=writedata, i get-38 (ENOSYS, function not implemented)running your script - this is the error i found when i tried this the first time.What version of libfabric do you have on your system? I think the reason for my lack of writedata is is that the build here is very old - its showing 1.22, whereas it looks like fi_writedata landed in libfabric a couple months ago (https://github.com/ofiwg/libfabric/blob/main/NEWS.md#v250-fri-march-20-2026).
I built 2.5.1 locally, and i get the same error you described with fi_writedata:
Then, perf numbers for fi_write, for both libfabric versions, 'our env' is the one from above, 'default env' is the one that's defaulted in the scripts with our FI_CXI_* toggled off. Swept both slots and payload sizes because i got some weird data, but its confined to 1.22
There's something up with large registered buffer sizes on 1.22, so at the least this has convinced me i should upgrade!
Then i reran in case libfabric version explained the perf difference on your cluster, it doesn't seem to:
doublewordai/uccl@cxi-epdoublewordai/uccl@cxi-epswiss-ai/uccl@slingshot-devswiss-ai/uccl@slingshot-devPanJason commentedon Jun 12, 2026
Cool thank you Fergus. Currently our cluster is down because of power outage but I can still provide you with some info.
2.5.0
Earlier results are similar to yours 2.5.1 version, need a sweep to verify when the cluster comes back
I guess likely fi_write is not the issue, probably fi_atomic. On our cluster fi_atomic performance is very poor. I prepared a reproducer doc for you and can you also run that to align?
https://pastebin.com/P3bktrGD
8 remaining items
fergusfinn commentedon Jun 15, 2026
ok great! glad that commit helped. I'm happy to rebase the other work i'm doing onto your branch and build & test on that - do you have an up to date public branch? I'd like to test it under load and see if it holds up. If you open it as a PR against your fork main, we can move the detailed discussion there?
PanJason commentedon Jun 15, 2026
Nice I willl create a branch and a PR and at you there. Then we can work together for more tests. The reason I haven't created it yet is that I encountered some errors while testing
EP==64. Trying to figure out where the error is coming from and I don't want to push something that has errors on the benchmark.PanJason commentedon Jun 15, 2026
@fergusfinn I updated the results above. It turned out to be the benchmark problem. The benchmark after I changed is here https://pastebin.com/DKu0vZiD. Also your PR1 failed in
EP==64case here:At
ep/src/internode.cu:2008Probably it is worth checking.
Now I think the code is mostly fine. I am creating the PR.
PanJason commentedon Jun 16, 2026
@fergusfinn I created the PR here: #997
The public branch is here https://github.com/swiss-ai/uccl/tree/main and https://github.com/swiss-ai/uccl/tree/slingshot-dev-clean which only include the basic porting code and minimum changes to the existing benchmark. I sent you the invitation.
You can pick main, and I will keep rebasing main over the UCCL main, so our PR is always in a mergeable state.
We can move our discussion there if you want.
fergusfinn commentedon Jun 16, 2026
great! i'll get that compiling and reproduce your numbers, and then run it in vLLM
PanJason commentedon Jun 16, 2026
Are your vLLM tests outside the UCCL tracking tree or inside? If you test vLLM on inference side, I can then test the training side.
fergusfinn commentedon Jun 17, 2026
outside - for vllm, UCCL is deepEP compatible, so there's no vLLM code changes required, and tests at the moment look like sending lots of HTTP requests.
ryanhankins commentedon Jun 23, 2026
I implemented fi_writedata() for CXI. Please let me know if I can help.
PanJason commentedon Jun 24, 2026
Hi Ryan, I have also implemented one version using
fi_writedata. The reason why I did not use that version is that I keep gettingENTRY_NOT_FOUNDerrors from slingshot nic. I tried to increase the cq size on the remote side, which was proven not useful. Do you have any idea about this issue?ryanhankins commentedon Jun 24, 2026
Can you please try to set: export OFI_NCCL_DISABLE_DMABUF=1 and see if it overcomes this error? There is a bug in some versions of libfabric.
p2p/cxi: simplify low-version warning to point at uccl-project#956
p2p/cxi: simplify low-version warning to point at uccl-project#956
p2p/cxi: log libfabric runtime version, warn on <2.0 large-MR cliff (#…
YangZhou1997 commentedon Nov 8, 2026
The original CXI/Slingshot backend request is implemented by #997, which is merged into
main. It adds the libfabriccxitransport for UCCL-EP, enabled withUSE_LIBFABRIC_CXI=1, including the proxy integration and RDMA/atomic operations.This proposal can be closed as implemented; any remaining CXI performance or shutdown problems should be tracked in their specific issues.