infiniband概念空間分析
【文件概要】
最近在考慮把我們的加速器方案擴充套件到infiniband(以下簡稱ib)的概念空間中,所以解構一下它的概念空間,看看這樣做的可能性有多少。
由於本文需要給幾位合作伙伴分享,所以在中間版本就開發公開,這裡做一個簡單的版本管理:
V0.1.20181125 Kenneth Lee 完成初步概念構建,只對了程式碼,還沒有程式設計驗證,待進一步細化
IB是跨平臺的,但本文僅分析Linux的實現,分析基於當前最新的Linux Kernel版本4.20-rc1和rdma-core stable-v15
【基礎概念空間】
我原來做我們的加速器方案的時候,很多共享地址空間相關的方案都參考過InfiniBand的 umem的方案,我們自己也有RDMA的硬體解決方案,但我從來沒有考慮過要把加速器整合到InfiniBand中,因為這個名字和它使用的場合就讓人想到這是個通訊方案,是和遠端的另一個實體進行合作用的,所以,我也沒有深入去看過verbs的整個設計理念。
但實際上,雖然IB根植於通訊解決方案,它的verbs理念其實確實可以和通訊完全獨立的。
IB的基礎理念是這樣的:我有一個程式,要和另一個程式(可能在另一臺機器上)進行互相協助,這種協助可以被抽象為:
- 程式A和程式B建立一個雙工管道QP(Queue Pair,包含兩個CQ,一個Send Complete Queue和一個Receive Complete Queue),一方要求另一個幹什麼,只要把請求WR(Work Request),寫到對應的CQ中,另一方對這種請求進行響應,這個模型就可以建立起來了
- WR可以說明請求是什麼,這種請求被抽象為特定的原語(稱為verb),verb中可以索引記憶體,這種被索引的記憶體稱為MR(Memory Region),verb可以更新對方的MR,實現遠端程序的記憶體更新,這稱為RDMA
這個概念我們用下面這幅圖來表達:

在實現理念上,IB心目中的Application可以在使用者態,也可以在核心態(統稱Client),但為了保證效率,IB認為,這個通訊是直接和硬體溝通的,不經過第三方的軟體代理。也就是說,如果你的應用在使用者態,向對端傳送verb或者更新對方的MR,不需要經過核心。QP是直接mmap到使用者態的,MR也是直接暴露為實際的記憶體,直接被硬體同步到另一端的,而不經過使用者態和核心態的通訊過程。
為了實現QP和對端通訊的細節,QP中包含了不少和通訊有關的語義,這個我們下一步分析。我們先理解一下verbs這一層封裝了什麼邏輯,其實verbs的核心邏輯主要就三個:
所以,如果拋開通訊細節相關的東西,這是個完全和遠端通訊或者具體業務無關的概念模型。要用於具體的某個業務,你可以基於這個通訊層,實現需要的業務。這個高一層的業務抽象,稱為ULP(Upper Layer Protocol),現在常用的ULP包括:
- SDP:Socket Direct Protocol
- SRP:SCSI RDMA Protocol
- iSER:iSCSI Extension for RDMA
- IPoIB: IP over IB
- NFS-RDMA
- RDS: Reliable Datagram Socket
- MPI:Message Passing Interface
這樣,這些通訊方就構成這樣一個協議棧了:

下層的通訊棧可以根據不同的通訊協議承載在不同的協議上的,最常見的協議當然是Mellanox的Infiniband協議了,這也是它總造成誤會的原因。IB框架和IB通訊協議,是重名的。但其實那是可以換掉的。Linux的IB協議中,有一個模組叫RXE,這個東西基於Socket實現了一個Transport Layer,下面根本就沒有那些層次,但仍可以支援上面的大部分的verbs。
從這個角度來看,比如你做了一個壓縮引擎的加速器,你完全可以把這個加速引擎本身作為一個通訊方構成這樣的一個構架:

這是不考慮通訊本身的語義的情況,但如前所述,實際上IB是從通訊發展起來的,所以它的QP在一定程度上是認知下面的通訊層的。所以,我們還需要認知在這個語義空間中,有CA,HCA,TCA,Switch,Channel這個概念(圖片來自IBTA):

但大部分時候我們都用不上,但我們可以知道的是CA就是Channel Adapter,指那個支援通訊的裝置,TCA和HCA是target和Host CA。Channel是連線TCA和HCA的一條通道(連線),Channel和CA的對應叫一個Port。
SA(Subnet Administration)是網路管理相關命令,有如下子概念:mad(management diagram)是sa的管理報文,pr(path record)是路由管理介面,mc group(multicast group)是多播管理介面。
cm(connection management)管理連線,有如下子概念:mra(message received acknowledgement),sid(service id)
上帝保佑,暫時不要讓我碰到它們。
【verbs名稱空間的進一步理解】
現在對qp的名稱空間做進一步的理解。如前所述,ib的應用,可以在核心態,也可以在使用者態,兩者只是API介面不同,語義是類似的(但核心用ib_register_client()的概念代替使用者態的context),所以我們只從使用者態的介面來考量一下這些概念。
qp的名稱空間基本上可以從libibverbs/verbs.h上看出來
首先我們得有提供qp的裝置,這個稱為dev,通過ibv_get_device_list()來獲得,然後通過裝置名稱來匹配自己需要的那個裝置,基於裝置建立context,基於context建立pd,基於pd建立cq,基於cq建立qp。
綜合起來這個過程大概是這樣的:
dev = find_a_matched_device(ibv_get_device_list()); ctx =ibv_open_device(dev) pd =ibv_alloc_pd(context) send_cq = ibv_create_cq(ctx, ...); recv_cq = ibv_create_cq(ctx, ...); qp = ibv_create_qp(pd, qp_attr(send_cq, recv_cq, ...)); ibv_modify_qp(qp, attr, attr_mask);
然後就可以用ibv_post_send()和ibv_post_recv()來進行verb的收發了。
這裡有幾個新概念:
ctx,這相當於一個client
pd,protection domain,這個用來隔離多對qp和mr。如果下面是個真正的通訊層,相關埠,地址(IB的地址叫id)等,可以通過ah(address handle)、channel等概念在建立cq的時候作為引數提供給相關的使用者態驅動,讓負責傳送的驅動來處理)
ibv_modify_qp主要是用於通訊的相關細節的設定,ibv_create_qp僅僅分配了資源,要通過這個modify來讓硬體進入工作狀態。
ibv_post_send和recv用於傳送verb,verb承載在一個稱為ibv_send_wr或者ibv_recv_wr的資料結構中,裡面是verb型別和mr的相關細節。verb的型別包括:
enum ibv_wr_opcode { IBV_WR_RDMA_WRITE, IBV_WR_RDMA_WRITE_WITH_IMM, IBV_WR_SEND, IBV_WR_SEND_WITH_IMM, IBV_WR_RDMA_READ, IBV_WR_ATOMIC_CMP_AND_SWP, IBV_WR_ATOMIC_FETCH_AND_ADD, IBV_WR_LOCAL_INV, IBV_WR_BIND_MW, IBV_WR_SEND_WITH_INV, IBV_WR_TSO, };
ULP層的訊息都可以通過IBV_WR_SEND_XXXX來封裝,其他的就是在IB層就可以處理的RDMA操作和原子操作。
【mr名稱空間的進一步理解】
mr基於ctx建立,通過verb進行分享和更新。先看看mr的建立方法:
mr = ibv_reg_mr(pd, addr, length, access);
基本上是直接給定一個虛擬地址,ib負責幫你建立一個控制代碼,建立的mr中包含一個lkey和一個rkey,前者用於本地索引和一個遠端索引。
把通訊的一方稱為A,另一方稱為B。A有一片記憶體要B更新,可以從A發出一個verb,把自己的rkey和地址發給B。B先在自己的記憶體中完成修改,然後用這個記憶體建立一個MR,然後用 IBV_WR_RDMA_WRITE一類的verb,裡面指定A的rkey和地址,就可以遠端更新到A的mr上了。
這個概念如果匹配到加速器上,把B看做是加速器,就是要求B直接更新到A指定下來的MR上,這個語義,接受了這麼多的IB的RDMA語義後,得到的收穫,和我直接對裝置做一個ioctl,沒有任何區別。IB辛辛苦苦做了這麼多工作,就是為了把另一端的記憶體寫到我這邊來,而我的資料本來就在本端,我真正要解決的問題是,讓裝置和CPU看到相同的地址空間,那我增加這麼多複雜度,最終的結果是拿著MR,把實體地址弄下來,交給裝置,讓它按這個實體地址給我填?IB在這裡提供的增值僅僅是gup加上dma_map,這不是所有dma操作本來就要乾的嗎?
而IOMMU的SVA/SVM能力,也不是IB需要的,因為PD和MR的存在,就已經意味這通訊的兩端是兩個實體,和加速器希望把程序的空間整體共享給裝置,讓裝置來幫助完成整個操作,這種場景只有加速器才會發生,RDMA並不會這樣用,換句話說,把另一臺伺服器某個程序的空間全部交給另一臺伺服器的程序進行操控,這樣的行為沒有什麼ULP會用到。
同樣,IB的ODP(On Demand Page)可以成為SVA/SVM的封裝,允許建立MR的時候不gup MR的記憶體,但它並不需要SVA的共享頁表能力。
【小結】
分析到現在為止,我的初步結論是IB的名稱空間不適合加速器,因為加速器並不是一個遠端裝置,它看見的記憶體和CPU看見的記憶體是同一片記憶體,和IB的MR概念中的記憶體是不同的,後者更像是一個記憶體的映象,讓記憶體在多臺裝置之間同步,而加速器,需要是的CPU和加速器圍在一起吃火鍋,你下一筷子,我下一筷子,然後大家都吃個飽。強行把這兩者合在一起,只會增加應用的複雜度。