如果我们的预期是将网络延时从10ms 降低到1ms,那么应该先分析这些时延的具体构成,很有可能瓶颈并不是网络传输;如果目标是将网络延时降低到微秒级或者百微秒级,那么我们才可能使用到高性能网络,例如RDMA技术。
1. TCP/IP 协议栈的局限
数据中心内部服务器的接入带正在由万兆(10G)接入升级为25G,在某些用于机器学习的服务器上甚至使用了100G的接入带宽。量变引起质变,增大的接入带宽让传统的TCP/IP协议栈遇到了严重的性能挑战。
在当前的操作系统中,使用TCP传输数据,需要大量的CPU参与,包括报文的封装解析和流控处理等。一个TCP报文均由一个CPU核处理,单个TCP流的最大吞吐受制于CPU单核的处理能力。无奈的是,CPU单核计算能力几乎不能再提升了,这导致采用TCP/IP协议栈的数据传输一定会遇到吞吐量瓶颈。如果想充分地利用100G的带宽,就必须使用多个流的并行传输。这一方面增加了应用程序的复杂度,另一方面也意味着不得不将更多昂贵的计算资源投入到网络传输的领域中去。
除了带宽以外,时延同样是使用传统TCP/IP协议栈的一个主要痛点。一个应用程序要发送数据,必须先通过socket API,数据从用户态进入到内核态,经过内核的报文处理后,再交给网络协议栈发送出去。类似地,在接收端,内核先收到报文,进行处理后提取出数据,等待用户态的处理。这中间需要经过操作系统在内核态/用户态转化,要经过CPU的报文处理,也还要依赖操作系统的中断。因此,在小数据量的传输时延中,主要延时并非是在物理网络上的传输时延,而是在发送/接收软件协议栈中的处理时延。
2. 高性能IB网络
在高性能计算集群中,网络协议一般不是Ethernet+TCP/IP,而是Infiniband(IB)协议,是从物理层到传输层的一整套协议栈。Infiniband的物理接口与以太网接口是完全不同的,是一套完全不同于一般数据中心中以太网架构的网络。
Infiniband是完全基于集中控制的一种网络设计,简化了交换设备的复杂度,有助于降低转发时延,但这也就导致了IB网络的扩展性不如以太网。作为超级计算机思想的自然延伸,Infiniband对上层表现为一条计算机内的总线,并不采用Best Effort的转发策略,而采用了避免丢包的lossless设计,并且上层编程接口开放了直接针对远程内存的Read/Write。
Infiniband的传输层协议是RDMA,即Remote Direct Memory Access,利用了底层网络lossless的特性,并向上层应用程序提供一种称为verbs API的编程接口。RDMA从设计之初就是让硬件网卡ASIC来执行网络传输相关操作的。
第一个Infiniband的标准成形于2000年,自产生以来在HPC领域得到了大量的使用。直到2010年,首个RDMA over Converged Ethernet(RoCE)标准形成,宣告IB网络的传输层协议RDMA可以以覆盖网络的形式运行于以太网之上,RoCE的性能相比Infiniband还是要差一些的。自此,IB网络和以太网正式发生交叠,RDMA技术开始进入一般数据中心,为即将到来的AI计算和云计算的爆发式增长提供了关键支持。
3. RDMA的特性
当我们使用RDMA的时候,应用程序的实际数据发送根本不用经过内核处理,也不用拷贝,而是由RDMA网卡直接从用户态内存中DMA到网卡上,然后在网卡硬件上进行封装等处理,而接收端也是从网卡上解封装处理后,直接把数据DMA给用户态内存。这就是RDMA技术中kernel bypass和zero copy两个特性的真正涵义。
正是因为kernel bypass和zero copy,RDMA获得了三个关键的衍生特性:低时延、高带宽和低CPU消耗。这三个衍生特性往往作为RDMA相对于TCP/IP协议栈的主要优势被提出。需要特别注意的是,kernel bypass和zero copy都需要网卡的硬件支持,这意味着若想用RDMA,就必须要拥有支持RDMA技术的网卡。
上图中RDMA的左边经过libibverbs的部分一般称为Command Channel,是应用程序调用verbs API时的命令通道,并不是真正的数据通道。
3.1 RDMA的verbs API
应用程序使用RDMA用的是verbs API,而不是socket API。RDMA有三种队列:Send Queue(SQ)、Recv Queue(RQ)和Completion Queue(CQ)。SQ和RQ往往成对出现,合起来称为Queue Pair。SQ是发送请求队列,RQ就是接收请求队列,CQ就是发送请求和接收请求完成情况的队列。
当一个应用程序需要发送数据的时候,会向SQ里提交一个发送请求(API:ibvpostsend),这个请求并不包含数据本身,只包含指向数据的指针以及数据的长度,提交操作是通过API实现的。这个请求会传递到网卡,由网卡自己按照地址和长度把要发送的数据取出,然后发送到网络。发送完成后,会在CQ中生成一个发送完成的说明。在接收端,应用程序必须事先提交一个接收请求到RQ(API:ibvpostrecv),这个接收请求里包含了接收数据要存放的内存指针以及可以接收的最大数据长度。当数据到来的时候,网卡会将数据放在RQ队列头中的接收请求所指明的内存位置,然后在CQ中生成一个接收完成的说明。verbs API的发送与接收都是异步非阻塞的调用,应用程序需要检查CQ中来判断一个请求的完成情况,QP可以视为类似socket。
其实在RDMA中,除了Send/Recv以外,还有RDMA Write/Read的特别请求,可以直接实现对远端应用程序虚拟内存的访问。RDMA Write/Read请求也是向发起端SQ提交的),但与Send/Recv不同的是,另一端并不需要事先向RQ提交接收请求。这种单边的RDMA传输方式会比Send/Recv有更好的性能,不过必须事先知道数据在对端的确切地址。
3.2 RDMA 的无丢包实现
丢包本身就是网络传输的性能杀手,而且为了从丢包中快速恢复,需要引入复杂的、难以用硬件实现的处理逻辑。以太网可以利用pause机制变成无丢包的,无丢包机制的实现对RDMA是至关重要的,在RoCE中启用pause机制的时候,为了尽可能限制pause的副作用,可以在网络中分出不同的优先级队列,仅仅在特定的优先级队列上开启pause,这就是以太网的优先级流控(PFC)机制,已经作为DCB标准的一部分。现在多数的数据中心交换机都已经支持PFC。在PFC配置生效的情况下,RDMA流量跑在开启了pause的优先级下,而让TCP的流量跑在没有开启pause的优先级下来尽可能限制pause机制所带来的副作用。
RDMA可以在特殊设计下放弃PFC配置,但这样的设备还没有真正诞生,依然要假定RDMA需要无丢包的底层网络,RDMA的正常使用高度依赖于网络内交换设备以及网卡的正确配置。
3.3 RDMA的相关技术
RDMAcm,全称为RDMA communication manager,是对verbs API的一个封装调用库。RDMAcm的API近似于socket API,如rdmaconnect,rdmalisten,rdma_accept等,只是作为部分verbs API的一个简化使用方案而已。rsocket是包含在librdmacm中的一个工具,可以把RDMA使用封装为socket接口,替代系统默认的socket,从而使得应用程序在不修改代码的情况下使用RDMA。
DPDK源自Intel的网卡kernel bypass技术,在数据中心中得到了广泛的应用。DPDK和RDMA没有直接关系,但都可以kernel bypass,不免有时会拿来对比。DPDK相比RDMA,主要有两个不同:一是DPDK必须轮询,会消耗CPU资源;二是DPDK仍需要由用户态做报文处理,这部分的时延和开销并没有降低。然而,DPDK有一个优势,即其不需要通信对端也做同样的支持,RDMA和DPDK各有属于自己的应用场景。
3.4 RDMA 的典型应用场景
RDMA当前最主要的应用场景有两类:一是高性能计算,包括分布式机器学习训练(尤其是使用GPU的时候);二是计算存储分离。前者主要关注高带宽,例如tensorflow、paddlepaddle等。后者主要关注低时延,代表性案例有nvmf、smb direct等。另外,RDMA在大数据处理(如spark)和虚拟化(如虚机迁移)等场景中也有应用,更多的使用场景仍在探索之中。
4 小结
对于高性能网络而言,通过kernel bypass和zero copy,RDMA实现了网络传输的低时延、高带宽与低CPU消耗。一般地,应用程序需要通过特殊的API来使用RDMA,而RDMA则需要底层网络具备无丢包配置,其主要应用场景包括了高性能计算以及计算存储分离。