RDMA 编程:点对点数据传输
大规模训练里最重的活是搬数据。Monarch 通过 RDMABuffer API 提供一等公民的 RDMA 支持:把"数据引用"与"数据搬运"彻底分离,让你按应用逻辑设计协调模式,而不是被框架的传输时机绑架。
1. 核心思想:引用与搬运分离
传统做法是把大张量塞进消息里发出去。Monarch 的做法是:
- 消息里只传轻量级的缓冲区引用(很小);
- 真正的批量数据在你显式要求时才搬运(很大)。
RDMA 传输基于 libibverbs,走 InfiniBand 或 RoCE。与 NCCL 集合通信"发送必须配对接收"不同:拿到缓冲区句柄的一方,可以不需要所有者参与,直接单边读或写。
2. RDMABuffer:不拷贝数据的视图
RDMABuffer 不复制数据,只是创建一个可传给其他进程的数据视图:
python
import torch
from monarch.actor import Actor, endpoint
from monarch.rdma import RDMABuffer
class ParameterServer(Actor):
def __init__(self):
self.weights = torch.rand(1000, 1000) # 大块模型权重
# RDMABuffer 不拷贝数据,只创建可传递的视图
self.weight_buffer = RDMABuffer(self.weights.view(torch.uint8).flatten())
@endpoint
def get_weights(self) -> RDMABuffer:
return self.weight_buffer # 小消息:只传一个引用!3. read_into:显式搬运
Worker 拿到引用后,控制面先取轻量引用,数据面再决定何时搬运:
python
class Worker(Actor):
def __init__(self):
self.local_weights = torch.zeros(1000, 1000)
@endpoint
def sync_weights(self, server: ParameterServer):
# 控制面:拿到轻量级引用(小消息)
weight_ref = server.get_weights.call_one().get()
# 数据面:需要时才显式批量传输
weight_ref.read_into(self.local_weights.view(torch.uint8).flatten()).get()把两端连接起来:
python
server_proc = this_host().spawn_procs(per_host={"gpus": 1})
worker_proc = this_host().spawn_procs(per_host={"gpus": 1})
server = server_proc.spawn("server", ParameterServer)
worker = worker_proc.spawn("worker", Worker)
worker.sync_weights.call_one(server).get()4. 参数服务器模式的完整图景
上面两段代码合起来就是一个极简参数服务器(Parameter Server):
text
ParameterServer Worker
│ │
│◄── get_weights.call_one() ─────│ 控制面:小消息
│ │
│── RDMABuffer 引用 ────────────►│ (几十字节)
│ │
│ (RDMA 单边读, │
│ weight_ref.read_into()) │ 数据面:8MB 直达显存
▼ ▼关键点:
- Server 的 endpoint 返回
RDMABuffer,没有把 8MB 权重塞进消息; read_into走 RDMA 单边传输,绕过两端 CPU;- Worker 可以在任何时刻发起同步,频率与时机完全由你的应用逻辑决定。
5. 使用须知
官方对 RDMABuffer 的定位是刻意保持底层:
- 它只做"被要求时的数据搬运";
- 调用方负责保证搬运完成前数据不被修改(否则读到中间状态);
- 更高级的库(张量传输、集合通信原语)将在这些原语之上构建。
这也是为什么教程把它放在高级篇:理解它,你才能理解 Monarch "控制平面/数据平面分离"的架构哲学(见《架构揭秘》)不是口号,而是落到了每一个 API 上。
6. 动手实验
官方仓库提供两个现成的实验材料:
docs/source/examples/getting_started.py:RDMA 章节(Parameter Server 示例);examples/rdma_pingpong/:RDMA 点对点传输基准测试,可用来测你网络的往返延迟与吞吐。
关键点
- 引用与搬运分离:消息传
RDMABuffer引用,数据走显式read_into; - 单边语义:拿到句柄即可读/写,无需所有者配合(对比 NCCL 的 send/recv 配对);
- 零拷贝:
RDMABuffer只是视图,不复制数据; - 底层原语:数据一致性由调用方负责,高级库在其上生长。
