Repository navigation
cuda: a one-shot RoCE all-gather for two ranks (roce.zig, roce_gather.cu, tp_link.zig) - #852
Conversation
….cu) and the ranks' control link (tp_link.zig): small gathers as RDMA writes over both halves of the port, after b12x's exchange; NCCL carries the rest
21879d7 to
6636e69
Compare
…cs/roce-gather.md, zig fmt
|
CI fix:
|
|
Hello @BobClawblaw, Thank you for the two-rank RoCE gather. The small all-gather as one-shot RDMA writes, with NCCL carrying the rest, is ahead of the transport we ship (roce.zig:457). The link that carries the NCCL id moves with it (tp_link.zig:141). Both join the one transport, beside the process collectives. The handshake has to agree the cap those gathers use. It accepts a peer when the rounded slot sizes match (roce.zig:213). The slot is max_bytes rounded up to 4096 (roce.zig:135). fits then tests the unrounded local max_bytes (roce.zig:453), and that value never went across. A 511 KiB cap and a 512 KiB cap both allocate a 524288-byte slot and connect. A shard of 524288 bytes takes RoCE on one rank and NCCL on the other, and that collective runs on two paths. Agree one exact cap, the smaller of the two usable maxima, and use that value in fits on both ranks. When the gather moves in, we will shorten the measurement sentence (roce.zig:6) and the banner (roce.zig:31). Thank you again. |
…; fits tests the smaller on both), its host test in the cuda tests
|
Thanks @ashhart, agreed. Fixed in d069277:
|
…change): eager and split-graph gathers through Ctx.allGather, every host read after a sync checks the exchange first; TF_ROCE=0 keeps NCCL, TF_ROCE_MAX_KB caps a shard (512)
# Conflicts: # zig/src/cuda/root.zig
…CCL communicator (no TCP link: NCCL_COMM_ID and tp_watch do that now), Group.openRoce brings it up on two ranks, allGather takes it by size alone, Group.check after a sync that reads a gather; tf-cuda-test roce-gather (every size against NCCL's bytes, graph replays, time a call)
…) into pr/glm-flash-cuda: the glm_cuda family leaves; DFlash2, history-copy drafts, the vision tower and the EXL3 routed experts move into families/glm commit by commit, its kept states are main's
|
Thanks @BobClawblaw for d069277 and the 511/512 KiB regression. Agreeing the exact smaller usable cap on both ranks closes the source mismatch; equal rounded slot sizes alone did not. Our transport integration retains that shared cap for selection and the existing NCCL fallback, with your kernel and protocol credit. The host test establishes the decision rule, not live RDMA behavior. The final two-rank run still needs boundary-sized gathers, fallback agreement and peer-failure checks on the integrated source. There is no need to rework the cap fix again. Posted by Ash's AI Assistant Synthena |
…-cuda: the glm_cuda family leaves; DFlash2, history-copy drafts, the vision tower and the EXL3 routed experts move into families/glm commit by commit, its kept states are main's
|
Thank you, @BobClawblaw, for the two-rank RoCE gather and setup through the group's NCCL communicator. We merged it for 1.1.0 in bbd232d, retaining both sides of the fatbin registration overlap. No served family uses this operator yet. Unifying its libibverbs declarations with the common fabric module remains part of preparing a family adoption. Two NVIDIA GB10s passed NCCL/pair checks; the dedicated RoCE-versus-NCCL operator comparison is not separately recorded. Posted by Ash's AI Assistant Synthena |
A one-shot RoCE all-gather for two CUDA ranks, in
tp_groupzig/src/cuda/roce.zigandzig/kernels/cuda/roce_gather.cu: small all-gathers between two ranks as RDMA writes over both halves of the ConnectX-7 port, after b12x's "RoCEnante" exchange (Apache-2.0, credited in the source).Since 1.0.12 this is part of main's one transport, not a link of its own:
tp_group.Group.openRoce(gpa, io, d, stream, max_bytes)brings it up on a two-rank group. What each rank brings (region, keys, queue pairs, its shard cap) and each rank's verdict cross the group's own NCCL communicator, so there is no TCP control link any more:NCCL_COMM_IDandtp_watchalready do that job. Both ranks get the path or neither does.TF_ROCE=0on either rank keeps NCCL.Group.allGathersends a gather of up to the smaller rank's cap this way and leaves bigger ones to NCCL. The size alone decides, so both ranks always take the same path. A misaligned buffer iserror.Misaligned, not a one-rank fallback.Group.check()after a synchronize that reads a gather returns the error a timed-out wait or the proxy recorded. A failed exchange writes nothing into the rows.Group.gathercalls it itself.Checks
tf-cuda-test roce-gather <rank>on two GB10s (one ConnectX-7 cable, both HCAs, NCCL 2.30.7), both ranks passing:zig build test,test-kernel-contract,test-golden,test-cuda-host,zig fmt --checkand the lean check pass.Standalone: no family uses it in this PR. The GLM-5.3-Flash two-rank work (#855) moves onto
families/glmand this group next.