RDMA 技术基于传统以太网的网络概念,但与以太网网络中的同类技术存在差异。关键区别在于,RDMA 提供了一种消息服务,应用程序可以使用该服务直接访问远程计算机上的虚拟内存。RDMA 通过绕过软件协议栈和避免不必要的数据复制来实现低时延、降低 CPU 占用率、减少内存带宽瓶颈和提供高带宽。RDMA 提供基于通道的 I/O,该通道使得应用程序可以使用 RDMA 设备直接读取和写入远程虚拟内存。
在传统的以太网应用场景中,运行在用户态的应用程序通过调用套接字(socket)API 从操作系统请求网络资源,然后使用这些 API 执行数据收发。RDMA 应用也依赖操作系统,但只是使用操作系统建立通道,而后允许用户态的程序直接操作硬件交互信息,无须内核态程序的进一步协助。这些信息交互方式可以是 RDMA Read、RDMA Write、Send 和 Receive。另外,RDMA协议 InfiniBand 和 RoCE 还支持多播传输。
目前 RDMA 已经是一个比较成熟的架构,主要应用在高性能计算(HPC)领域和大型数据中心中,典型的应用场景包括分布式神经网络计算(比如 TensorFlow+MPI+RDMA)和大数据存储(比如 HDFS+RDMA+NVMe)等。
一、RDMA的控制通路和数据通路
RDMA的控制通路需要进入内核态准备通信所需的各种资源,比如创建和配置后面章节会介绍的各 RDMA 基本元素(如 CQ、QP 等),主要操作由软件完成,硬件接受配置。数据通路专门负责数据收发,由软件和硬件合作完成RDMA Write(写)、RDMA Read(读)、Send(发送)和 Receive(接收)等操作。
1.RDMA通信过程
以 Send 和 Receive 操作为例,一次 RDMA 通信的过程简单描述如下。
- 发送端和接收端的软件都通过控制通路进入内核态,创建通信所需的各种资源,包括 MR、QP、CQ 等。
- 在数据通路上,接收端的应用程序通知硬件准备接收数据,并将存放数据的缓存地址告知硬件。
- 在数据通路上,发送端的应用程序通知硬件发送数据,并将待发送数据所在的缓存地址和数据长度告知硬件。
- 发送端硬件使用 DMA 操作从位于主机内存的缓存中将数据复制到自己的硬件内部缓存,然后按照协议封装数据包并发送给对端。
- 接收端硬件收到数据包,按照协议对其进行解析,并通过 DMA 操作将有效的应用数据写入主机内存。
- 在数据通路上,接收端的应用程序获知收到的数据已被放入本地缓存。
上图展示了使用 RDMA 方案时,用户数据在两个运行在不同机器上的应用程序之间传递的过程。图中的机器 1 为发送端,机器 2 为接收端。包括在网线/光纤上的数据传输,整个数据传递过程共进行了 3 次数据复制,按照编号依次如下。
① 发送端网卡通过 DMA 操作,从主机内存的用户空间将数据复制到自己的硬件内部缓存中,并进行封装,即添加各层协议报头和校验信息。
② 发送端网卡通过网线/光纤将封装好的数据发送给接收端的网卡。
③ 接收端网卡接收到数据后,先进行数据解析,即把各层协议报头和校验信息剥离,然后将硬件缓存中的数据通过 DMA 操作复制到主机内存的用户空间。
2.RDMA方案的优点
本地内存零复制,即省去了数据在主机内存的用户空间和内核空间之间复制的步骤,降低了整个数据收发过程的时延。
内核旁路(bypass),即数据通路绕过内核,避免了系统调用和上下文切换的时间开销。
把数据包的封装和解析工作交由网卡来实现,降低了 CPU 负载。
在一个系统中,内核协议栈方案和 RDMA 方案是可以共存的。RoCE 类型的 RDMA 网卡可以同时支持以太网和 RDMA。下图从数据通路的角度比较了在同一系统中运行的(APP1 使用的)以太网方案和(APP2 使用的)RDMA 方案的区别。可见 RDMA 方案的数据通路已经进行了充分的简化,几乎卸掉了所有的包袱。
不过,相对于以太网方案,RDMA 方案对网卡提出了新的要求,主要有两点。
- 能够解析页表:由于应用程序申请的数据缓存一般都是虚拟地址连续而物理地址不连续的,因此要求硬件有解析页表的能力,能够访问物理地址不连续的缓存。注意,此处所说的页表是软件专门为 RDMA 网卡建立的,不是 MMU 访问的页表。
- 能够封装和解析数据包:网卡需要按照协议,在发送数据前加上协议报头与校验和,并在接收数据后将其剥离。
二、RDMA的优势
通信领域出现率最高的性能指标就是带宽和时延。简单来说,所谓带宽是指单位时间内能够传输的数据量(比如 100Gbit/s),而时延指的是数据从本端发出到被对端接收所消耗的时间。相比传统以太网,RDMA 技术实现了更低的时延,所以 RDMA 能够在很多对时延要求较高的场景中(比如分布式神经网络多个计算节点间的数据同步)得以发挥作用。
三、RDMA协议
RDMA 指的是一种 远程直接存储器访问技术。具体到协议层面,它主要包含 InfiniBand、 RoCE 和 iWARP 三种协议。三种协议都符合 RDMA 标准,共享相同的上层用户接口(Verbs),只是在不同层次上有一些差别。1.InfiniBand
InfiniBand(直译为“无限带宽”,缩写为 IB)是一个用于高性能计算的计算机网络通信标准,它具有极高的吞吐量和极低的时延,但是 InfiniBand无法兼容现有以太网,如果企业想部署的话,除了需要专用网卡之外,还要重新购买配套的网络交换设备。
2.Roce
基于融合以太网的 RDMA(RDMA over Converged Ethernet,RoCE)
InfiniBand 架构规范定义了如何通过 InfiniBand 网络执行 RDMA,而 RoCE 则定义了如何通过以太网网络执行 RDMA。
RoCE 有RoCEv1 和RoCEv2 两个版本。RoCEv1 的网络层使用了InfiniBand规范,链路层使用以太网协议,因此允许同一个以太网广播域中的两台主机进行通信。RoCEv2使用了“UDP+IP”作为网络层,是一个“网络层+链路层”协议,因此 RoCEv2 网络中的数据包可以被路由。RoCE 被认为是 InfiniBand 的“低成本解决方案”,将InfiniBand 传输层的报文封装成以太网数据包进行收发(也就是说 RoCE 仍然使用 InfiniBand 传输层)。由于 RoCE 可以使用以太网交换设备,因此在企业中的应用比较多,但是其在相同场景下相比 InfiniBand 会有一些性能方面的损失。
RoCE 与 InfiniBand 有如下几个技术差异。
- 链路级流量控制。InfiniBand 使用基于信用(credit-based)的算法来保证无损的网络通信。RoCE 的实现需要无损以太网网络,以达到类似 InfiniBand 的性能。无损以太网通常通过以太网流量控制或优先级流量控制(PFC)进行配置,配置一个无损以太网网络比配置一个InfiniBand 网络复杂。
- 阻塞控制。InfiniBand 定义了基于 FECN/BECN 标记的阻塞控制协议。RoCEv2 定义了一种使用 ECN 进行标记、CNP 帧进行反馈的阻塞控制协议,网络中的交换机中需要支持 ECN 功能。
- InfiniBand 交换机的时延通常低于以太网交换机。
在以太网链路层上使用 RDMA 应用程序时,应注意以下几点。
- 网络中不需要子网管理器。对于那些需要与子网管理器通信的操作,在 RoCE 网络中会以不同的方式进行管理。
- 由于 LID 是 InfiniBand 协议栈链路层的属性,其在 RoCE 网络中无效,因此在查询RoCE 网卡的端口时,LID 显示为零。
- 因为子网管理器不存在,所以无法查询路径。因此,在建立连接之前,必须将相关的值填充进路径记录结构。建议使用 RDMA CM 建立连接,因为它可以负责填充路径记录结构。
- RoCE 设备的流量不显示在相关以太网设备的计数器(比如 ifconfig 命令的输出中可以看到的收发包计数)中,因为它的数据收发不通过以太网设备驱动程序。RoCE 设备和 InfiniBand 设备的流量 统计都在 /sys/class/infiniband/<device>/ports/<port number>/counters/目录下。
获取此网卡当前支持的 RoCE 版本
cma_roce_mode -d mlx5_0 -p 1
3.iWARP
iWARP(Internet Wide Area RDMA Protocol)是 IETF 定义的基于 TCP 的 RDMA,它和 RoCE v2 都可以路由。因为 TCP 是面向连接的可靠协议,这使得 iWARP 在面对有损网络场景时,相比 RoCEv2 和 InfiniBand 具有更好的可靠性,在大规模组网时也有明显的优势。但在大规模数据中心和大规模应用程序(比如大型企业网、云计算、Web 2.0 应用程序等)中使用 iWARP 时,大量连接的内存需求以及 TCP 的流量和可靠性控制将会导致可扩展性和性能相关的问题,并且会耗费很多的内存资源。总体来看,RoCE 在时延、吞吐量和 CPU 开销方面明显优于 iWARP。此外,RoCE 规范中定义了多播,而当前的 iWARP 规范没有定义如何执行多播 RDMA。
需要注意的是,虽然存在软件实现的 RoCE 和 iWARP,但是真正商用时上述几种协议都需要专门的硬件(网卡)支持。本文中测试和分析代码时所使用的 RDMA 网卡都为支持 RoCEv2 协议的网卡。
四、RDMA网络构成
InfiniBand 体系结构定义了组网通信所需的多种设备:通道适配器(channel adapter)、交换机(switch)、路由器(router)和子网管理器(subnet manager)。其中子网管理器属于虚拟设备,它可以在其他任何一台设备上实现。每个终端(endnode)设备必须至少有一个通道适配器(HCA 或 TCA)。一个子网中至少有一个子网管理器用于配置和维护链路。所有的通道适配器和交换机必须包含子网管理代理(subnet management agent,SMA),用于处理与子网管理器的通信。除了子网管理器,RoCE 类型的网络中也需要上述这些组件。
1.主机通道适配器(host channel adapter,HCA)
HCA 即安装在主机上的 RDMA 网卡,用于将一个主机设备连接到一个 RDMA 网络上。一个 HCA 可以有多个物理端口(port),每个端口有自己的本地标识符(local identifier, LID)或 LID 范围。另外,每个端口还有自己的发送和接收缓存(buffer),因此所有端口可以并行发送和接收。
子网管理器为 HCA 的每一个物理端口配置子网内的本地地址,即 LID。HCA 中的子网管理代理和子网管理器通信,共同实现子网管理功能。
厂商会给每一个 HCA 分配独一无二的标识符,称为 GUID(globally unique identifier)。子网管理器分配给 HCA 的 LID 并不是永久的(断电重启后可能会变),所以 GUID 就成了永久识别某一个 HCA 的主要标识符。另外,厂商还给每一个端口分配了一个端口 GUID。
HCA 支持 InfiniBand 定义的所有软件 Verbs。Verbs 是一种抽象表示,它定义了客户端软件和 HCA 功能之间所需的接口。Verbs 不直接指定操作系统的应用程序编程接口(API),而是定义了一系列操作,提供给操作系统供应商开发相应的API。
2.目标通道适配器(target channel adapter,TCA)
TCA 为 I/O 设备(比如硬盘控制器)提供其到 RDMA 网络的连接,支持每个设备的特定操作所需的 HCA 功能子集。
3.子网管理器(subnet manager)
InfiniBand 子网管理器为连接到InfiniBand 网络的每个端口分配 LID,并基于分配的 LID建立路由表。子网管理器属于软件定义网络(SDN)的概念,它消除了互连的复杂性,支持创建非常大规模的计算和存储基础设施。子网管理器配置本地子网并确保其持续运行。每个子网中必须至少有一个子网管理器,用于管理所有交换机和路由器的配置,并在链路断开或出现新链路时重新配置子网。
子网管理器可以位于子网中的任何设备内,它通过与每台设备上的子网管理代理通讯来进行工作。一个子网中可以有多个子网管理器,但只能有一个子网管理器处于活动状态。不在活动状态的子网管理器(即备用子网管理器),会同步保存处于活动状态的子网管理器转发的信息副本,并验证活动状态的子网管理器是否仍在运行。如果处于活动状态的子网管理器停机了,备用子网管理器将接管它的工作,以确保整个子网不会停摆。
在 RoCE 类型的网络中,不存在子网管理器。
4.交换机(switch)
InfiniBand 交换机在概念上类似于标准以太网交换机,但其设计旨在满足 InfiniBand 的性能要求。它们实现 InfiniBand 链路层的流量控制以防止丢包,有避免阻塞和自适应路由的功能,并支持高级服务质量(QoS)。许多交换机包含了子网管理器的功能。交换机包含多个端口,并根据协议第二层本地路由报头中包含的 LID,将数据包从一个端口转发到另一个端口。交换机只会管理和转发数据包,不会消耗或产生数据包。与通道适配器(HCA 和 TCA)一样,交换机必须包含子网管理代理功能,以处理子网管理报文。交换机可以被配置为转发单播数据包(到单个设备)或多播数据包(到多个设备)。
RoCE 类型的网络中使用的是以太网交换机。
5.路由器(router)
InfiniBand 路由器将数据包从一个子网转发到另一个子网,而不消耗或产生数据包。与交换机不同,路由器根据全局路由报头(global route header,GRH)中包含的 IPv6 网络层地址来转发数据包。在将数据包发送到下一个子网中时,路由器会按照目标子网中合适的 LID 来修改数据包中的本地路由报头(local route header,LRH),重新组装每个数据包。
路由对终端来说并不是透明的,因为终端发包时必须指定路由器的 LID 和最终目标的GID。
每一个子网都有独一无二的子网ID,称为子网前缀。子网管理员会把这个子网前缀赋值给这个子网中所有的端口(包含在端口的 PortInfo 属性中)。这个子网前缀和端口的 GUID结合,就成了端口的GID。端口也可以有其他的GID。
从路由器的角度看,GID 中的子网前缀部分就代表了穿过路由器的路径。路由器依据数据包的目的 GID 和转发表来决定把数据包转发到哪个或哪些端口。
RoCE 类型的网络中使用的是以太网路由器。
五、LID和GID
从功能上看,LID(local identifier)和 GID(globally identifier)的概念类似于“以太网和 IP 网”中的 MAC 和IP,分别用于子网内的目标寻址和子网间的目标寻址。
根据InfiniBand 协议,两台设备间建立连接时,需要知道对方的 QP 号和端口,其中对端口的识别根据 LID 和GID(后者可选)进行。
1.LID
InfiniBand 定义的 LID 是一个 16 位的标识符。LID 有以下特征。
- 由子网管理员分配,子网内唯一,不可用于子网间路由。
- LID 作为一种网络地址,分为预留、单播和多播地址段。
- 数据包中的本地路由报头(local route header,LRH)中包含了 LID。
- 源 LID 指的是第一个将数据包插入子网的终端端口的 LID。
- 一个单播型的目的 LID 适用于某一个目的终端端口。一个多播型的目的 LID 适用于一个子网中某个多播组里的一系列目的终端端口。
- 如果最终的目的端口不在这个子网内,数据包中的目的 LID 指向的是,负责转发这个数据包到下一跳的路由器的某个端口。
- 一个终端端口在连接到子网后,收到的数据包可能经过了子网内的多条物理路径。如图中交换机之间相同类型的连线表示一条可能的路径,这样的路径共有 4条。每条路径可以被一个或多个物理 LID 标识。为了降低 HCA 的多路径操作的复杂度,每个物理端口应分配一个基本 LID 和一个 LMC。LMC 是一个 3 位的域,代表
条路径。HCA A 和 HCA C 之间存在多条路径。如果 HCA A 被分配了基本 LID 4,LMC =2,则其 LID 的范围是 4、5、6、7。如果 HCA C 被分配了基本 LID 8,LMC=2,则其 LID 的范围就是 8、9、10、11。
- LID 的分配规则:LID 0x0000 无效;LID 0xFFFF 分配给接收数据包的终端端口的 QP0; 0x0001 和 0xBFFF 之间为单播 LID;0xC000 和 0xFFFE 之间为多播 LID。
对于 RoCE 类型的网络,LID 无效,所有端口的 LID 都为 0x0000。
2.GID
GID 是一种 128 位的单播或多播标识符,用于标识端口或多播组。
GUID(globally unique identifier)是全局唯一的 EUI-64 标识符,共 64 位。其中的 24 位表示厂商 ID,另外 40 位是扩展标识符,由生产设备的厂商来分配。
GID 有以下特征。
- 每个终端端口必须被分配至少一个单播 GID。第一个单播 GID 在创建时必须使用厂商分配的 EUI-64 标识符。此 GID 称为 0 号 GID。
- 默认的GID 前缀为 0xFE80::0,共 64 位。使用默认 GID 前缀和厂商/子网管理器分配的 EUI-64 可以组成 128 位的 GID,使用这种 GID 封装的数据包必须被终端接纳。一个数据包的全局路由报头(GRH)中如果有这种前缀的目的 GID,则路由器不能将其转发,也就是必须限制在本地子网内处理。
- 一个子网 GID 必须使用下列一个或多个规则来创建。
- 规则 1。把默认 GID 前缀和厂商给终端端口分配的 EUI-64 标识符连接起来。这个 GID 就是默认的GID。
- 规则 2。把子网管理器分配的 64 位的GID 前缀和厂商给终端端口分配的EUI-64标识符连接起来。
- 规则 3。子网管理器分配的 GID。子网管理器把默认或者分配的 GID 前缀和一组本地分配的 EUI-64 值连接起来。这种 GID 称为 1 号或更大号码的 GID。每个终端端口必须用规则 1 分配至少一个单播 GID。其他 GID 可用规则 2 或规则 3分配。注意,一个子网在某个时间点只能有一个分配的(非默认的)GID 前缀。
- 通道适配器、交换机或路由器上的任何 QP,都可以用默认 GID 前缀加上为这个 QP分配的 GID 来寻址。这使得一个子网可以在不中断已有通信会话的情况下,从默认 GID 前缀状态转换为托管状态。
- 每个终端端口可以支持的单播 GID 的最大数量(N)取决于具体实现。子网管理器可以分配N−1 个额外的单播 GID,这 N−1 个 GID 中的每一个都是通过将一个子网管理器分配的 EUI-64 标识符与GID 前缀连接起来创建的。
- 单播GID 地址 0:0:0:0:0:0:0:0 是保留的,称为保留 GID。不得将其分配给任何终端端口,也不得将其用作目的地址或用在 GRH 中。
- 单播 GID 地址 0:0:0:0:0:0:0:1 称为环回 GID,仅由原始(raw)IPv6 服务使用,不由InfiniBand 传输服务使用。不得将其分配到终端端口或出现在任何 InfiniBand 数据包中。
- 单播GID 子网前缀应限于 GID 地址空间的高 64 位。子网前缀的位的数量可能会进一步受到填充(filler)和作用域(scope)位的限制,见下文分析。
- 单播GID 的低 64 位不能进一步划分子网。
- 单播GID 的低 64 位在子网中是唯一的。
- GRH 中应包含有效的源 GID 和目的 GID。
- 单播GID 的范围包括以下类型。
- 本地链路型(link-local)。这种单播 GID 使用默认的 GID 前缀(0xFE80::0),只在子网内使用。如果数据包中有此类 GID,无论是作为源 GID 还是目的 GID,路由器都不能把数据包转发到子网外。本地链路型 GID 的格式如图 13-10(a)所示。
- 本地区域型(site-local)。这种单播 GID 在一组子网(比如一个数据中心的多个子网)组成的区域内是唯一的,但不一定是全局唯一。路由器不能把带有这种源 GID或目的 GID 的数据包转发到区域外。本地区域型 GID 的格式如图 13-10(b)所示。
- 全局唯一型(global)。这种单播GID 是带有全局前缀的,即路由器可以使用此 GID在整个企业网或互联网上路由数据包。全局唯一型 GID 的格式如图13-10(c)所示。
- 多播GID(MGID)用于识别多播组。多播组中的所有成员,除了具有相同的 MGID,还必须共享相同的 P_key 和 Q_key。
- 多播GID 的格式如图 13-11 所示。
- 起始的 11111111 表示这是多播 GID。
- Scope(作用域)字段也有 4 位,用于限制多播组的作用域。如果 Scope 字段的值为 2,表示此多播 GID 仅限在子网内使用;如果 Scope 字段的值为 5,表示此多播GID 仅限在由几个子网组成的一个区域中使用;如果 Scope 字段的值为 8,表示此多播 GID 可以在一个本地组织中使用;如果 Scope 字段的值为 0xE,表示此多播 GID 可以全局使用。
- 标记(Flag)字段有 4 个 1 位的标记,格式为 000T,目前保留前 3 个标记,并定为 0。如果 T 为 0,表示这是一个永久分配的(即众所周知的)多播 GID;如果 T 为 1,表示这是一个非永久分配(即暂时)的多播 GID。
- 一个终端端口可以加入 0、1 或多个多播组,也就是说,一个终端端口可以被分配 0、 1 或多个多播GID。
- 多播GID 不能作为源 GID 出现在全局路由报头中。
- 多播 GID FF02:0:0:0:0:0:0:1 是一个本地链路型的多播 GID,路由器不能把以这种 GID为目的GID 的数据包转发到子网外。此 GID 在作为 GRH 内的目的地址时,被用来与参与所有通道适配器多播组的一组 QP 通信。所有通道适配器多播组包括希望参与该多播组的所有通道适配器,和增强型交换机的 0 号端口。所有通道适配器多播组用于向能够参与多播操作的所有通道适配器(必须共享相同的 MGID、P_key 和 Q_key)实现广播服务。