2. RDMA基础:概念、协议对比与核心操作

2.1 为什么多GPU集群需要RDMA

在单机多卡或跨节点GPU训练中,梯度同步和参数交换是性能瓶颈。传统TCP/IP协议栈需要经过内核、协议处理、数据拷贝等多个环节,延迟高且CPU开销大。RDMA(Remote Direct Memory Access,远程直接内存访问)的核心思想是:让网卡(RNIC/HCA)直接读写远端主机内存,绕过操作系统内核和CPU参与,从而将节点间通信延迟从数十微秒降低到1~3微秒,同时释放CPU用于计算。

对于多GPU集群,RDMA的价值体现在三个层面:

  • 低延迟:单次消息延迟可低至1μs量级,满足AllReduce等集合操作的同步需求。
  • 高带宽:现代RDMA网卡支持100Gbps~400Gbps,配合多轨组网可线性扩展。
  • CPU卸载:通信过程无需CPU拷贝,GPU Direct RDMA更可让数据在GPU显存间直接传输,跳过主机内存。
关键认知:RDMA不是一种具体网络,而是一类技术总称。它包含底层协议(InfiniBand、RoCE、iWARP)、编程接口(Verbs API)和上层库(libibverbs、UCX、NCCL)。在多GPU集群设计中,我们通常关注的是物理拓扑如何匹配RDMA的传输特性。

2.2 RDMA核心概念:队列对与内存注册

RDMA通信的基本模型基于队列对(Queue Pair, QP)。每个QP由发送队列(SQ)和接收队列(RQ)组成,通信双方通过QP建立连接。工作请求(WR)被提交到队列,由网卡硬件异步执行,完成后再通过完成队列(CQ)通知应用程序。

另一个核心概念是内存注册(Memory Registration)。RDMA要求通信缓冲区在通信前被锁定(Pin)并注册到网卡,网卡才能直接访问该内存区域。注册后获得本地密钥(lkey)和远程密钥(rkey),远端凭rkey才能访问本端内存。

节点A(发起方) 发送队列 (SQ) 接收队列 (RQ) 完成队列 (CQ) 内存注册区 (lkey/rkey) 节点B(目标方) 发送队列 (SQ) 接收队列 (RQ) 完成队列 (CQ) 内存注册区 (lkey/rkey) RDMA网络 InfiniBand / RoCEv2 硬件卸载,零拷贝 WR 数据到达 ACK/CQ RDMA Read/Write

上图展示了两个节点通过QP进行通信的基本架构。发送方将WR提交到SQ,网卡硬件从注册内存区直接读取数据并发送到网络;接收方网卡将数据直接写入预先注册的内存区,完成后在CQ中产生完成事件。整个过程无需CPU介入数据搬运。

2.3 InfiniBand与RoCE对比

目前主流的RDMA实现有两种:InfiniBand(IB)和RoCE(RDMA over Converged Ethernet)。两者在协议栈、网络要求、生态和成本上有显著差异。

对比维度 InfiniBand RoCEv2
协议栈 独立IB网络层+传输层 基于UDP/IP(以太网)
网络要求 专用IB交换机/线缆 需无损以太网(PFC/ECN)
最大带宽 NDR 400Gbps/端口 400Gbps(取决于以太网)
延迟 极低(~0.5μs) 低(~1.5μs,依赖交换机)
拥塞控制 内置基于信用的流控 依赖ECN+PFC配合
成本 较高(专用硬件) 较低(复用以太网)
生态兼容 NCCL/UCX原生支持 需配置无损网络参数
重要提醒:RoCEv2虽然成本低,但对网络丢包极其敏感。即使0.1%的丢包率也会导致RoCE吞吐量下降50%以上。因此,部署RoCE必须启用PFC(优先级流控)和ECN(显式拥塞通知),并确保网络无环、无拥塞。在多GPU集群中,如果预算允许,InfiniBand通常是更稳妥的选择。

2.4 核心操作:Send/Receive与Read/Write

RDMA提供四种基本操作类型,分为双边操作和单边操作两大类。

2.4.1 双边操作:Send / Receive

Send/Receive需要通信双方都参与:发送方调用ibv_post_send提交Send WR,接收方必须预先ibv_post_recv提交Receive WR并准备好缓冲区。数据到达后,接收方网卡将数据写入预先注册的缓冲区,并产生完成通知。

  • 特点:语义类似传统消息传递(MPI_Send/Recv),双方都需要参与。
  • 适用场景:控制消息、小数据量同步、连接建立。
  • 缺点:接收方必须提前知道消息到达并准备好缓冲区,否则数据会被丢弃。
// 发送方伪代码
struct ibv_send_wr wr = {0};
wr.opcode = IBV_WR_SEND;
wr.sg_list = &sge;
wr.num_sge = 1;
ibv_post_send(qp, &wr, &bad_wr);

// 接收方伪代码(需提前执行)
struct ibv_recv_wr rr = {0};
rr.sg_list = &rsge;
rr.num_sge = 1;
ibv_post_recv(qp, &rr, &bad_wr);

2.4.2 单边操作:Read / Write

Read/Write是RDMA的精髓,允许一方(发起方)直接读写另一方(目标方)的注册内存,目标方CPU完全不知情。发起方需要知道目标方的内存地址和rkey。

  • RDMA Write:发起方将本地数据直接写入目标方指定内存地址。目标方无需预置Receive缓冲区。
  • RDMA Read:发起方从目标方指定内存地址读取数据到本地缓冲区。目标方完全被动。
GPU集群中的典型用法:NCCL的AllReduce在节点间通信时,通常使用RDMA Write将梯度数据直接写入目标GPU的显存(通过GPUDirect RDMA),目标GPU的CPU完全不需要参与数据接收过程。这大大减少了同步开销。
// RDMA Write 伪代码(发起方)
wr.opcode = IBV_WR_RDMA_WRITE;
wr.wr.rdma.remote_addr = remote_addr; // 目标方内存地址
wr.wr.rdma.rkey = remote_rkey;       // 目标方远程密钥
ibv_post_send(qp, &wr, &bad_wr);

// RDMA Read 伪代码(发起方)
wr.opcode = IBV_WR_RDMA_READ;
wr.wr.rdma.remote_addr = remote_addr;
wr.wr.rdma.rkey = remote_rkey;
ibv_post_send(qp, &wr, &bad_wr);

2.5 案例:NCCL中RDMA操作的选择

以NCCL(NVIDIA Collective Communications Library)为例,在多节点AllReduce中,NCCL会根据数据量和拓扑选择不同实现:

  1. 节点内:通过NVLink直接读写GPU显存,不经过网卡。
  2. 节点间(小消息):使用Send/Receive,因为消息量小,双边操作的控制开销可接受。
  3. 节点间(大消息):使用RDMA Write,将梯度分块直接写入目标节点的GPU显存,配合Ring AllReduce算法流水线传输。

实际测试表明,在100Gbps RoCEv2网络下,使用RDMA Write比Send/Receive在大消息(>1MB)场景下吞吐量提升约30%,延迟降低约40%。

2.6 常见误区与复盘

误区1:RDMA不需要CPU参与,所以CPU配置不重要。
实际上,虽然数据搬运不经过CPU,但QP创建、内存注册、完成事件轮询仍然需要CPU。高并发QP数会消耗大量CPU中断和内存带宽。建议为RDMA通信预留专用CPU核心。
误区2:RoCE和IB的编程接口完全一样,可以无缝切换。
虽然都使用Verbs API,但RoCE需要额外配置PFC、ECN、MTU等以太网参数,且对交换机缓冲区大小敏感。从IB迁移到RoCE时,必须重新验证网络配置。
误区3:RDMA Read比Write更高效。
实际上,RDMA Read需要目标网卡返回数据,涉及请求-响应往返,延迟更高。在AllReduce等场景中,优先使用Write推送数据,避免Read拉取。

2.7 本节小结