第 3 周:RDMA verbs、QP、CQ 和 RNIC
对应原计划:
plans/muxi-fabric-network-learning-plan.md第 3 周。
本章定位:理解通信库最终如何把工作交给 RNIC 执行。重点不是把 verbs API 背下来,而是知道 MR、QP、WQE、CQE、GID、MTU、QP 数这些对象如何影响性能和可观测性。
0. 这一周到底学什么
第 1 周你已经知道 collective 会被通信库拆成 channel/chunk,然后交给底层通信路径。第 3 周要回答:
通信库真正把数据交给网卡时,发生了什么?
RDMA/RoCE 和普通 socket 最大的不同是:应用不是每次 send() 都走内核复制数据,而是预先建立一组对象,然后把 work request 放进队列,让 RNIC 异步执行。
学完你要能回答:
- MR 为什么要注册和 pin memory?
lkey、rkey解决什么问题?- QP 是什么?为什么一个 QP 不只是“一条连接”?
- WQE/CQE 分别表达什么?
- RDMA write/read/send/recv 有什么区别?
- 为什么 RDMA fast path 可以少 syscall,但不是完全不需要 CPU/内核/驱动?
- 为什么 QP 数变化可能同时影响 RNIC 并发和 ECMP hash?
- 为什么
ib_write_bw快,不等于 MCCL AllReduce 快?
本周核心心智模型:
应用/通信库 post work request;
RNIC 根据 QP/MR 执行 DMA 和网络传输;
完成事件通过 CQE 返回;
软件继续 poll 和推进状态机。1. RDMA 和普通 socket 的直觉差异
1.1 普通 socket 粗略模型
普通 TCP/UDP 发送可以粗略理解为:
应用 buffer
↓ send syscall
内核协议栈
↓ copy / skb / qdisc / driver
网卡
↓
网络这里内核参与很多:协议栈、缓冲、调度、copy、系统调用。
1.2 RDMA 粗略模型
RDMA 的目标是让数据搬运更接近:
应用预先注册内存
↓
应用把 work request 放进设备队列
↓
RNIC 直接 DMA 读写内存
↓
网络传输
↓
RNIC 写入远端内存或完成接收这不代表没有内核,而是把 fast path 做得更靠近用户态和设备。
1.3 “绕过内核”这句话的边界
常见说法:
RDMA bypass kernel更准确地说:
数据传输 fast path 尽量不为每个 packet 走 syscall 和内核协议栈;
但资源创建、权限隔离、内存注册、设备管理、错误处理仍需要内核和驱动。所以如果看到 CPU/proxy/polling 异常,不能说“RDMA 不用 CPU,所以无关”。
2. verbs 对象总图
一个简化 RDMA 程序通常涉及这些对象:
Device / Context
↓
Protection Domain (PD)
↓
Memory Region (MR)
↓
Completion Queue (CQ)
↓
Queue Pair (QP)
↓
Work Queue Entry (WQE)
↓
Completion Queue Entry (CQE)可以画成:
应用 / 通信库
│
│ register memory
▼
MR: addr + length + lkey/rkey
│
│ create QP, CQ
▼
QP: Send Queue + Receive Queue
│
│ post WQE
▼
RNIC 执行 DMA / packet / retry / completion
│
│ write CQE
▼
CQ: 软件 poll 完成事件你不需要一开始记住所有 API 参数,但要知道这些对象的位置。
3. MR:为什么内存要注册
3.1 MR 是什么
MR = Memory Region,表示一段允许 RNIC 访问的内存区域。
注册 MR 大致做几件事:
1. 告诉内核和驱动这段内存要给 RNIC 用;
2. pin 住页面,避免传输中被换出或移动;
3. 建立 RNIC 可以使用的地址映射;
4. 生成访问 key:lkey / rkey。3.2 为什么不能直接给 RNIC 一个指针
普通指针是进程虚拟地址:
0x7f....但 RNIC 做 DMA 需要稳定、可访问的物理/I/O 地址映射。如果操作系统在传输中把页面换出、迁移或回收,RNIC 就会写错地方。
所以必须注册和 pin。
3.3 lkey 和 rkey
粗略理解:
lkey:本地 RNIC 访问本地 MR 时使用的权限 key
rkey:远端 RNIC 访问这段 MR 时需要的权限 key如果你要做 RDMA write 到远端内存,远端需要把地址和 rkey 告诉你。
3.4 GPU memory 的特殊性
如果 buffer 在 GPU 上,GDRDMA 还需要:
GPU memory 可被 RNIC DMA;
GPU driver / RNIC driver / IOMMU 支持;
GPU 和 HCA 拓扑可达;
内存注册和 cache/coherency 语义正确。这就是为什么 GPU↔HCA 亲和也可能影响性能。
3.5 小 case:MR 问题会表现成什么
MR/GDRDMA 路径问题可能表现为:
建连成功但传输失败;
小消息正常大消息异常;
某些 GPU/HCA 组合慢;
回退到 host staging 后性能下降;
注册开销导致短消息性能差;
错误日志里出现 access error / protection error。所以不要只看“网络连通”。
4. QP:通信上下文和并发单元
4.1 QP 是什么
QP = Queue Pair,一对队列:
Send Queue (SQ)
Receive Queue (RQ)应用把 work request post 到 SQ/RQ,RNIC 执行后把完成写到 CQ。
4.2 QP 状态机
可靠连接 RC QP 通常要经历:
RESET → INIT → RTR → RTS建连需要双方交换:
QP number
PSN
GID / LID
MTU
其他路径属性所以 QP 不只是“开个端口”,它包含 RDMA transport 的状态。
4.3 QP 类型
常见类型:
RC:Reliable Connected,可靠连接
UC:Unreliable Connected
UD:Unreliable Datagram大多数你关心的可靠 RDMA 数据传输会先从 RC 心智模型理解。
4.4 QP 数为什么会影响性能
QP 数可能同时影响多个层:
RNIC 内部并发;
WQE 排队;
CQ polling 压力;
retry / flow control 状态;
RoCEv2 UDP source port / flow entropy;
ECMP hash 分布;
通信库 channel 到 QP 的映射;
CPU/proxy thread 工作量。这就是为什么“多 QP 后变快”不能直接等于“ECMP 碰撞被解决”。它也可能是 RNIC 并发或通信库调度变了。
4.5 小 case:1 QP vs 8 QP
实验:
固定 src/dst host
固定 rail
固定 message size
固定并发 pair 数
只改变 QP 数:1 → 8结果:
1 QP: 12GB/s
8 QP: 23GB/s可能解释:
- 8 QP 增加 ECMP entropy,分散到更多 path;
- 8 QP 提高 RNIC 内部并发;
- 1 QP 被某个队列/credit/retry 限制;
- 通信库 channel 映射随 QP 变化;
- 接收端 CQ polling 更有效或更差;
- 测量噪声/背景流量变化。
要区分,需要:
实际 UDP source port;
交换机 per-uplink bytes;
RNIC QP counter;
CQE/retry/CNP counter;
多次随机 seed 复测;
负对照 pair。5. WQE/CQE:异步执行模型
5.1 WQE 是什么
WQE = Work Queue Entry。它告诉 RNIC 要做什么:
从哪个 MR 读;
写到哪里;
长度多少;
使用哪个 lkey/rkey;
操作类型是 send/write/read/atomic;
是否需要 completion。5.2 CQE 是什么
CQE = Completion Queue Entry。RNIC 执行完或失败后,在 CQ 里写完成事件。
success
error
byte length
work request id
status5.3 post 时间不等于完成时间
软件 post WQE 很快:
应用把任务放进队列但真正完成要等:
RNIC 取 WQE;
DMA 读本地数据;
网络传输;
远端处理;
ACK/完成;
CQE 写回;
软件 poll 到 CQE。所以 benchmark timing 必须明确测的是 post 时间、poll 完成时间,还是全局同步时间。
5.4 小 case:为什么 timing 修正很重要
如果一个脚本只测:
post isend 的时间可能得到很小时间。
但真实数据还在 RNIC/网络里飞,直到:
wait / synchronize / poll completion才算完成。
Muxi 主计划里 W0.1 timing 修正就是为了避免这种误判。
6. RDMA 操作语义:send/recv、write、read、atomic
6.1 send/recv
send/recv 像消息传递:
发送端 post send
接收端必须提前 post recv如果接收端没有准备好,可能出现 RNR 等问题。
6.2 RDMA write
发送端直接把数据写入远端已授权的 MR:
local MR → network → remote MR远端 CPU 不一定参与 data path,但远端需要提前交换地址和 rkey。
6.3 RDMA read
发送端主动从远端 MR 读取数据:
remote MR → network → local MRread 对延迟、credit、远端响应路径敏感。
6.4 atomic
远端原子操作,例如 compare-and-swap、fetch-and-add。常用于同步,不是大流量数据搬运主力。
6.5 通信库封装后的边界
当你用 torch.distributed.isend/irecv 或 MCCL collective 时,你不一定能直接知道底层用的是 RDMA write/read/send/recv 的哪种组合。
所以正确说法是:
应用层 API 是 isend/irecv 或 AllReduce;
底层 RDMA verb 语义需要通过通信库文档、debug 日志、抓包或厂商支持确认。7. perftest 和通信库 benchmark:测的不是同一层
7.1 ib_write_bw 测什么
ib_write_bw 通常测两个 RDMA 端点之间的 write bandwidth。它负载简单、变量少:
一个或多个 QP;
固定消息大小;
固定 RDMA operation;
固定端点。它适合回答:
这条 RDMA path 在简单负载下能不能跑起来?
单 rail / 单 QP / 多 QP 的基线是多少?
MTU、GID、QP 数变化有什么影响?7.2 MCCL AllReduce 测什么
AllReduce 测的是:
多 rank;
多阶段;
多 channel;
GPU kernel;
rank mapping;
同步尾部;
网络路径;
通信库算法。所以 perftest 快,只能说明底层简单 RDMA 路径健康,不代表 collective 一定快。
7.3 小 case:perftest 24GB/s,AllReduce 5GB/s
可能解释:
简单 RDMA 单流路径没问题;
AllReduce 的多 rank 多阶段触发了 ECMP/queue/rail/channel/tail 问题;
通信库算法或 rank mapping 不理想;
每节点注入模式不同;
背景流量只在大规模同步时显现。这不是矛盾,而是不同层级基准提供不同证据。
8. 和 Muxi 现象的关系
Muxi 的 W2/W4 中多次涉及 QP/channel/rail/GPU 映射。第 3 周给你一个判断框架:
channel 改变 → 可能改变 QP/flow/RNIC 并发/rail 映射
rail 掩码改变 → 可能改变 HCA、GID、ECMP group、物理路径
GPU 集合改变 → 可能改变 GPU-HCA 亲和、NUMA、通信库 rank mapping因此,任何一个 A/B 结果都要问:
这次只改变了一个因素吗?
它在 verbs/RNIC 层改变了什么?
它在网络 ECMP 层改变了什么?
它在通信库 channel 层改变了什么?最终报告说 MCCL/本地软件映射是参与因素,但不是已证实单一根因。这个判断是合理的,因为 QP/channel/rail 这些变量跨层耦合太强。
9. 推荐阅读提炼
9.1 Linux userspace verbs
一句话
userspace verbs 解释用户态程序如何通过 verbs 接口和 RDMA 设备交互。
抓哪个问题
RDMA 为什么可以减少 per-packet syscall?
为什么 fast path 快,但资源管理仍需要内核?和 Muxi 的关系
当你看到 CPU/proxy/polling 相关问题时,不要说“RDMA 绕过内核所以 CPU 无关”。RDMA 只是让数据 fast path 更靠近设备,通信库仍需要软件推进。
9.2 RDMA Aware Networks Programming Manual
一句话
这是学习 PD、MR、CQ、QP、WR、SGE 等对象的基础手册。
抓哪个问题
一个 RDMA 程序创建和使用对象的顺序是什么?最小顺序:
open device
alloc PD
register MR
create CQ
create QP
exchange QP info
modify QP to RTS
post WQE
poll CQE和 Muxi 的关系
MCCL 把这些细节封装了,但 debug 时你仍然需要问:QP 数是多少?CQ polling 在哪里?MR/GDRDMA 是否生效?
9.3 rdma-core ibv_rc_pingpong
一句话
ibv_rc_pingpong 是理解 RC QP 建连和最小收发的经典例子。
抓哪个问题
两端如何交换 QP number、PSN、GID?
QP 状态如何从 INIT 到 RTR 到 RTS?小 case
如果 GID index 或 MTU 不一致,可能不是“网络带宽低”,而是 QP 根本没正确进入可通信状态,或者走了错误路径。
9.4 perftest
一句话
perftest 提供 ib_write_bw、ib_read_bw、ib_send_bw 等简单 RDMA 负载,用来建立底层基线。
抓哪个问题
在不引入 collective 的情况下,单 RDMA operation 的路径能跑多快?不能照搬
perftest 是低层对照,不是训练/AllReduce 性能预测器。
10. 常见误判
- RDMA 完全不需要 CPU、内核或驱动。
- GDRDMA 正常就说明网络不会慢。
- QP 数影响带宽,就一定是 ECMP。
ib_write_bw快,就代表 AllReduce 应该快。- CQE 成功就说明没有队列、重传、拥塞或尾部问题。
- post WQE 的时间就是传输完成时间。
- 通信库 API 名字能直接告诉你底层 verb 操作。
11. 本周任务设计
11.1 任务 A:画 verbs 对象依赖图
画出:
context → PD → MR/CQ/QP → WQE → CQE并说明每个对象解决什么问题。
11.2 任务 B:解释 MR/lkey/rkey
用人话解释:
为什么 RNIC 不能随便读写进程指针?
lkey 和 rkey 的权限边界是什么?
GPU memory 注册有什么额外复杂性?11.3 任务 C:QP 数 A/B 辨析
假设:
1 QP: 12GB/s
8 QP: 23GB/s列出至少 6 个可能原因,并标注哪些属于 RNIC,哪些属于 ECMP,哪些属于通信库。
11.4 任务 D:perftest vs AllReduce
写一段解释:
为什么 ib_write_bw 快,不能反证 MCCL AllReduce 慢?12. 和 agent 讨论的问题模板
12.1 QP/RNIC 拆解
请把这个带宽变化拆成 RNIC/QP/CQ、ECMP、通信库 channel、GPU-HCA 亲和四类候选。
每类说明需要什么日志或实验才能区分。12.2 verbs 语义确认
请根据现有脚本判断它测的是 RDMA write/read/send/recv 中哪类语义,还是被通信库封装后无法直接判断。
列出需要补充的低层证据。12.3 perftest 对照
我想用 perftest 给 Muxi 建立底层 RDMA 基线。
请设计单 rail、单 QP、多 QP、不同 message size、不同 MTU/GID 的只读/低风险实验矩阵,并说明它不能证明什么。13. 本周最小掌握清单
- MR 是授权和固定内存:RNIC 不能随便读写进程指针。
- QP 是通信上下文:它有状态、队列和传输语义。
- WQE/CQE 是异步模型:post 不等于完成。
- QP 数跨层耦合:可能同时影响 RNIC 并发、ECMP hash、通信库 channel。
- perftest 是低层基线:不能直接预测 collective。
- RDMA fast path 不等于没有 CPU:软件仍要 post、poll、管理资源。
14. 本周结束时你应该能解释的一段话
如果有人问:
“多 QP 后带宽变好,是不是就证明 ECMP hash 用了 UDP 源端口?”
你应该能回答:
不能直接证明。多 QP 可能改变 RoCEv2 flow entropy,从而影响 ECMP 分布;但它也可能提高 RNIC 内部并发、改变 WQE/CQ 排队、改变通信库 channel 到 QP/HCA 的映射,或者改变接收端处理压力。
要证明 ECMP 机制,需要观察实际 UDP 源端口、交换机 ECMP group、逐上行端口 bytes,以及多 seed 复测。没有这些,只能说结果支持“QP/flow entropy 相关”的行为假设。15. 进阶总图:一次 RDMA write 具体经历什么
用一个最小 RDMA write 来把本周概念串起来。
15.1 准备阶段
两端先准备资源:
发送端:
open device
alloc PD
register local MR
create CQ
create QP
接收端:
open device
alloc PD
register remote MR
create CQ
create QP然后交换连接信息:
QP number
GID / LID
PSN
MTU
remote addr
rkey接着 QP 状态切换:
RESET → INIT → RTR → RTS只有到 RTS,QP 才真正 ready to send。
15.2 执行阶段
发送端 post 一个 RDMA write WQE:
operation = RDMA_WRITE
local addr = local MR address
local lkey = xxx
remote addr = remote MR address
remote rkey = yyy
length = N bytesRNIC 执行:
读取本地 MR
↓
生成 RoCE packet
↓
通过 Ethernet/IP/UDP 网络发送
↓
远端 RNIC 校验 rkey 和地址
↓
写入远端 MR
↓
返回完成/ACK
↓
本地 CQ 出现 CQE15.3 这条路径上可能慢在哪里
MR 注册开销;
GPU memory 到 RNIC DMA 路径;
QP send queue 堵;
RNIC 调度;
PCIe/NUMA;
RoCE packet 在 ECMP 上撞路径;
交换机 queue;
PFC/ECN/CNP;
远端写入路径;
CQ polling 不及时;所以 RDMA write 看起来是“网卡直接写远端内存”,但性能仍然跨越 GPU、CPU、RNIC、网络和远端内存路径。
16. 进阶辨析:QP、connection、flow、channel 不是一回事
这几个词很容易混。
16.1 QP
QP 是 RDMA transport 上的队列对和状态机。
它包含:
SQ/RQ;
QP number;
状态;
PSN;
访问属性;
路径属性;16.2 connection
connection 是更高层的通信关系。一个 peer pair 之间可能有一个或多个 QP。
rank A ↔ rank B
├─ QP0
├─ QP1
└─ QP216.3 flow
网络里的 flow 通常由 header 字段定义:
src IP, dst IP, protocol, src port, dst port, ...一个 QP 可能对应一个或多个网络 flow,具体取决于 RoCE UDP source port、实现和封装。
16.4 channel
channel 是通信库内部并行车道。一个 channel 可能映射到一个或多个 QP,也可能多个 channel 共享某些 QP/HCA。
16.5 为什么这个辨析重要
如果你看到:
channel 数增加后带宽变好不能直接说:
ECMP flow 变多了。中间可能是:
channel 增加 → QP 增加 → UDP source port 增加 → ECMP entropy 增加也可能是:
channel 增加 → RNIC 并发提高或者:
channel 增加 → GPU kernel pipeline 改变如果没有实际 QP 和 packet header 证据,就不能跳过中间环节。
17. 进阶 case:RNR、retry、CQ error 怎么进入性能分析
RDMA 不是只有成功/失败,也有很多中间状态会表现为慢。
17.1 RNR:Receiver Not Ready
send/recv 语义下,接收端要提前 post recv。如果没有 recv buffer,发送端可能遇到 RNR。
表现可能是:
传输没有立即失败;
但等待重试;
延迟和尾部变高;17.2 retry
可靠传输遇到丢包、NACK 或超时,可能重传。
表现:
带宽下降;
尾部增加;
RNIC retry counter 增加;17.3 CQ error
CQE 里可能返回错误状态,例如 protection error、remote access error、timeout 等。
如果只看应用层 benchmark 输出,可能看不到完整原因。
17.4 和 Muxi 的关系
如果怀疑链路错误、QoS 或拥塞控制,应该尽量拿:
RNIC retry counter;
timeout / error CQE;
CNP counter;
packet drop;
CRC/FEC;只看 bandwidth 不足以区分。
18. 进阶 case:GDRDMA 路径为什么也可能有亲和问题
18.1 GPU、CPU、PCIe、RNIC 不是均匀全互联
一台机器里可能有:
GPU0 更靠近 HCA0;
GPU7 更靠近 HCA3;
某些 GPU 到某些 HCA 要跨 PCIe switch 或 NUMA;如果通信库把 GPU0 的数据主要走 HCA3,可能不如走 HCA0。
18.2 这会怎么表现
同一 host 上不同 GPU 集合性能不同;
同一 rail 对不同 GPU 表现不同;
单机/跨机差异;
GPU 顺序 A/B 有影响;18.3 不能直接下的结论
看到 GPU 集合影响性能,不能直接说:
某张 GPU 坏了。它可能是:
GPU-HCA 亲和;
PCIe/NUMA;
通信库 rank mapping;
rail 选择;需要 GPU↔HCA topo、实际 HCA bytes 和复测。
19. perftest 该怎么设计才有信息量
19.1 不要只跑一个数字
只跑:
ib_write_bw A B得到 24GB/s,信息量有限。
更有用的是矩阵:
operation: write / read / send
message size: 4KiB / 64KiB / 1MiB / 16MiB / 256MiB
QP: 1 / 2 / 4 / 8
rail: xscale_0 / xscale_1 / xscale_2 / xscale_3
direction: A→B / B→A
repeat: 多次19.2 每个维度回答什么
operation:区分 write/read/send 语义差异;
message size:区分 latency 和 throughput;
QP 数:区分并发/entropy;
rail:区分 HCA/路径;
direction:区分方向性慢;
repeat:区分稳定问题和间歇问题;19.3 和 collective 的关系
perftest 是底层基线:
如果 perftest 都慢,collective 慢不意外;
如果 perftest 快,collective 仍可能慢;第二种情况说明问题可能出现在:
通信库调度;
rank mapping;
多流并发;
collective 同步;
网络聚合;19.4 安全边界
在真实集群里,perftest 也可能制造大流量。要控制:
节点数;
并发数;
消息大小;
持续时间;
结果目录;
停止条件;Muxi 规则里实验类要先 verify/probe,不盲目起大作业。
20. 推荐阅读进一步拆解:怎么读 verbs 材料
20.1 读 userspace verbs 时,重点看“fast path 和 control path”
不要只记住 “bypass kernel”。要画出:
control path:创建 PD/MR/CQ/QP,注册内存,权限管理
fast path:post WQE,RNIC 执行,poll CQE然后问:
当前问题发生在 control path 还是 fast path?例如:
第一次 iteration 慢 → 可能 control path/lazy init/MR
稳态每轮慢 → 可能 fast path/network/queue20.2 读 RDMA Aware Programming Manual 时,重点看对象依赖
可以做这张表:
对象 解决什么问题 出问题可能表现
PD 资源隔离 权限/访问错误
MR 授权内存给 RNIC 注册失败/访问错误/性能回退
CQ 完成事件 poll 不及时/完成延迟
QP 通信上下文 建连失败/重试/性能差
WQE 发给 RNIC 的任务 post 快但完成慢
CQE 完成/错误状态 成功/错误/超时20.3 读 ibv_rc_pingpong 时,重点看连接建立
你要关注:
双方交换了哪些字段?
GID/MTU/PSN/QPN 在哪里出现?
QP 状态如何切换?这会帮助你理解为什么 GID index 或 MTU 错误可能导致奇怪行为。
20.4 读 perftest 时,重点看实验变量
不要只把 perftest 当成测速命令。要看它能控制:
message size;
QP 数;
operation type;
inline;
MTU;
GID index;
report units;这些变量可以帮你构造低层对照。
21. 本周自测题:带答案方向
21.1 为什么 MR 需要 pin memory?
答案方向:
RNIC 做 DMA 需要稳定可访问的地址映射。普通虚拟内存可能被换出或移动,所以要注册和 pin,并生成 lkey/rkey 做权限控制。21.2 QP 数增加后带宽变好,为什么不能直接证明 ECMP?
答案方向:
QP 数增加可能改变 ECMP entropy,也可能改变 RNIC 并发、WQE/CQ 排队、通信库 channel 映射和 CPU/proxy 压力。需要 UDP port、交换机 bytes、QP counter 等证据。21.3 ib_write_bw 快,为什么 AllReduce 仍可能慢?
答案方向:
ib_write_bw 是简单 RDMA operation 基线;AllReduce 是多 rank、多阶段、多 channel、同步 collective,会触发并发、mapping、ECMP、queue 和 tail 问题。21.4 post WQE 快,为什么传输不一定快?
答案方向:
post 只是把任务放进队列;真正完成还需要 RNIC 执行、网络传输、远端处理、ACK/完成和 CQ polling。21.5 GPU 集合影响性能,为什么不能直接说 GPU 坏?
答案方向:
可能是 GPU-HCA 亲和、PCIe/NUMA、rank mapping、rail 选择或通信库调度造成,需要 topology 和 per-HCA bytes 支持。