RDMA Tutorial
Jana Giceva, Large-Scale Data & Systems (LSDS) Group, Imperial College London
目录
- RDMA 简介
- RDMA 的优势
- RDMA 核心机制
- RDMA 通信模型
- 使用与挑战
- 附录与参考
1. RDMA 简介
什么是 RDMA?
RDMA (Remote Direct Memory Access) 即远程直接内存访问。
它是一种硬件机制,通过该机制,网络接口卡 (NIC) 可以直接访问远程节点主存的全部或部分内容,而无需处理器参与。
RDMA 概念图,展示了两个节点上的应用通过 NIC 直接访问对方的内存缓冲区,绕过了操作系统和 CPU。
RDMA 的属性
- 远程 (Remote) - 数据在网络中的节点之间传输。
- 直接 (Direct) - 数据传输不涉及 CPU 或操作系统内核。
- 内存 (Memory) - 数据在两个应用程序及其虚拟地址空间之间传输。
- 访问 (Access) - 支持发送 (send)、接收 (receive)、读取 (read)、写入 (write) 以及原子操作。
RDMA 的主要亮点:
- 零拷贝数据 (Zero-copy data)
- 绕过 CPU
- 绕过操作系统内核
- 基于消息的事务
2. RDMA 的优势
使用 RDMA 带来的好处包括:
- 高吞吐量 (带宽)
- 低端到端延迟
- 低 CPU 使用率
- 单边 (One-sided) RDMA 操作完全不涉及远程 CPU。
- 低内存总线争用
- 数据不在用户空间和内核之间来回复制。
- 异步操作
- 非常适合将通信与计算重叠进行。
与传统 TCP/IP 套接字的对比
与传统的 TCP/IP 协议栈不同,RDMA 的 Verbs API 为应用程序提供了一个直接的数据通道,绕过了内核网络协议栈,从而实现了高性能。
传统 TCP/IP 协议栈与 RDMA 协议栈的对比图。
3. RDMA 核心机制
建立 RDMA 数据通道
在使用缓冲区之前,必须将其注册 (registered) 到网卡。
在注册过程中:
- 固定内存 (Pin memory),使其不能被操作系统交换出去。
- 将地址转换信息存储在 NIC 中。
- 设置内存区域的权限。
- 返回一个远程 (remote) 和本地 (local) 密钥 (key),适配器在执行 RDMA 操作时会使用这些密钥。
工作队列 (Work Queues)
RDMA 通信基于一组三个队列:
- 发送队列 (Send)
- 接收队列 (Receive)
- 完成队列 (Completion)
发送和接收队列总是成对创建,称为队列对 (Queue Pair, QP)。发送和接收队列用于调度待完成的工作。完成队列则用于通知工作何时已完成。
队列元素 (Queue Elements)
应用程序通过工作请求 (work request) 或工作队列元素 (work queue element, WQE) 来发布任务。
工作请求是一个小型的 struct,包含一个指向缓冲区的指针:
- 在发送队列中,它指向待发送的消息。
- 在接收队列中,它指明了传入消息应被放置的位置。
当一个工作请求完成后,适配器会创建一个完成队列元素 (completion queue element),并将其放入完成队列中。
RDMA 网络栈概览
- 应用程序 (Application)
- 向队列提交工作请求。
- 每个工作请求是一个消息,一个工作单元。
- RDMA 适配器驱动 (RDMA adapter driver)
- Verbs 接口:允许应用程序请求服务。
- 维护工作队列。
- 管理地址转换。
- 提供完成甚至事件机制。
- 支持 RDMA 的 NIC 和网络协议
- 传输层:可靠/不可靠、数据报等。
- 将消息分包。
- 实现 RDMA 协议。
- 实现端到端可靠性。
- 确保可靠交付。
支持 RDMA 的网络协议
- InfiniBand (IB)
- QDR 4x – 32 Gbps
- FDR 4x – 54 Gbps
- EDR 4x – 100 Gbps
- RoCE – RDMA over Converged Ethernet
- iWARP – internet Wide Area RDMA Protocol
4. RDMA 通信模型
RDMA 本身只是一种机制,它不规定数据传输的语义。RDMA 网络支持两种类型的内存访问模型:
- 单边 (One-sided) - RDMA 读 (read)、写 (write) 和原子操作。
- 双边 (Two-sided) - RDMA 发送 (send) 和接收 (receive)。
双边操作:RDMA 发送和接收 (Send and Receive)
这是一种传统的消息传递模式,其中源 (source) 和目标 (destination) 进程都主动参与通信。
- 双方都需要创建它们的队列:
- 一个由发送和接收队列组成的队列对 (queue pair)。
- 一个用于该队列对的完成队列 (completion queue)。
- 发送方 (Sender) 的工作请求包含一个指向其希望发送的缓冲区的指针。该 WQE 被放入发送队列。
- 接收方 (Receiver) 的工作请求包含一个指向用于接收消息的空缓冲区的指针。该 WQE 被放入接收队列。
RDMA Send 示例流程
-
系统 A(发送方)和系统 B(接收方)都准备好各自的队列和已注册的内存区域。发送方准备好要传输的数据缓冲区,接收方准备好用于存放数据的空缓冲区。
RDMA 发送操作的初始状态,显示了系统A和系统B各自的队列和内存。
-
发送方将一个工作请求(指向数据缓冲区)放入其发送队列。接收方将一个工作请求(指向空缓冲区)放入其接收队列。
工作请求被放入发送和接收队列。
-
NIC 处理队列中的请求,数据从系统 A 的内存直接传输到系统 B 的内存。
数据通过网络从系统A的注册内存传输到系统B的注册内存。
-
传输完成后,NIC 在两边的完成队列中各放入一个完成通知。
传输完成后,完成队列中出现通知。
单边操作:RDMA 读取和写入 (Read and Write)
在这种模式下,只有发送方 (sender) 是主动的,而接收方 (receiver) 是被动的。
- 被动方不发出任何操作,不消耗 CPU 周期,也不会收到关于“读”或“写”发生的指示。
- 要发起 RDMA 读或写操作,工作请求必须包含:
- 远程端的虚拟内存地址。
- 远程端的内存注册密钥。
- 主动方必须事先通过其他方式(通常使用传统的 RDMA 发送/接收机制)获取被动方的地址和密钥。
5. 使用与挑战
使用 Verbs API
Verbs API 是用于 RDMA 编程的底层接口。下图展示了使用 Verbs API 建立连接并执行 RDMA 写入操作的典型流程。该流程包括初始化上下文、分配资源、交换连接信息、修改队列对状态以建立连接,以及最终的数据传输。
使用 Verbs API 进行 RDMA 通信的序列图,展示了从初始化到数据写入的完整步骤。
使用 RDMA 的挑战
直接使用 Verbs API 给开发者带来了额外的复杂性。因此,在实际应用中,通常会使用构建在 RDMA 之上的上层协议和系统来简化开发。
RDMA 技术栈,展示了上层协议如 MPI、NFS RDMA 如何封装底层的 RDMA 驱动和 IB Fabric Interconnect。
- MPI : Message Passing Interface
- 在高性能计算(HPC)中广泛使用。
- 示例:OpenMPI, MVAPICH, Intel MPI 等。
- 文件系统 (File Systems):
- Lustre – 面向 Linux 的并行分布式文件系统。
- NFS_RDMA – 基于 RDMA 的网络文件系统。
6. 附录与参考
参考资料
新 EDR 集群概览
- EDR InfiniBand
- 36 端口 Mellanox 交换机
- 18 节点集群 (EDR NICs)
- 1 台服务器,配备 4 颗 Xeon E5-5660 v4 处理器:
- 64 核 (启用 HT 后 128 核)
- 512 GB RAM
- 2 个 EDR NICs, 1 个 10G NIC, 1 个 1G NIC
- 8 台服务器,配备 2 颗 Xeon E5-2630 v4 处理器:
- 20 核 (启用 HT 后 40 核)
- 32 GB RAM
- 2 个 EDR NICs