NCCL 传输架构详解NCCL 通过一套分层插件化的传输架构支持多种传输模式核心设计思想是统一抽象层 插件化扩展 自动选择最优路径。一、传输抽象层Transport Abstraction Layer核心定义在 src/include/transport.h 中所有传输都遵循同一个接口契约// 4 种内置传输类型#define NTRANSPORTS 4#define TRANSPORT_P2P 0 // GPU 直接 P2PNVLink/CUDA IPC#define TRANSPORT_SHM 1 // 共享内存同机进程间#define TRANSPORT_NET 2 // 网络跨节点通过 NET 插件#define TRANSPORT_COLLNET 3 // 集合通信网络如 IB SHARP#define TRANSPORT_PROFILER 4 // Profiler不是真正传输// 每个传输暴露的接口表struct ncclTransportComm {ncclResult_t (*setup)(…); // 建立前的参数协商ncclResult_t (*connect)(…); // 建立连接ncclResult_t (*free)(…); // 释放ncclResult_t (*proxySharedInit)(…);ncclResult_t (*proxySetup)(…); // Proxy 端建立ncclResult_t (*proxyConnect)(…);ncclResult_t (*proxyFree)(…);ncclResult_t (*proxyProgress)(…); // Proxy 端数据搬运进度ncclResult_t (*proxyRegister)(…); // 内存注册ncclResult_t (*proxyDeregister)(…);};struct ncclTransport {const char name[8];ncclResult_t (*canConnect)(…); // 判断是否能连接struct ncclTransportComm send; // 发送端接口struct ncclTransportComm recv; // 接收端接口};这 5 个传输实例被统一注册在 src/transport.cc 的 ncclTransports[] 数组中struct ncclTransport* ncclTransports[NTRANSPORTS1] {p2pTransport, // TRANSPORT_P2P (0)shmTransport, // TRANSPORT_SHM (1)netTransport, // TRANSPORT_NET (2)collNetTransport, // TRANSPORT_COLLNET (3)profilerTransport // TRANSPORT_PROFILER (4)};二、传输选择机制selectTransport 模板在建立通信时transport.cc 的 selectTransport 函数会遍历所有传输调用每个传输的 canConnect 来判断templatestatic ncclResult_t selectTransport(…) {for (int t0; tNTRANSPORTS; t) {struct ncclTransport *transport ncclTransports[t];int ret 0;NCCLCHECK(transport-canConnect(ret, comm, graph, myInfo, peerInfo));if (ret) {connector-transportComm transportComm; // 绑定到 connectorNCCLCHECK(transportComm-setup(…));return ncclSuccess;}}// 没有找到可用传输 - 报错}优先级顺序P2P (NVLink) → SHM (共享内存) → NET (网络) → COLLNETcanConnect 会基于拓扑信息判断P2P: 检查 CUDA 设备间是否有 NVLink 直连SHM: 检查是否在同一节点、同一进程空间NET: 有网络设备可用即可COLLNET: 需要集合通信网络硬件支持如 IB SHARP三、每个传输的具体实现每个传输都在 src/transport/ 下有自己的文件传输 文件 适用场景P2P p2p.cc 同机 GPU 间 NVLink 或 CUDA IPCSHM shm.cc 同机进程间共享内存NET net.cc 跨节点网络IB/RoCECOLLNET coll_net.cc 网络交换机内置集合通信如 SHARPNVLS nvls.cc NVLink SHARPNVSwitch 内置归约Profiler profiler.cc 仅用于 profiler 回调各传输的实例化以 P2P 为例// src/transport/p2p.cc:1345struct ncclTransport p2pTransport {“P2P”,p2pCanConnect,{ p2pSendSetup, p2pSendConnect, p2pSendFree, NULL,p2pSendProxySetup, NULL, p2pSendProxyFree, NULL,p2pProxyRegister, p2pProxyDeregister },{ p2pRecvSetup, p2pRecvConnect, p2pRecvFree, NULL,p2pRecvProxySetup, NULL, p2pRecvProxyFree, NULL,p2pProxyRegister, p2pProxyDeregister }};P2P 传输内部又根据实际能力分 4 种模式enum p2pType { P2P_DIRECT, P2P_INTERMEDIATE, P2P_IPC, P2P_CUMEM };P2P_DIRECT: GPU 直接访问对方显存NVLink P2PP2P_INTERMEDIATE: 通过中间 GPU 中转P2P_IPC: CUDA IPC同进程不同 GPUP2P_CUMEM: cuMem API跨进程NET 传输是最复杂的它通过 NET 插件机制对接各种网络硬件。四、NET 插件机制Network PluginNET 传输本身不直接做网络通信而是通过插件系统加载外部网络库。插件接口定义在 src/include/plugin/net/net_v12.htypedef struct {const char* name;ncclResult_t (*init)(…); // 初始化网络ncclResult_t (devices)(intndev); // 返回设备数ncclResult_t (*getProperties)(…); // 设备属性ncclResult_t (*listen)(…); // 监听连接ncclResult_t (*connect)(…); // 连接对端ncclResult_t (*accept)(…); // 接受连接ncclResult_t (*regMr)(…); // 注册内存ncclResult_t (*deregMr)(…);ncclResult_t (*isend)(…); // 异步发送ncclResult_t (*irecv)(…); // 异步接收ncclResult_t (*test)(…); // 轮询完成// … 更多回调} ncclNet_v12_t;插件加载在 src/plugin/net.cc 实现通过 dlopen 动态加载共享库由 NCCL_NET_PLUGIN 环境变量指定路径查找符号 ncclNetPlugin_v12支持多版本兼容v6~v12自动探测最高可用版本最多可加载 16 个独立插件// src/include/plugin/nccl_net.htypedef ncclNet_v12_t ncclNet_t; // 当前使用 v12#define NCCL_NET_PLUGIN_SYMBOL ncclNetPlugin_v12内置的 IB 网络插件实现在 src/transport/net_ib/支持GDR (GPU Direct RDMA): GPU 显存直通 RDMAGDRCopy: 通过 GDRCopy 库加速小消息GIN (GPU Initiated Network): GPU 直接发起网络操作GDAKI (GPU Direct Async Kernel Initiative): DOCA GPUNetIO 方案五、IBGDA / GDAKI 实现你关心的 IBGDA 对应的是 GDAKIGPU Direct Async Kernel Initiative代码在 src/transport/net_ib/gdaki/。这是基于 NVIDIA DOCA GPUNetIO 的技术核心思想是让 GPU 内核kernel直接操作网络硬件无需 CPU 参与Host 侧: gin_host_gdaki.cc / gin_host_gdaki.h — 管理 GIN (GPU Initiated Network) 连接Device 侧: DOCA GPUNetIO 设备头文件doca_gpunetio_dev_verbs_*.cuh提供了 GPU kernel 中操作 QP、CQ、发送/接收 WR 的能力通信方式: GPU kernel 直接写 doorbell、轮询 CQ实现零 CPU 参与的通信而 rdma_rt/ 目录下的 ibgda_rt.h 是针对 TPU v7 或其他非 NVIDIA 硬件的类似方案使用自定义驱动 /dev/sg-host-drv-2通过 TPU 内核模块执行 doorbell 写入和 CQ 轮询。六、GPU 上写通信算子GPU Initiated CommunicationNCCL 支持多种 GPU 直接驱动通信的方式统称为 GIN (GPU Initiated Network)方式 类型标识 说明纯 Host 驱动 NCCL_NET_DEVICE_HOST0 传统方式CPU 驱动网卡GPU Unpack NCCL_NET_DEVICE_UNPACK1 GPU 解包网络数据GIN Proxy NCCL_NET_DEVICE_GIN_PROXY2 GPU 通过 proxy 发起网络操作GIN GDAKI NCCL_NET_DEVICE_GIN_GDAKI3 GPU kernel 直写网卡 doorbell这些类型定义在 src/include/nccl_device/net_device.h。GIN 的设备侧实现在 src/include/nccl_device/gin/gin_device_api.h: GPU 侧 GIN 设备 APIgin_device_common.h: GPU 侧公共 GIN 代码gin_device_host_common.h: 主机和设备共享的 GIN 代码gdaki/gin_gdaki.h: GDAKI 特定的 GPU 侧接口七、整体数据流用户调用 AllReduce → Kernel Planner 分发任务到多个 Channel→ 每个 Channel 有 send/recv Connector→ Connector 绑定了 transportComm (来自 selectTransport 选择)→ 数据传输- P2P/SHM: 直接内存访问GPU 或 CPU 侧- NET: 通过 Proxy 线程 → NET 插件 → 网卡- GIN/GDAKI: GPU kernel 直接操作网卡零 CPU 开销核心思想是NCCL 为每种通信场景提供最优传输路径通过 canConnect 优先级遍历自动选择无需用户干预。NET 插件系统使得跨节点通信可以通过动态加载的外部网络库灵活扩展而 GIN/GDAKI 让 GPU 可以直接控制网络硬件消除 CPU 瓶颈。