程 鵬 盧宇彤 高 濤 王晨旭
(高性能計算國家重點實驗室(國防科學技術大學) 長沙 410073)
(國防科學技術大學計算機學院 長沙 410073)
(peng_cheng_13@163.com)
隨著科學與工程應用對計算性能要求的不斷增加,基于CPU的同構系統已經不能滿足計算需求.而圖形處理單元(GPU)、英特爾至強融核(many integrated core, MIC)或其他加速單元在處理高度并行性負載的情況下可以提供遠強于CPU的浮點計算能力,因此使用GPU或MIC等加速單元作為協處理器負責數據密集型負載的異構計算得到了迅速發展[1-5].在2015年6月的TOP500排名中,共有88臺超級計算機為異構系統,使用英特爾Xeon Phi(MIC)協處理器的超級計算機共有33臺,其中也包括排名第一的天河二號[6].近年來,為了簡化異構編程難度,CUDA[7],OpenCL[8]等編程模型也得到了廣泛應用.由于MIC結構是基于現有的X86架構進行設計,采用與CPU相同的X86指令集,支持OpenMP[9],TBB[10]等現有并行編程模型,因此CPU+MIC的異構編程難度小于CPU+GPU的異構編程難度.盡管如此,使用MIC高效進行異構計算還存在2個難點:1)由于CPU與MIC之間沒有共享內存空間,程序員必須區分數據的本地或遠程訪問,并顯式地指定數據在CPU和MIC之間的傳遞情況;2)傳統的加載模式,如英特爾的語言拓展加載模式(LEO)受限于在單個計算節點之內實現,并且無法在MIC之間直接進行傳輸數據.
分塊全局地址空間(PGAS)模型適用于分布式存儲系統,通過提供邏輯上共享的尋址空間和允許所有處理單元訪問位于共享內存空間的數據,簡化數據管理和進程間通信.常見的PGAS模型包括UPC,CAF(co-array Fortran),Titanium[11]和全局數組(global arrays, GA).GA模型[12]基于聚合遠程內存拷貝接口(ARMCI)為分布式存儲系統提供異步單邊通信、共享內存的編程環境,通過允許編程人員創建一個分布在多個計算節點之間的全局共享數組,并對共享數組的直接訪問隱藏數據在不同內存空間的傳輸細節.GA近年來應用廣泛,相比于UPC和CAF,GA允許編程人員顯式控制數據局部性,且GA基于庫實現而不依賴編譯器,具有很好的可移植性.因此,結合異構系統特點實現GA模型可以為CPU與加速單元之間提供邏輯上共享的數據結構,從而隱藏數據在CPU和MIC之間的傳輸細節,達到簡化編程并優化數據傳輸的目的.然而,ARMCI通信接口是GA模型實現的關鍵,也關系到GA模型的可移植性,即在新的系統中使用GA模型前必須結合該平臺特點實現ARMCI接口.而此時尚未有AMRCI針對CPU+MIC異構系統的實現,因此通過標準GA模型簡化異構編程難度并優化數據傳輸的目標難以實現.
為了在CPU+MIC的異構系統中高效實現GA模型,我們在本文中提出了CoGA,并基于MIC上的對稱傳輸接口(symmetric communication interface, SCIF)[13]實現對GA模型的異構拓展.CoGA通過為CPU與MIC之間提供邏輯上共享的全局數組,隱藏數據在CPU與MIC之間的傳輸細節.通過CoGA,編程人員可以像訪問本地數組一樣去訪問全局數組而不必關心數據的具體存儲位置.此外,我們還結合SCIF接口的特點,對CPU與MIC間的數據傳輸進行優化,針對小數據通信特點提供低延遲的通信接口,并允許節點內MIC之間直接進行數據傳遞,而不必像offload模式那樣先將數據傳送回CPU,再由CPU傳遞至另一個MIC.本文的主要貢獻有3點:
1) 結合GA模型特點,針對CPU+MIC異構系統設計并實現了CoGA庫,簡化了異構編程難度;
2) 分析MIC協處理器特點,邏輯上拓展了MIC內存,并結合SCIF接口優化數據傳輸性能;
3) 通過數據傳輸帶寬、消息傳遞延遲和稀疏矩陣乘問題評估CoGA性能并證明其有效性和實用性.
英特爾MIC結構基于X86架構,支持包括OpenMP和MPI在內的多種并行模型,采用C,C++,Fortran等語言進行軟件移植開發,特點以編程簡單(引語方式)著稱,工具鏈豐富.MIC卡含有57~61個核,每個核可以支持4個線程,浮點運算性能超過1TFLOPS,含有512 b的向量寬度,支持8個雙通道GDDR內存控制器,內存大小為6 GB或8 GB[14].由于MIC既可以作為CPU的協處理器也可以單獨作為處理節點,因此MIC與CPU的協同方式非常靈活.常用協同方式包括:加載模式、原生模式和對等模式.在加載模式下,CPU作為主機端并將數據密集型任務加載到MIC上運行;在原生模式下,MIC作為一個獨立的計算節點,程序只在MIC上單獨運行;在對等模式下,MIC設備可以看作與CPU對等的計算節點.在異構計算中,加載(offload)模式是最常用的模式,MIC設備的啟動、關閉和數據傳輸操作都通過編譯指導命令動態實現.
SCIF作為一種簡單高效的對稱傳輸接口,允許數據從MIC設備通過PCIE總線與CPU進行數據傳輸.SCIF應用程序接口提供了2種類型的數據傳輸操作:點對點的發送-接收操作和遠程內存訪問(RMA)操作.發送-接收語義支持阻塞和非阻塞傳輸,一端作為源而另一端作為目的地;RMA操作則支持單邊通信,當知道本地和遠程數據地址的時候,數據就可以被傳輸.2個端點之間成功的數據通信必須通過注冊地址空間,即本地進程注冊其部分地址空間作為遠端進程訪問的窗口,并建立該段地址空間與物理內存的映射關系.
Sreeram等人[15]在其近期工作中通過共享內存,IB verbs和SCIF接口設計了含有MIC的異構節點內的高效數據傳輸方式.Nishkam等人[16]在其近期工作中提出了一組新的指令,以更為寬松的語義添加到原有的指令基礎語言中,從而允許使用者在源代碼中建議而不是指定加載區域.然而,由于CPU與MIC之間沒有共享內存空間,程序員必須區分數據的本地或遠程訪問,并顯式地指定數據在CPU和MIC之間的傳遞情況.此外,如圖1所示,現有的offload模式中,由于MIC設備之間沒有建立直接連接,因此數據在MIC設備之間的傳輸較為復雜,數據必須經CPU中轉才能加載到另一塊MIC上.

Fig. 1 Data transmission in offload mode圖1 offload數據傳輸方式
GA模型是一種PGAS語言,可以為分布式存儲系統提供異步單邊通信、共享內存的編程環境,同時優化整體性能,減少處理器之間顯式的通信開銷.傳統的GA模型通過聚合遠程內存拷貝接口(ARMCI)實現put和get單邊通信,最新版本的GA模型(GA-5-4b)增加了對拓展性通信庫ComEx的兼容性,允許GA通過MPI雙邊通信語義(即MPI_Send和MPI_Recv)實現單邊通信協議,并將默認通信模式由socket改為MPI雙邊通信,從而允許GA模型在任何支持MPI編程模型的平臺上實現[17].
近期的使用C++庫拓展并行編程模型研究包括UPC++[18],Coarrays C++[19-20]和Charm++[21]等.Manojkumar等人[22]提出了在Blue GeneP超級計算機上通過IBM DCMF(deep computing messaging framework)框架實現GA模型.其中,ARMCI put和get操作通過DCMF應用接口實現并表現出比原本的GA和MPI接口更好的性能.Daniel等人[23]則基于PGAS動態消息傳遞范例提出了global futures,增加可拓展性的同時保持與GA和MPI兼容,通過一系列API允許用戶定義的計算任務(futures)在擁有GA數據分塊的位置遠程執行.James等人[24]則通過協調MPI RMA和PGAS模型語義,通過MPI單邊通信實現GA模型.
然而,現有的offload模式下,編程人員必須區分數據是本地或遠程訪問,并顯式地指定數據在CPU和MIC之間的傳遞情況,而且同一節點內MIC之間無法直接進行通信.此外,迄今為止還未出現在異構系統中使用GA模型簡化CPU和MIC之間顯式的數據傳輸的方案,現有的GA模型也沒有針對MIC結構的高效實現.而若GA模型在CPU+MIC異構系統中通過MPI雙邊通信網絡模式進行數據傳輸必然導致性能低下.
為了能夠在CPU+MIC的異構系統中實現GA模型并保證數據傳輸性能,我們提出CoGA,基于SCIF接口在CPU與MIC之間高效實現GA模型,通過提供邏輯上共享數組隱藏數據傳輸細節,簡化異構編程難度.本節簡要介紹CoGA的拓展方式及API接口.
圖2對比了GA與CoGA的軟件層次結構.原本的GA模型使用Fortran或C語言等應用接口實現對分布式共享數組的管理,通過ARMCI或ComEx動態庫內部的網絡通信接口,如MPI雙邊通信接口,調用網絡驅動及操作系統庫實現內存管理和數據傳輸等操作;而CoGA則通過SCIF接口直接調用網絡驅動及操作系統庫,更高效地實現對CPU和MIC的內存管理及CPU與MIC間的數據傳輸.

Fig. 2 Comparison between GA and CoGA圖2 GA和CoGA軟件層對比
表1總結了CoGA現有的API接口.其主要分為2大類,coGA_Initialize等接口是基于原本的GA接口進行的拓展,實現了CoGA庫的初始化和終止、全局數組的創建與銷毀、put和get單邊通信等操作,這些接口在實現原有功能的同時還結合MIC結構與SCIF傳輸特點進行了優化;coGA_Reg等接口則是為了簡化數組操作并優化數據傳輸所拓展的新接口,包括小數據的發送與接收、快速獲取本地緩存指針等操作.通過這些接口,編程人員可以在異構系統中高效使用CoGA模型實現內存管理和數據傳輸,達到簡化編程而不影響性能的目的.

Table 1 Summary of GA and CoGA Function Call表1 GA與CoGA接口對比
本節對原有GA模型內存管理方式進行簡要分析,并針對CPU+MIC的異構系統提出CoGA模型的內存管理方式.
GA模型通過不同的函數調用實現全局數組對象在對稱多處理節點上的規則和不規則分布,動態分配大部分內存空間用于存儲新創建的全局數組數據或者作為其他操作的臨時緩存,并在程序運行結束后釋放.在提供共享內存的系統上,內存空間由ARMCI動態庫管理,其首先從操作系統中劃分大段共享內存空間,之后再根據GA操作分配或釋放內存.在程序終止之前,ARMCI庫所管理的大段內存空間不會被釋放.
然而,由于MIC設備的時鐘頻率低于CPU,分配同樣大小的內存空間時,MIC上的內存分配開銷比CPU的內存分配開銷更大.為了減少內存分配次數進而降低整體開銷,CoGA通過函數coGA_Create為全局數組分配固定內存空間,一旦全局數組創建,該數組就可以被用于存儲不同數據直至數組被銷毀.
函數coGA_Create的語義與其他標準內存分配調用的語義類似,參與計算的每個進程都必須執行該函數,并根據參數分配相應的內存空間.參數type表示全局數組的數據類型,如整型、浮點型等;參數size表示全局數組的整體長度;參數dis[n]則表示數據的分布情況.編程人員可以通過dis[n]參數直觀地控制數據如何分布在CPU和MIC上.圖3說明了函數coGA_Create對內存的分配和注冊.CPU端和MIC端都執行該函數,并為全局數組分布本地內存空間.CPU的進程號為0,CPU所分配的內存大小為dis[0]-0;MIC的進程號為1,則MIC上分配的內存大小為dis[1]-dis[0].全局數組的總大小為dis[1]-0.在異構系統上創建全局數組后,為便于CoGA接口通過SCIF接口實現遠程內存訪問,函數coGA_Create內部調用接口scif_register將各進程所分配的全局數組本地內存空間注冊為遠程訪問地址空間,并建立注冊地址空間與物理頁面的固定映射關系,從而允許遠端進程直接對該部分地址空間進行讀寫操作.

Fig. 3 Memory allocation of GA and CoGA圖3 GA和CoGA內存分配對比
為了保證CoGA庫一旦初始化就可以實現對CPU和MIC的內存管理并進行遠端通信,我們使用函數coGA_Initialize負責初始化CoGA庫并通過SCIF接口建立CPU與MIC的連接:CPU和MIC各自創建新的端口并將地址綁到其本地節點;CPU端的端口作為監聽端接收MIC端所發送的連接請求,請求響應后CPU與MIC可成功建立連接.在SCIF實現中,每個建立連接的端口稱為端點,每個計算節點可與多個不同節點建立多個連接,而且每個連接都通過其各自的端點完成,即一個節點上可以擁有多個端點,各個端點負責與其連接的對應端點間通信.
CoGA的核心思想是隱藏數據傳輸細節的同時為CPU和MIC提供對等的API接口.圖4說明了CoGA模型的數據傳輸方式.MIC設備在CoGA庫初始化時通過SCIF接口直接建立連接,進而允許用戶調用CoGA函數實現數據在MIC間的直接傳輸.

Fig. 4 Data transmission in CoGA圖4 CoGA數據傳輸
CoGA的put和get操作包含完成單邊通信的參數,如全局數組的句柄、數據的上下邊界及本地數組的指針.在調用put和get操作后,進程首先對數據邊界和全局數組分布情況進行對比,再根據數據在遠程或本地選擇不同傳輸方式.put和get操作定義2種不同的完成方式:本地傳輸和遠程傳輸.本地傳輸是指數據在CPU或MIC內部傳遞,可通過函數memcpy實現;遠端傳輸則意味著數據在CPU和MIC之間進行傳輸,可以通過SCIF RMA訪問操作實現.SCIF提供2組接口完成RMA訪問:scif_readfrom,scif_writeto和scif_vreadfrom,scif_vwriteto.接口scif_readfrom,scif_writeto在本地注冊地址空間和遠端注冊地址空間之間完成數據的讀寫訪問,而接口scif_vreadfrom和scif_vwriteto則將本地用戶空間作為參數與遠端注冊地址空間進行數據傳輸操作,即數據可以直接從用戶虛擬地址發送到遠端數組對象而無需對該段虛擬地址進行注冊.如果已知本地緩存將被使用多次作為RMA訪問的源或者目的地,那么scif_readfrom,scif_writeto可提供更好的傳輸性能;反之,若本地緩存僅僅是源或一次傳輸的目的地,那么scif_vreadfrom,scif_vwriteto則能避免注冊窗口、數據傳輸、釋放窗口的復雜操作,減少注冊開銷.
為了保證傳輸性能的同時不影響簡易性,我們同時提供這2種完成方式:在put和get操作中增加flag標志位,flag值默認為-1,若用戶未注冊本地臨時緩存,則put和get操作自動調用scif_vwriteto,scif_vreadfrom在本地虛擬地址和遠端注冊地址之間完成數據傳輸;當用戶使用函數coGA_Reg提前為本地臨時緩存注冊地址空間后,返回的flag值即為注冊地址空間偏移,put或get操作自動調用scif_writeto或scif_readfrom,在注冊地址空間之間進行數據傳輸.當需要進行遠端數據傳輸時,CoGA函數直接將參數傳遞給SCIF接口,包括源地址、遠端注冊地址空間偏移和拷貝數據長度.
此外,CoGA還提供函數coGA_GetLocalBuffer允許進程獲取共享數組的本地緩存指針,從而避免冗余的數據拷貝.
考慮到程序運行過程中,CPU和MIC可能需要頻繁地進行小數據通信,而且MIC端計算完成后,MIC與MIC或者MIC與CPU之間的小數據通信無法避免.傳統的offload模式下,編程人員必須通過編譯指導命令來指明傳輸的數據,而且數據無論大小,傳輸的數據都是按照4 KB對齊,即使數據只有1 B,MIC端也會為該數據分配4 KB的內存空間.在需要進行頻繁小數據通信的情況下,offload模式一方面會使得代碼顯得較為冗長;另一方面也會造成空間浪費,并且導致傳輸延遲增加.
在函數coGA_Put和coGA_Get實現過程中,由于數據必須先放入全局數組對象才能使用,對于小數據傳遞(通常小于4 KB),函數coGA_Put和coGA_Get可能顯得過于復雜.為降低傳輸延遲,我們基于SCIF點對點通信實現了在CPU和MIC間直接傳遞短消息的函數:coGA_sendMsg和coGA_recvMsg.用戶可以直接調用這2個函數在任意2個建立連接的端點之間進行通信.此外,相比于多個連接共享一個消息隊列的情況,CoGA實現中每一對連接的端點都包含2個消息隊列,每個消息隊列負責一個通信方向,因此發送消息的進程不會被其他進程阻礙.coGA_sendMsg和coGA_recvMsg所構成的消息傳遞層主要針對小消息傳遞,而不是大塊數據.盡管它能傳遞最大為(231-1)B的消息,由于消息隊列較短,一條長消息會被轉化為多個短消息進行傳遞,而且在傳送過程中每個短消息都會產生延遲,因此傳遞長消息會使總體延遲急劇增大.
CoGA使用了與GA類似的一致性模型:
1) 只有在訪問全局數組相同或重疊區域時,函數coGA_Put和coGA_Get必須嚴格保證執行順序;反之,訪問區域不重疊或訪問不同全局數組時,put和get操作允許以任意順序完成.
2) CoGA模型的put操作可通過2種方式訪問全局數組,即本地訪問和遠程訪問.put操作在本地訪問完成后立即返回,這也意味著此時數據已經從本地拷貝完畢但可能尚未到達遠端.
CoGA提供2種同步函數:coGA_Fence是局部操作,用于等待函數調用端進程的操作完成;coGA_Sync則是集體操作,對所有進程進行同步并保證CPU和MIC端的CoGA操作完成.coGA_Fence操作基于SCIF RMA同步操作實現:首先通過接口scif_fence_mark()標記那些已經開始但尚未完成的RMA訪問操作,并將返回的句柄傳遞給scif_fence_wait();之后再調用接口scif_fence_wait()等待被標記的RMA訪問完成.
我們基于SCIF,一種類似socket、用于主機端和MIC之間傳遞數據的對稱傳輸接口,在CPU+MIC的異構系統上實現CoGA.本節主要通過帶寬測試、延遲測試和稀疏矩陣乘(sparse matrix vector multiply, SpMV)問題評估CoGA性能.
圖5通過一個簡單的例子說明CoGA編程與offload編程的差異.在offload模式中,同一節點內的MIC之間無法直接進行傳輸數據,因此數據必須
if(rank=1)*MIC0*
{
coGA_sendMsg(2,p,k);*sent message to MIC1*
}
if(rank=2)*MIC1*
{
coGA_recvMsg(1,p,k);*receive message from MIC0*
}
?
(a) CoGA
?
#pragma offload target (mic:0) in (p:length(i))
{
}
#pragma offload target (mic:0) out (p:length(i))
{
}
#pragma offload target (mic:1) in (p:length(i))
{
}
?
(b) offload
Fig. 5 Programming example
圖5 編程對比
coGA_sendMsg
coGA_recvMsg
為了更好地了解CoGA的實用性和具體性能,我們測試了函數coGA_Put的數據傳輸帶寬和coGA_sendMsg發送小消息的延遲,并測試了在同一節點內2個MIC之間進行傳輸傳遞時CoGA接口的實用性,最后通過稀疏矩陣乘問題測試其整體性能.測試工作在由2個CPU和4個MIC組成的異構系統上進行,其中CPU型號為Intel Xeon E5-2670,2.60 GHz;MIC型號為Xeon Phi 3100,1.1 GHz;MPI版本為MPICH-3.2b1,網絡模式為SCIF;GA版本為GA-5-4b,網絡模式為MPI雙邊通信.

Fig. 6 Bandwidth test圖6 帶寬測試
首先,我們分別測試CoGA模型、GA模型和offload模式下從CPU傳輸數據至MIC端的數據傳輸帶寬,其中coGA_Put包含2種遠程數據傳輸方式,即scif_writeto和scif_vwriteto.測試結果如圖6所示:GA_Put沒有結合MIC上SCIF接口特點而是基于MPI雙邊通信實現,數據經過緩沖才發送至MIC端,因此帶寬最低;函數coGA_Put(scif_writeto)實現過程中,數據從本地注冊空間直接發送至遠端注冊空間,帶寬性能優于coGA_Put(scif_vwriteto);coGA_Put(scif_writeto)在數據規模小于3.7 MB時,帶寬低于offload模式帶寬,這是因為put操作啟動開銷較大,需要比較數據傳輸范圍并決定相應的數據傳輸方式,而當數據規模不斷增加后,這部分開銷所占的比例也不斷減小,因此數據大于4 MB后coGA_Put帶寬性能與offload帶寬相當,甚至略高于offload模式.
其次,我們測試了在CPU與MIC之間進行數據通信時,函數coGA_sendMsg發送短消息的延遲,并與原本GA模型和offload模式進行對比.在發送短消息(小于4 KB)時,數據所需的內存空間通常由系統自動分配,因此在測試時我們也采用系統自動分配內存空間的方式進行.offload模式下,從源進程發送到目標進程的數據至少是4 KB對齊的,這也導致了其發送小消息效率低下.而coGA_sendMsg和GA_Put根據變量大小分配合適空間,因此延遲較低.測試結果如圖7所示:當數據小于4 KB時,coGA_sendMsg和GA_Put的延遲要遠小于offload模式;而coGA_sendMsg通過SCIF消息傳遞層傳遞小消息,沒有數據緩沖開銷,因此延遲也低于GA_Put;但當數據不斷增加大于4 KB后,GA_Put帶寬低于offload模式,且SCIF消息傳遞層只適合發送小消息,因此coGA_sendMsg和GA_Put延遲急劇增加.

Fig. 7 Latency test圖7 延遲測試
此外,我們還測試了在MIC之間進行數據通信時offload模式與CoGA接口的延遲表現.由于傳輸數據較大,此時我們提前為傳輸數據分配內存空間.測試結果如圖8所示:隨著數據規模增加,offload模式與coGA_Put延遲也不斷增加,而且coGA_Put延遲整體小于offload模式延遲.由于此時事先分配好內存空間,因此offload模式下MIC間的傳輸延遲相對于未提前分配內存情況下offload模式的傳輸延遲減小.但是offload延遲包含MIC0傳輸至CPU加上CPU傳輸至MIC1的時間,因此總延遲較大;相比之下,coGA_Put允許數據直接從MIC0傳輸至MIC1,因此延遲較低.

Fig. 8 Latency test between MICs圖8 MIC間延遲測試

Fig. 9 SpMV performance comparison圖9 稀疏矩陣乘性能測試
最后,我們通過稀疏矩陣乘問題評估CoGA整體性能.矩陣1的規模為116 158×116 158,包含8 516 500個非零點;矩陣2的規模為259 156×259 156,包含4 429 042個非零點.這2個矩陣都存儲為CSR格式,CPU和MIC各自負責處理一半的數據.CoGA和offload模式下測試結果如圖9所示:CoGA和offload模式的數據傳輸開銷基本相同,說明了CoGA通過SCIF進行傳輸數據的性能與offload性能相當;與預測相符,計算開銷也基本相同.
我們面向異構系統對GA進行拓展,結合MIC上的SCIF接口實現了CoGA,從而在CPU和MIC之間實現共享數據結構.CoGA提供的API接口隱藏數據傳輸細節并允許編程人員忽略數據的具體位置而直觀操作共享數據,實現了MIC之間直接的數據通信,進而簡化了編程難度.此外,CoGA基于庫實現的特點也保證了其與OpenMP和MPI等并行編程模型的兼容性.我們定義了2種數據傳輸方式:本地訪問通過函數memcpy實現,遠端訪問通過SCIF RMA接口實現.我們對CoGA的傳輸帶寬的測試也表明了CoGA的實際性能遠高于原本GA模型;此外,我們還通過函數coGA_sendMsg和coGA_recvMsg優化小數據發送,降低通信延遲.CoGA在具有簡單和高效特點的同時也存在不足,如現在API接口不夠豐富并只能應用于CPU+MIC的異構系統.在下一步工作中,我們將繼續完善CoGA庫特性并嘗試將其拓展至GPU.