在 RDMA 系统中,一个非常典型的通信模式是:
RDMA Write
↓
RDMA Write
↓
RDMA Write-with-Immediate
↓
Remote CQE(Remote CQE 不会再发回 Server A)它的设计思想非常简单:
先把数据写到远端内存,再通过 Write-with-Immediate 告诉远端:“数据已经准备好了,可以用了。”
例如:
Sender Receiver
│ │
│ RDMA Write: 4 MB Tensor │
├────────────────────────────────────────────>│ Remote Buffer
│ │
│ Write-with-Immediate: READY │
├────────────────────────────────────────────>│
│ │
│ Generate CQE
│ │
│ Application wakes up
│ │
│ Read 4 MB Tensor
这个机制看起来简单,但对传统 RNIC 来说,实际上提出了一个非常重要的要求:
RNIC 必须保证:在远端应用收到 Write-with-Immediate 的 Completion Notification 之前,前面的 RDMA Write 数据已经按照要求到达并对远端可见。
否则就会出现严重的数据一致性问题。
1. 为什么需要 Write-with-Immediate
普通 RDMA Write 的特点是:
Sender
│
│ RDMA Write
▼
Remote Memory数据可以直接写进远端内存。
但有一个问题:
远端 CPU 怎么知道这次 Write 已经完成?
普通 RDMA Write 通常不会主动给远端应用生成一个 Receive Completion。
因此可能出现:
Remote Buffer
什么时候更新完成?
CPU:不知道一种方式是让 CPU 不停 Poll:
while (buffer->flag != READY) {
// spin
}但这样效率不高。
因此 RDMA 提供了:
RDMA Write with Immediate它同时完成两件事情:
Write-with-Immediate
Sender RNIC
│
├─────────────── Data ──────────────→ Remote Memory
│
└──────── Immediate Data ───────────→ Remote CQ也就是说:
写入远端 Memory;
在远端产生 Completion;
CQE 中携带一个 32-bit Immediate Data。
例如:
Immediate = 0x00000001可以解释为:
Tensor #1 is ready2. 为什么常见的是:
Write
↓
Write
↓
Write-with-Immediate而不是每次都使用 Write-with-Immediate?
假设需要传输一个 4 MB Tensor。
可以先:
WQE 1:
RDMA WRITE
Address = Buffer + 0 MB
Length = 1 MB
WQE 2:
RDMA WRITE
Address = Buffer + 1 MB
Length = 1 MB
WQE 3:
RDMA WRITE
Address = Buffer + 2 MB
Length = 1 MB
WQE 4:
RDMA WRITE
Address = Buffer + 3 MB
Length = 1 MB最后:
WQE 5:
RDMA WRITE WITH IMM
Immediate = READY于是接收端只需要收到一次通知:
CQE:
Immediate = READY就知道:
前面的 4 MB 数据全部完成因此 Write-with-Immediate 经常被当成一种:
Doorbell / Notification Mechanism
即:
Data
Data
Data
Data
↓
Doorbell3. 真正困难的问题:不能让“通知”跑到“数据”前面
假设 Sender 发:
WQE 1 = RDMA Write(DATA)
WQE 2 = Write-with-Immediate(READY)WQE(Work Queue Entry)软件交给 RNIC 的一张“工作指令单”
从应用程序角度看:
DATA
↓
READY但底层实际上有很多异步组件:
Application
│
▼
Send Queue
│
▼
RNIC Pipeline
│
▼
Network
│
▼
Remote RNIC
│
▼
PCIe
│
▼
Host Memory于是存在一个危险场景。
比如:
Packet carrying DATA
↓
Remote RNIC
↓
PCIe Write
↓
Host Memory与此同时:
Immediate packet
↓
Remote RNIC
↓
CQE如果 RNIC 不提供严格的排序保证,就可能出现:
Time ─────────────────────────────>
Immediate arrives
│
▼
CQE generated
│
▼
CPU reads buffer
DATA DMA still in progress
↓
Memory updated
于是 CPU 会读到:
Old Data
而不是:
New Data这显然是不允许的。
所以传统 RNIC 必须实现:
Data-before-Notification ordering
4. 第一层保证:Send Queue WQE Ordering
假设:
SQ(在 RDMA 里,SQ 和 RQ 是一个 QP(Queue Pair)里的两条工作队列)
# 一个 QP = 一条发送队列 SQ + 一条接收队列 RQ,再加上一套通信状态。
WQE #100
RDMA Write
WQE #101
RDMA Write
WQE #102
Write-with-Immediate对于同一个可靠连接 QP,例如:
RC QPRNIC 必须按照 WQE 的顺序处理。
逻辑关系为:
WQE 100
↓
WQE 101
↓
WQE 102不能变成:
WQE 102
↓
WQE 100
↓
WQE 101 因此 RNIC 内部需要维护:
QP Context
│
├── SQ Producer Index
├── SQ Consumer Index
├── Current WQE
├── PSN
├── Outstanding Requests
└── Completion State
这些状态通常就需要占用 RNIC 的片上 SRAM。
5. 第二层保证:Packet Sequence Number
一个大型 RDMA Write 不会只变成一个网络包。
例如:
1 MB RDMA Write可能被拆成:
Packet PSN 1000
Packet PSN 1001
Packet PSN 1002
...
Packet PSN 1200然后:
Write-with-Immediate可能继续使用:
PSN 1201形成:
PSN:
1000
1001
1002
...
1200
1201 ← Write-with-Immediate因此 Receiver RNIC 可以知道:
如果 1201 到了
但是 1199 没到
那么不能直接认为前面的数据已经完成对于传统 RC Transport:
Expected PSN = 1199
收到:
1201说明:
存在 Gap需要进行:
NAK
Retransmission
Recovery 因此 PSN 本质上提供了一套:
Transport-level ordering
6. 第三层保证:Remote RNIC 的 WQE/Packet 状态
真正复杂的是 Remote RNIC。
假设收到:
PSN 100
DATA
PSN 101
DATA
PSN 102
WRITE_WITH_IMMRemote RNIC 不能简单地:
收到 102
↓
马上生成 CQE而必须确保:
PSN 100
↓
DMA complete / visibility requirement satisfied
PSN 101
↓
DMA complete / visibility requirement satisfied
PSN 102
↓
Write-with-Imm completion
↓
CQE因此 RX RNIC 内部需要维护很多状态:
RC QP Context
Expected PSN
Last ACKed PSN
Current Message State
DMA State
Receive WQE State
Immediate State
CQ State所以:
Ordering并不是“网络天然就有”。
而是 RNIC ASIC 里大量状态机共同实现出来的。
7. 第四层:PCIe Ordering
这里开始进入真正的硬件问题。
Remote RNIC 收到数据之后,还要通过:
PCIe DMA把数据写进 Host DRAM。
例如:
RNIC
│
│ PCIe Memory Write
▼
Host DRAM所以完整链路其实是:
Network packet
↓
RNIC RX
↓
PCIe DMA
↓
Memory Controller
↓
DRAM与此同时,RNIC 还可能:
Generate CQE
↓
PCIe Write
↓
Completion Queue所以存在两类 PCIe Write:
A:
Data DMA
→ Remote Buffer
B:
CQE DMA
→ Completion Queue
关键要求是:
B 不能在语义上超越 A。
否则:
CQE visible
但
Data not yet visible应用就会读到旧数据。
因此 RNIC 必须利用:
PCIe ordering rules
DMA engine ordering
internal pipeline barriers
completion scheduling
确保:
DATA visibility
↓
CQE visibility8. 所以真正的 Write → Write-with-Imm 链条是
简化来看:
Sender Application
│
▼
┌─────────────────┐
│ Sender RNIC │
│ │
│ WQE 1 WRITE │
│ WQE 2 WRITE_IMM │
└────────┬────────┘
│
│ ordered packets
▼
┌─────────────────┐
│ Network │
│ │
│ PSN 100 │
│ PSN 101 │
│ PSN 102 │
└────────┬────────┘
│
▼
┌─────────────────────────┐
│ Receiver RNIC │
│ │
│ PSN checking │
│ Reassembly │
│ DMA scheduling │
│ Ordering state │
└──────────┬──────────────┘
│
│ PCIe DMA
▼
Remote Memory
│
│ data visible
▼
┌─────────────────────────┐
│ Receiver RNIC │
│ │
│ Generate CQE │
│ Immediate = READY │
└──────────┬──────────────┘
│
▼
Completion Queue
│
▼
Remote CPU
│
▼
Read Data最核心的顺序是:
Data Transfer
↓
Data Visibility
↓
Immediate Notification
↓
Application Access9. 为什么这个机制特别消耗 RNIC SRAM
这和现代 AI RNIC 论文讨论的:
hardware resource constraints
直接相关。
为了维护这种严格的可靠、有序传输,传统 RNIC 对每个 QP 都可能保存:
QP Context
───────────────────
SQ state
RQ state
Expected PSN
Send PSN
ACK state
Retry state
Timeout state
Outstanding WQEs
DMA state
Completion state
RDMA Read state
Atomic state
Write-with-Imm state假设一个 QP Context 需要:
几百 Byte如果支持:
1,000,000 QPs理论状态规模就可能达到:
数百 MB显然不能全部放在最昂贵的高速 SRAM 中。
因此传统 RNIC 经常需要复杂的:
On-chip SRAM Cache
+
Host DRAM Context层级。
10. 为什么 AI Cloud 给了 RNIC 新的优化机会
传统 RNIC 设计目标是:
General-purpose RDMA
因此必须考虑很多场景:
RDMA Write
RDMA Write-with-Imm
RDMA Read
Send
Receive
Atomic
Large number of QPs
Reliable Transport
Ordering
Retry
...但是 AI 网络的行为高度规律。
例如 AI Collective 可能大量使用:
RDMA Write
Send/Recv
Write-with-Immediate而某些复杂 Verbs 很少使用。
因此论文作者会问:
能不能减少:
Rare RDMA Verbs
Complex connection state
Some legacy semantics
↓
释放硬件资源
↓
增加:
Per-packet spraying
Credit state
Path state
Reordering
Congestion control这就是很多新型 AI RNIC 的设计哲学:
传统 RNIC:
更多“通用性”
↓
AI RNIC:
牺牲部分极少使用的通用能力
↓
换取更多:
Multipath
Congestion Control
Credit
Reordering11. Write-with-Immediate 和 Send/Receive 有什么区别?
这也是很容易混淆的一点。
SEND
Sender Buffer
│
│ SEND
▼
Receiver RNIC
│
▼
Receive BufferReceiver 必须提前:
Post Receive WQERDMA Write
Sender
│
│ WRITE
▼
Receiver MemorySender 直接指定:
Remote Address
rkey远端 CPU 不直接参与。
RDMA Write-with-Immediate
可以理解成:
RDMA Write
+
Remote Notification即:
Data
↓
Remote Memory
同时
Immediate
↓
Remote CQE因此它特别适合:
Data Plane
+
Doorbell这种设计。
12. 一个典型 AI / Storage 使用方式
例如 Sender 要把 Tensor 写给 Receiver:
Tensor = 64 MB可以:
WR 1
WRITE 16 MB
WR 2
WRITE 16 MB
WR 3
WRITE 16 MB
WR 4
WRITE 16 MB
WR 5
WRITE_WITH_IMM
IMM = Tensor_ID_123_READYReceiver 只需要 Poll CQ:
poll_cq();
if (wc.opcode == RDMA_WRITE_WITH_IMM &&
wc.imm_data == TENSOR_123_READY) {
process_tensor(buffer);
}而无需:
不停检查 64 MB Tensor 是否到齐13. 一个非常重要的边界:同一个 QP
这种 ordering 最容易保证的是:
Same RC QP例如:
QP 7:
WRITE A
↓
WRITE B
↓
WRITE_WITH_IMM存在明确的顺序关系。
但如果:
QP1:
WRITE DATA
QP2:
WRITE_WITH_IMM那么:
QP1 ─────────────→
QP2 ───────→两个 QP 在 RNIC 内部可能走不同:
Queue
Scheduler
Pipeline
Path此时不能简单依赖:
程序提交顺序推导:
远端可见顺序因此:
需要 ordering guarantee 时,应明确通信是否在同一个 QP/ordering domain 中。
14. Fence 也不要和这个问题混淆
RDMA 中还有:
IBV_SEND_FENCE但它不是简单地说:
“所有 WRITE 后面都必须加 Fence。”
Fence 主要用于某些前序操作,例如:
RDMA Read
Atomic存在返回数据/依赖关系时,约束后续 Work Request 的执行。
对于普通:
RDMA Write
↓
RDMA Write-with-Immediate在同一 RC QP 内,基本的发送顺序和可靠传输语义本身就非常关键。
所以不要把:
Write → Write-with-Imm ordering简单解释成:
靠 Fence 实现两者不是一回事。
15. 为什么 Per-Packet Spraying 会让这件事情变复杂?
传统 RNIC 假设:
一个 QP
↓
一条 ECMP Path所以:
P1 → Path A
P2 → Path A
P3 → Path A
P4 → Path A网络中的 packet 顺序相对容易维护。
但如果使用:
Per-packet spraying可能:
P1 → Path A ────────────────→
P2 → Path B ────────→
P3 → Path C ──────────→Receiver 实际收到:
P2
P3
P1这就直接打破了传统 RNIC 很重要的:
in-order packet arrival assumption而传统 Write → Write-with-Immediate 又要求:
DATA
↓
READY因此现代支持 packet spraying 的 RNIC 必须额外增加:
Out-of-order handling
↓
Packet tracking
↓
Selective retransmission
↓
Reordering
↓
Completion ordering才能最终保证:
即便 Packet Arrival 是:
P3 P1 P2 P5 P4
应用看到的语义依然是:
WRITE
↓
WRITE
↓
WRITE_WITH_IMM
↓
CQE这就是为什么:
Per-packet spraying 本身不难,“既 spraying 又保持 RDMA 原有语义”才是真正难的地方。
16. 一张图总结传统 RNIC 的工作
Application
│
│
│ WRITE
│ WRITE
│ WRITE_WITH_IMM
▼
┌────────────────────────────┐
│ Sender RNIC │
│ │
│ SQ Ordering │
│ WQE State │
│ PSN Allocation │
│ Retry State │
└──────────────┬─────────────┘
│
▼
Network
│
▼
┌────────────────────────────┐
│ Receiver RNIC │
│ │
│ PSN Checking │
│ In-order Processing │
│ DMA Ordering │
│ Write Visibility │
│ CQE Ordering │
└──────────────┬─────────────┘
│
┌──────┴──────┐
│ │
▼ ▼
Remote DRAM CQE
│ │
└──────┬──────┘
│
▼
Application
保证:
DATA visible
↓
READY notification总结
传统 RNIC 中:
RDMA Write
↓
RDMA Write-with-Immediate本质上是一种非常常见的:
Data + Doorbell
通信模型。
为了保证:
“收到 Doorbell”
=
“前面的数据已经可以安全使用”RNIC 必须维护:
WQE Ordering
+
PSN Ordering
+
Reliable Delivery
+
DMA Ordering
+
Memory Visibility
+
Completion Ordering因此传统 RNIC 需要大量:
QP state
Packet state
DMA state
Retry state
Completion state而这些状态最终会消耗宝贵的:
On-chip SRAM这也解释了为什么现代 AI RNIC 论文如此强调:
如何在保持传统 RDMA 语义的同时,引入 per-packet spraying、credit-based congestion control 和 out-of-order transport,而又不能让 RNIC SRAM 与状态复杂度爆炸。