如果我們的預(yù)期是將網(wǎng)絡(luò)延時從10ms 降低到1ms,那么應(yīng)該先分析這些時延的具體構(gòu)成,很有可能瓶頸并不是網(wǎng)絡(luò)傳輸;如果目標(biāo)是將網(wǎng)絡(luò)延時降低到微秒級或者百微秒級,那么我們才可能使用到高性能網(wǎng)絡(luò),例如RDMA技術(shù)。
1. TCP/IP 協(xié)議棧的局限
數(shù)據(jù)中心內(nèi)部服務(wù)器的接入帶正在由萬兆(10G)接入升級為25G,在某些用于機器學(xué)習(xí)的服務(wù)器上甚至使用了100G的接入帶寬。量變引起質(zhì)變,增大的接入帶寬讓傳統(tǒng)的TCP/IP協(xié)議棧遇到了嚴重的性能挑戰(zhàn)。
在當(dāng)前的操作系統(tǒng)中,使用TCP傳輸數(shù)據(jù),需要大量的CPU參與,包括報文的封裝解析和流控處理等。一個TCP報文均由一個CPU核處理,單個TCP流的最大吞吐受制于CPU單核的處理能力。無奈的是,CPU單核計算能力幾乎不能再提升了,這導(dǎo)致采用TCP/IP協(xié)議棧的數(shù)據(jù)傳輸一定會遇到吞吐量瓶頸。如果想充分地利用100G的帶寬,就必須使用多個流的并行傳輸。這一方面增加了應(yīng)用程序的復(fù)雜度,另一方面也意味著不得不將更多昂貴的計算資源投入到網(wǎng)絡(luò)傳輸?shù)念I(lǐng)域中去。
除了帶寬以外,時延同樣是使用傳統(tǒng)TCP/IP協(xié)議棧的一個主要痛點。一個應(yīng)用程序要發(fā)送數(shù)據(jù),必須先通過socket API,數(shù)據(jù)從用戶態(tài)進入到內(nèi)核態(tài),經(jīng)過內(nèi)核的報文處理后,再交給網(wǎng)絡(luò)協(xié)議棧發(fā)送出去。類似地,在接收端,內(nèi)核先收到報文,進行處理后提取出數(shù)據(jù),等待用戶態(tài)的處理。這中間需要經(jīng)過操作系統(tǒng)在內(nèi)核態(tài)/用戶態(tài)轉(zhuǎn)化,要經(jīng)過CPU的報文處理,也還要依賴操作系統(tǒng)的中斷。因此,在小數(shù)據(jù)量的傳輸時延中,主要延時并非是在物理網(wǎng)絡(luò)上的傳輸時延,而是在發(fā)送/接收軟件協(xié)議棧中的處理時延。
2. 高性能IB網(wǎng)絡(luò)
在高性能計算集群中,網(wǎng)絡(luò)協(xié)議一般不是Ethernet+TCP/IP,而是Infiniband(IB)協(xié)議,是從物理層到傳輸層的一整套協(xié)議棧。Infiniband的物理接口與以太網(wǎng)接口是完全不同的,是一套完全不同于一般數(shù)據(jù)中心中以太網(wǎng)架構(gòu)的網(wǎng)絡(luò)。
Infiniband是完全基于集中控制的一種網(wǎng)絡(luò)設(shè)計,簡化了交換設(shè)備的復(fù)雜度,有助于降低轉(zhuǎn)發(fā)時延,但這也就導(dǎo)致了IB網(wǎng)絡(luò)的擴展性不如以太網(wǎng)。作為超級計算機思想的自然延伸,Infiniband對上層表現(xiàn)為一條計算機內(nèi)的總線,并不采用Best Effort的轉(zhuǎn)發(fā)策略,而采用了避免丟包的lossless設(shè)計,并且上層編程接口開放了直接針對遠程內(nèi)存的Read/Write。
Infiniband的傳輸層協(xié)議是RDMA,即Remote Direct Memory Access,利用了底層網(wǎng)絡(luò)lossless的特性,并向上層應(yīng)用程序提供一種稱為verbs API的編程接口。RDMA從設(shè)計之初就是讓硬件網(wǎng)卡ASIC來執(zhí)行網(wǎng)絡(luò)傳輸相關(guān)操作的。
第一個Infiniband的標(biāo)準(zhǔn)成形于2000年,自產(chǎn)生以來在HPC領(lǐng)域得到了大量的使用。直到2010年,首個RDMA over Converged Ethernet(RoCE)標(biāo)準(zhǔn)形成,宣告IB網(wǎng)絡(luò)的傳輸層協(xié)議RDMA可以以覆蓋網(wǎng)絡(luò)的形式運行于以太網(wǎng)之上,RoCE的性能相比Infiniband還是要差一些的。自此,IB網(wǎng)絡(luò)和以太網(wǎng)正式發(fā)生交疊,RDMA技術(shù)開始進入一般數(shù)據(jù)中心,為即將到來的AI計算和云計算的爆發(fā)式增長提供了關(guān)鍵支持。
3. RDMA的特性
當(dāng)我們使用RDMA的時候,應(yīng)用程序的實際數(shù)據(jù)發(fā)送根本不用經(jīng)過內(nèi)核處理,也不用拷貝,而是由RDMA網(wǎng)卡直接從用戶態(tài)內(nèi)存中DMA到網(wǎng)卡上,然后在網(wǎng)卡硬件上進行封裝等處理,而接收端也是從網(wǎng)卡上解封裝處理后,直接把數(shù)據(jù)DMA給用戶態(tài)內(nèi)存。這就是RDMA技術(shù)中kernel bypass和zero copy兩個特性的真正涵義。
正是因為kernel bypass和zero copy,RDMA獲得了三個關(guān)鍵的衍生特性:低時延、高帶寬和低CPU消耗。這三個衍生特性往往作為RDMA相對于TCP/IP協(xié)議棧的主要優(yōu)勢被提出。需要特別注意的是,kernel bypass和zero copy都需要網(wǎng)卡的硬件支持,這意味著若想用RDMA,就必須要擁有支持RDMA技術(shù)的網(wǎng)卡。
上圖中RDMA的左邊經(jīng)過libibverbs的部分一般稱為Command Channel,是應(yīng)用程序調(diào)用verbs API時的命令通道,并不是真正的數(shù)據(jù)通道。
3.1 RDMA的verbs API
應(yīng)用程序使用RDMA用的是verbs API,而不是socket API。RDMA有三種隊列:Send Queue(SQ)、Recv Queue(RQ)和Completion Queue(CQ)。SQ和RQ往往成對出現(xiàn),合起來稱為Queue Pair。SQ是發(fā)送請求隊列,RQ就是接收請求隊列,CQ就是發(fā)送請求和接收請求完成情況的隊列。
當(dāng)一個應(yīng)用程序需要發(fā)送數(shù)據(jù)的時候,會向SQ里提交一個發(fā)送請求(API:ibvpostsend),這個請求并不包含數(shù)據(jù)本身,只包含指向數(shù)據(jù)的指針以及數(shù)據(jù)的長度,提交操作是通過API實現(xiàn)的。這個請求會傳遞到網(wǎng)卡,由網(wǎng)卡自己按照地址和長度把要發(fā)送的數(shù)據(jù)取出,然后發(fā)送到網(wǎng)絡(luò)。發(fā)送完成后,會在CQ中生成一個發(fā)送完成的說明。在接收端,應(yīng)用程序必須事先提交一個接收請求到RQ(API:ibvpostrecv),這個接收請求里包含了接收數(shù)據(jù)要存放的內(nèi)存指針以及可以接收的最大數(shù)據(jù)長度。當(dāng)數(shù)據(jù)到來的時候,網(wǎng)卡會將數(shù)據(jù)放在RQ隊列頭中的接收請求所指明的內(nèi)存位置,然后在CQ中生成一個接收完成的說明。verbs API的發(fā)送與接收都是異步非阻塞的調(diào)用,應(yīng)用程序需要檢查CQ中來判斷一個請求的完成情況,QP可以視為類似socket。
其實在RDMA中,除了Send/Recv以外,還有RDMA Write/Read的特別請求,可以直接實現(xiàn)對遠端應(yīng)用程序虛擬內(nèi)存的訪問。RDMA Write/Read請求也是向發(fā)起端SQ提交的),但與Send/Recv不同的是,另一端并不需要事先向RQ提交接收請求。這種單邊的RDMA傳輸方式會比Send/Recv有更好的性能,不過必須事先知道數(shù)據(jù)在對端的確切地址。
3.2 RDMA 的無丟包實現(xiàn)
丟包本身就是網(wǎng)絡(luò)傳輸?shù)男阅軞⑹郑覟榱藦膩G包中快速恢復(fù),需要引入復(fù)雜的、難以用硬件實現(xiàn)的處理邏輯。以太網(wǎng)可以利用pause機制變成無丟包的,無丟包機制的實現(xiàn)對RDMA是至關(guān)重要的,在RoCE中啟用pause機制的時候,為了盡可能限制pause的副作用,可以在網(wǎng)絡(luò)中分出不同的優(yōu)先級隊列,僅僅在特定的優(yōu)先級隊列上開啟pause,這就是以太網(wǎng)的優(yōu)先級流控(PFC)機制,已經(jīng)作為DCB標(biāo)準(zhǔn)的一部分?,F(xiàn)在多數(shù)的數(shù)據(jù)中心交換機都已經(jīng)支持PFC。在PFC配置生效的情況下,RDMA流量跑在開啟了pause的優(yōu)先級下,而讓TCP的流量跑在沒有開啟pause的優(yōu)先級下來盡可能限制pause機制所帶來的副作用。
RDMA可以在特殊設(shè)計下放棄PFC配置,但這樣的設(shè)備還沒有真正誕生,依然要假定RDMA需要無丟包的底層網(wǎng)絡(luò),RDMA的正常使用高度依賴于網(wǎng)絡(luò)內(nèi)交換設(shè)備以及網(wǎng)卡的正確配置。
3.3 RDMA的相關(guān)技術(shù)
RDMAcm,全稱為RDMA communication manager,是對verbs API的一個封裝調(diào)用庫。RDMAcm的API近似于socket API,如rdmaconnect,rdmalisten,rdma_accept等,只是作為部分verbs API的一個簡化使用方案而已。rsocket是包含在librdmacm中的一個工具,可以把RDMA使用封裝為socket接口,替代系統(tǒng)默認的socket,從而使得應(yīng)用程序在不修改代碼的情況下使用RDMA。
DPDK源自Intel的網(wǎng)卡kernel bypass技術(shù),在數(shù)據(jù)中心中得到了廣泛的應(yīng)用。DPDK和RDMA沒有直接關(guān)系,但都可以kernel bypass,不免有時會拿來對比。DPDK相比RDMA,主要有兩個不同:一是DPDK必須輪詢,會消耗CPU資源;二是DPDK仍需要由用戶態(tài)做報文處理,這部分的時延和開銷并沒有降低。然而,DPDK有一個優(yōu)勢,即其不需要通信對端也做同樣的支持,RDMA和DPDK各有屬于自己的應(yīng)用場景。
3.4 RDMA 的典型應(yīng)用場景
RDMA當(dāng)前最主要的應(yīng)用場景有兩類:一是高性能計算,包括分布式機器學(xué)習(xí)訓(xùn)練(尤其是使用GPU的時候);二是計算存儲分離。前者主要關(guān)注高帶寬,例如tensorflow、paddlepaddle等。后者主要關(guān)注低時延,代表性案例有nvmf、smb direct等。另外,RDMA在大數(shù)據(jù)處理(如spark)和虛擬化(如虛機遷移)等場景中也有應(yīng)用,更多的使用場景仍在探索之中。
4 小結(jié)
對于高性能網(wǎng)絡(luò)而言,通過kernel bypass和zero copy,RDMA實現(xiàn)了網(wǎng)絡(luò)傳輸?shù)牡蜁r延、高帶寬與低CPU消耗。一般地,應(yīng)用程序需要通過特殊的API來使用RDMA,而RDMA則需要底層網(wǎng)絡(luò)具備無丟包配置,其主要應(yīng)用場景包括了高性能計算以及計算存儲分離。