葉雨曦,傅 游,梁建國(guó),孟現(xiàn)粉,劉 穎,花 嶸
(1.山東科技大學(xué) 計(jì)算機(jī)科學(xué)與工程學(xué)院,山東 青島 266590; 2.中科寒武紀(jì)科技股份有限公司, 北京 100191; 3. 中國(guó)科學(xué)院計(jì)算技術(shù)研究所,北京 100190)
任務(wù)并行編程模型把任務(wù)作為并行的基本單位,為編程人員提供任務(wù)劃分和任務(wù)同步接口。編程人員需要考慮如何對(duì)應(yīng)用程序進(jìn)行合理的任務(wù)劃分,而任務(wù)具體的要在哪個(gè)物理核上執(zhí)行以及如何實(shí)現(xiàn)任務(wù)之間的同步都由運(yùn)行時(shí)系統(tǒng)完成。任務(wù)并行編程模型可看作底層體系結(jié)構(gòu)和上層程序應(yīng)用之間的橋梁,向上隱藏并行處理的細(xì)節(jié),提高編程層次,簡(jiǎn)化并行編程;向下充分利用硬件資源,高效正確地執(zhí)行并行程序[1]。支持任務(wù)并行調(diào)度的并行編程模型主要有MIT的Cilk[2]/Cilk++[3]、Intel的Threading Building Blocks(TBB)[4]、BSC的OmpSs[5]、微軟的Task Parallel Library(TPL)[6]等。
中國(guó)科學(xué)院計(jì)算技術(shù)研究所并行編譯組提出了一種面向網(wǎng)格應(yīng)用,以數(shù)據(jù)為中心,應(yīng)用于多核、眾核平臺(tái)上的任務(wù)并行編程模型AceMesh[7-10]。AceMesh主要包括編譯器和任務(wù)調(diào)度系統(tǒng)。AceMesh編譯器作為一個(gè)源到源編譯框架[5],根據(jù)平臺(tái)特性將帶指導(dǎo)語(yǔ)句的程序代碼自動(dòng)生成指定平臺(tái)的并行化程序,編程人員只需要關(guān)注指導(dǎo)語(yǔ)言和應(yīng)用本身即可。AceMesh任務(wù)調(diào)度系統(tǒng)采用基于有向無(wú)環(huán)圖[11](directed acyclic graph,DAG)的動(dòng)態(tài)任務(wù)調(diào)度,能自動(dòng)發(fā)掘結(jié)構(gòu)化網(wǎng)格應(yīng)用中存在的數(shù)據(jù)驅(qū)動(dòng)的任務(wù)圖并行性,其性能較其他的任務(wù)并行編程模型優(yōu)越[12-13]。
AceMesh作為數(shù)據(jù)流驅(qū)動(dòng)的任務(wù)并行模型,細(xì)粒度的任務(wù)劃分會(huì)使其構(gòu)圖開(kāi)銷顯著增加,降低應(yīng)用的并行可擴(kuò)展性。王松等[14]提出了并發(fā)構(gòu)圖的方法,對(duì)AceMesh構(gòu)圖進(jìn)行了優(yōu)化,但該方法在訪存、內(nèi)存申請(qǐng)和任務(wù)收集方面存在一定的問(wèn)題,導(dǎo)致AceMesh構(gòu)圖過(guò)程開(kāi)銷仍過(guò)大。為提高構(gòu)圖效率,本研究從減少通信開(kāi)銷、設(shè)計(jì)內(nèi)存池和優(yōu)化任務(wù)收集策略等角度對(duì)AceMesh構(gòu)圖過(guò)程進(jìn)行優(yōu)化,通過(guò)數(shù)據(jù)測(cè)試驗(yàn)證構(gòu)圖優(yōu)化的可行性和有效性。
“神威·太湖之光”[13-15]計(jì)算機(jī)系統(tǒng)采用“申威26010”異構(gòu)眾核處理器,芯片工作頻率1.45 GHz,峰值運(yùn)算速度3.168 TFLOPS,采用了針對(duì)該處理器定制的64位申威指令系統(tǒng),與X86指令系統(tǒng)不兼容。“申威26010”異構(gòu)眾核處理器架構(gòu)如圖1所示。
“申威26010”異構(gòu)眾核處理器集成了4個(gè)運(yùn)算核組,共260個(gè)運(yùn)算核心,核組間支持Cache一致性,通過(guò)高速片上網(wǎng)絡(luò)相連。每個(gè)核組包含1個(gè)運(yùn)算控制核心(management processing element, MPE)即主核、1個(gè)運(yùn)算核心(computing processing elements,CPE)即從核陣列和1個(gè)存儲(chǔ)控制器(memory controller,MC),通過(guò)iMC與主存相連。眾核處理器還集成系統(tǒng)接口總線用于連接標(biāo)準(zhǔn)PCIe接口,實(shí)現(xiàn)片間直連和互連,管理與維護(hù)接口負(fù)責(zé)系統(tǒng)管理、維護(hù)和測(cè)試。4個(gè)核組和系統(tǒng)接口總線通過(guò)群間傳輸網(wǎng)絡(luò)實(shí)現(xiàn)存儲(chǔ)共享和通信。主核具有兩級(jí)片上存儲(chǔ)層次:L1級(jí)數(shù)據(jù)和指令Cache、共享的L2級(jí)Cache。1個(gè)計(jì)算核組中的64個(gè)從核共享L2級(jí)指令Cache。每個(gè)從核具有私有L1級(jí)指令Cache和用于數(shù)據(jù)存儲(chǔ)的LDM空間。應(yīng)用程序由主核啟動(dòng),借助高性能線程庫(kù)Athread將計(jì)算任務(wù)加載到從核執(zhí)行,雙方通過(guò)同步接口協(xié)同。
AceMesh任務(wù)調(diào)度系統(tǒng)的工作機(jī)制如圖2所示。用DAG將計(jì)算任務(wù)之間的依賴關(guān)系表達(dá)出來(lái)的過(guò)程稱為構(gòu)圖,利用構(gòu)建的DAG分析保持?jǐn)?shù)據(jù)原有依賴關(guān)系的正確任務(wù)執(zhí)行順序,并對(duì)任務(wù)進(jìn)行調(diào)度和計(jì)算的過(guò)程,稱為圖執(zhí)行。DAG的構(gòu)建由主核獨(dú)自完成,執(zhí)行由主核和從核共同完成。
圖2 AceMesh任務(wù)調(diào)度系統(tǒng)工作機(jī)制
構(gòu)圖過(guò)程包括兩步:一是數(shù)據(jù)域的劃分及計(jì)算任務(wù)封裝。根據(jù)代碼訪問(wèn)數(shù)據(jù)區(qū)域的不同,將整個(gè)數(shù)據(jù)域劃分成若干個(gè)數(shù)據(jù)區(qū)域。為減少通信量,盡可能把具有依賴關(guān)系的數(shù)據(jù)區(qū)域分配到一個(gè)數(shù)據(jù)塊中,并將數(shù)據(jù)塊、對(duì)該數(shù)據(jù)塊的操作和需要通信的鄰居節(jié)點(diǎn)封裝成一個(gè)計(jì)算任務(wù);二是計(jì)算任務(wù)注冊(cè)。為了更好地發(fā)掘緩存中的數(shù)據(jù)重用性,初始化計(jì)算任務(wù)的親和性設(shè)置,根據(jù)最近、可達(dá)的數(shù)據(jù)訪問(wèn)信息如變量地址、鄰居關(guān)系、讀寫信息等,構(gòu)建正在注冊(cè)的計(jì)算任務(wù)與前驅(qū)計(jì)算任務(wù)間的數(shù)據(jù)依賴邊,并記錄為后繼任務(wù);將沒(méi)有前驅(qū)的任務(wù)存放在無(wú)前驅(qū)任務(wù)列表need_spawn_tasks中,作為最先調(diào)度的任務(wù);查找無(wú)后繼任務(wù)并將其存放在無(wú)后繼任務(wù)列表end_tasks中,用于檢查DAG執(zhí)行結(jié)束狀態(tài)。
在構(gòu)建DAG的過(guò)程中存在下面3個(gè)問(wèn)題:
1) DAG構(gòu)建由主核獨(dú)立完成,為了在構(gòu)建完成后喚醒從核,主核需要在主存上維護(hù)一個(gè)共享變量is_run。主核構(gòu)建DAG時(shí)將is_run賦值為0,構(gòu)建完成后將is_run賦值為1;處于等待狀態(tài)的從核會(huì)訪問(wèn)is_run的值,若值為1則從核進(jìn)入工作狀態(tài),執(zhí)行計(jì)算任務(wù)。因此主核構(gòu)建DAG期間所有的從核都在不斷地訪問(wèn)主存,造成了很大的訪存開(kāi)銷。
2) 系統(tǒng)使用new()、malloc()等申請(qǐng)分配內(nèi)存,會(huì)調(diào)用操作系統(tǒng)的系統(tǒng)調(diào)用函數(shù)mmap2(),時(shí)間開(kāi)銷大,應(yīng)盡量減少系統(tǒng)調(diào)用的次數(shù)。AceMesh任務(wù)調(diào)度系統(tǒng)中大量地使用動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu),如任務(wù)的繼承類、任務(wù)參數(shù)和任務(wù)后繼列表等,當(dāng)任務(wù)的總數(shù)很多時(shí),這些動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)的分配和釋放造成大量的系統(tǒng)開(kāi)銷。
3) 無(wú)后繼任務(wù)列表end_tasks是基于哈希表實(shí)現(xiàn)的,用于檢查DAG執(zhí)行結(jié)束狀態(tài)。每個(gè)新任務(wù)注冊(cè)后都需要對(duì)end_tasks列表執(zhí)行添加和查找操作,每次更新后存在后繼的任務(wù)需要從end_tasks列表中刪除。若無(wú)后繼任務(wù)占比較低,隨著注冊(cè)任務(wù)數(shù)增加,end_tasks列表的修改和查找開(kāi)銷會(huì)變得越來(lái)越大。
AceMesh任務(wù)調(diào)度系統(tǒng)先構(gòu)圖后調(diào)度,合理高效的構(gòu)圖方法可以有助于減少線程的等待時(shí)間,提高程序的執(zhí)行效率。本節(jié)針對(duì)第2節(jié)中AceMesh構(gòu)圖過(guò)程存在的3個(gè)問(wèn)題進(jìn)行構(gòu)圖優(yōu)化。
申威26010異構(gòu)眾核處理器單核組存儲(chǔ)器訪問(wèn)方式如圖3所示。每個(gè)核組的從核可以直接訪問(wèn)主存和局存,從核訪問(wèn)主存有g(shù)ld/gst離散訪存和DMA批量式訪存兩種方式。主核不能直接訪問(wèn)主存,但是可以通過(guò)I/O訪問(wèn)局存,借助宏h2ldm(elment,penum,cgnum)函數(shù)直接對(duì)從核LDM變量進(jìn)行I/O存取操作,其中element是運(yùn)算核心程序內(nèi)的局存私有變量,penum是核號(hào),cgnum是核組號(hào)。
圖3 單核組存儲(chǔ)器訪問(wèn)圖
AceMesh任務(wù)調(diào)度系統(tǒng)中從核訪問(wèn)共享變量is_run的方式為gld/gst離散訪存。在訪存帶寬方面,gld/gst方式單個(gè)核組內(nèi)的訪存帶寬為1.5 GB/s,DMA方式單個(gè)核組內(nèi)的訪存帶寬為26 GB/s;在延遲方面,gld/gst方式延遲278 cycle;DMA方式延遲29 cycle。可以看出,與gld/gst方式相比,DMA方式帶寬利用率高,延遲小。
但是DMA批量式訪存也存在一定的局限性。圖4所展示的單核組DMA帶寬增長(zhǎng)趨勢(shì)表明,只有當(dāng)單次拷貝的數(shù)據(jù)塊大于256 B而且主存地址256 B對(duì)齊時(shí),DMA方式才能有效利用訪存帶寬。另一方面,從核在構(gòu)圖期間不斷地進(jìn)行變量的數(shù)據(jù)傳輸,會(huì)占用訪存帶寬。因此DMA方式不是有效的優(yōu)化方式。
圖4 單核組DMA訪存帶寬
為了減少?gòu)暮嗽L問(wèn)主存的帶寬開(kāi)銷,將主存上的共享變量is_run改為從核LDM私有變量,每個(gè)從核維護(hù)一個(gè)自己的通信變量is_run。如圖5所示,主核構(gòu)圖完成后,通過(guò)h2ldm(is_run,i,cgid)=1訪問(wèn)每個(gè)從核的LDM空間并將私有變量is_run賦值為1。從核判斷自己維護(hù)的私有變量is_run的值為1后開(kāi)始執(zhí)行任務(wù)。當(dāng)任務(wù)執(zhí)行完成后,主核再通過(guò)h2ldm(is_run,i,cgid)=0通知從核停止任務(wù)執(zhí)行,等待下一個(gè)任務(wù)圖的執(zhí)行。將is_run變量改為從核私有變量減少了從核訪問(wèn)主存的次數(shù),有效降低了構(gòu)圖過(guò)程中的訪存開(kāi)銷。
圖5 優(yōu)化后的主、從核通信流程
AceMesh允許用戶為一個(gè)應(yīng)用程序設(shè)置多個(gè)并行區(qū),隨著應(yīng)用計(jì)算規(guī)模的增加,單個(gè)并行區(qū)內(nèi)提交的任務(wù)數(shù)也不斷增加,這些并行任務(wù)提交時(shí)申請(qǐng)的內(nèi)存空間將在并行區(qū)結(jié)束后釋放。頻繁的內(nèi)存申請(qǐng)和釋放會(huì)帶來(lái)嚴(yán)重的內(nèi)存碎片問(wèn)題,同時(shí)malloc()和free()函數(shù)的使用也會(huì)造成很大的時(shí)間開(kāi)銷。
為解決上述問(wèn)題,引入內(nèi)存池管理存儲(chǔ)資源。內(nèi)存池實(shí)質(zhì)上是一種內(nèi)存分配方式,在真正使用內(nèi)存之前,通過(guò)調(diào)用系統(tǒng)內(nèi)存分配函數(shù)預(yù)先申請(qǐng)適當(dāng)大小的內(nèi)存塊作為備用,之后應(yīng)用程序?qū)?nèi)存的分配和釋放則通過(guò)這個(gè)內(nèi)存池來(lái)完成。當(dāng)有新的內(nèi)存需求時(shí),就從內(nèi)存池中分出一部分內(nèi)存塊,若內(nèi)存塊不夠,需要?jiǎng)討B(tài)擴(kuò)展時(shí),再繼續(xù)申請(qǐng)新的內(nèi)存塊。
本研究提出一種采用內(nèi)存池管理內(nèi)存分配的方法,其內(nèi)存池的申請(qǐng)和釋放狀態(tài)轉(zhuǎn)換圖如圖6所示。內(nèi)存池中可以申請(qǐng)多個(gè)內(nèi)存塊,申請(qǐng)的內(nèi)存塊中包含可分配的空閑節(jié)點(diǎn),所有空閑塊由內(nèi)存池空閑列表管理,若空閑塊被分配出去則將其從表中刪除;若已分配的內(nèi)存塊被釋放,則將其重新插入到空閑列表的頭部。如果內(nèi)存塊中的空閑塊不足,則申請(qǐng)新的內(nèi)存塊。內(nèi)存池的分配和釋放都是以固定大小的內(nèi)存塊為單位,不會(huì)產(chǎn)生內(nèi)存碎片,因此可以有效避免內(nèi)存泄露。
圖6 內(nèi)存池內(nèi)存分配狀態(tài)轉(zhuǎn)換圖
內(nèi)存池和內(nèi)存塊的數(shù)據(jù)結(jié)構(gòu)為:
typedef struct node{
void* data;
struct node* next;
}node;//內(nèi)存塊
typedef struct MemPool{
void* to; //指向當(dāng)前空閑塊的尾部
void* from; //指向當(dāng)前空閑節(jié)點(diǎn)的可用位置
struct node* AllocatedMemNode; //指向內(nèi)存塊的已分配列表
struct node* FreeMemNode; //指向內(nèi)存塊的空閑列表
}MemPool;//內(nèi)存池
根據(jù)內(nèi)存池的工作流程,內(nèi)存池申請(qǐng)算法如下。
Algorithm 1內(nèi)存池申請(qǐng)算法輸入:需要使用的內(nèi)存空間大小data_size,一個(gè)內(nèi)存塊包含的內(nèi)存節(jié)點(diǎn)數(shù)num_node,每個(gè)內(nèi)存節(jié)點(diǎn)的存儲(chǔ)空間大小node_size輸出:內(nèi)存池變量Mpool1 //內(nèi)存池初始化2 struct MempoolMpool3 Mpool.AllocatedMemNode = NULL4 Mpool.FreeMemNode = NULL5 //為內(nèi)存池加入新的內(nèi)存塊6 byte *new_memory_block = (byte *)malloc(node_size * sizeof(byte))7 do i = 1, num_node8 申請(qǐng)一個(gè)新的內(nèi)存塊node[i]9 node_i.data = new_memory_block + i * node_size10 if (i == 1) then continue11 else 上一個(gè)內(nèi)存塊node[i-1].next指向node[i]12 endif13 end do14 if (Mpool.FreeMemNode) //空閑列表不為空14 then將新內(nèi)存節(jié)點(diǎn)鏈表加入到FreeMemNode列表15 else{16 Mpool.FreeMemNode = node[1]17 Mpool.from = node[1].data 18 Mpool.to = node[1].data + node_size}19 end if
內(nèi)存池分配算法如下。
Algorithm 2內(nèi)存池分配算法輸入:已分配好的內(nèi)存池變量Mpool,需要申請(qǐng)的內(nèi)存大小data_size,需要申請(qǐng)空間的指針變量data_point輸出:分配好內(nèi)存空間的指針data_point1 int node_n, node_size = Mpool.to - Mpool.from2 根據(jù)node_size和data_size計(jì)算需要分配的節(jié)點(diǎn)數(shù)node_n3 void * point = Mpool.FreeMemNode->data4 do i = 1, node_n5 if (Mpool.FreeMemNode == NULL)//當(dāng)前內(nèi)存池內(nèi)沒(méi)有空閑節(jié)點(diǎn)6 then 為內(nèi)存池加入新的內(nèi)存塊7 endif8 將Mpool.FreeMemNode第一個(gè)節(jié)點(diǎn)取出9 在Mpool.AllocatedMemNode加入新分配的節(jié)點(diǎn)10 end do11 data_point = point
從內(nèi)存池的申請(qǐng)和分配算法中可以看出,只在新的內(nèi)存節(jié)點(diǎn)申請(qǐng)時(shí)用到malloc()函數(shù),內(nèi)存節(jié)點(diǎn)的分配則是通過(guò)傳遞指針和修改鏈表來(lái)完成的,減少了malloc()和free()函數(shù)的調(diào)用次數(shù),從而降低內(nèi)存申請(qǐng)的時(shí)間開(kāi)銷。
無(wú)后繼任務(wù)列表end_tasks是為了檢測(cè)DAG是否執(zhí)行結(jié)束而引入的一個(gè)任務(wù)集,用來(lái)記錄應(yīng)用程序的所有無(wú)后繼任務(wù)。AceMesh任務(wù)調(diào)度系統(tǒng)中end_tasks列表的數(shù)據(jù)結(jié)構(gòu)為unordered_set,利用哈希表實(shí)現(xiàn)。哈希表是根據(jù)鍵值進(jìn)行直接訪問(wèn)的數(shù)據(jù)結(jié)構(gòu),通過(guò)相應(yīng)的哈希函數(shù)處理關(guān)鍵字得到相應(yīng)的鍵值,鍵值對(duì)應(yīng)著一個(gè)特定位置,用該位置來(lái)存取相應(yīng)的信息,能以較快的速度獲取關(guān)鍵字的信息,具有可快速查找、刪除和添加的優(yōu)點(diǎn)。在AceMesh構(gòu)圖機(jī)制中,end_tasks列表的收集方法是在每個(gè)任務(wù)注冊(cè)時(shí)將其添加到end_tasks,若發(fā)現(xiàn)任務(wù)有后繼,再?gòu)膃nd_tasks中查找并刪除。
圖7是對(duì)航天飛行器應(yīng)用中部分代碼進(jìn)行任務(wù)劃分后得到的DAG。該部分代碼包含多個(gè)循環(huán)計(jì)算,通過(guò)對(duì)循環(huán)的劃分來(lái)分配計(jì)算任務(wù)。每個(gè)圓圈代表一個(gè)計(jì)算任務(wù),圓圈內(nèi)第一個(gè)數(shù)字代表并行區(qū)內(nèi)的循環(huán)的序號(hào),第二個(gè)數(shù)字代表計(jì)算任務(wù)在循環(huán)內(nèi)的序號(hào),每個(gè)任務(wù)通過(guò)箭頭指向其后繼任務(wù),相同顏色的計(jì)算任務(wù)在同一個(gè)計(jì)算線程上執(zhí)行。這部分代碼計(jì)算的數(shù)據(jù)訪問(wèn)很規(guī)則,所以計(jì)算任務(wù)之間的依賴關(guān)系比較簡(jiǎn)單,因?yàn)橛?jì)算任務(wù)是按照循環(huán)的次序串行提交的,所以該DAG構(gòu)建時(shí),第一個(gè)循環(huán)內(nèi)的任務(wù)(即第一行的任務(wù))首先注冊(cè),并被加入到end_tasks列表中,第二行計(jì)算任務(wù)注冊(cè)時(shí),之前提交的計(jì)算任務(wù)都被檢測(cè)到有后繼任務(wù),end_tasks列表需要將第一個(gè)循環(huán)內(nèi)的任務(wù)刪除,第三行計(jì)算任務(wù)提交后同樣需要?jiǎng)h除第二行計(jì)算任務(wù),這就造成了很多不必要的哈希表查找和修改操作。若無(wú)后繼任務(wù)占比極低,會(huì)使得注冊(cè)時(shí)收集到的任務(wù)絕大多數(shù)被刪除,導(dǎo)致哈希表相應(yīng)數(shù)據(jù)項(xiàng)的操作失去意義,造成不必要的開(kāi)銷。
圖7 航天飛行器應(yīng)用規(guī)則部分DAG
對(duì)于無(wú)后繼任務(wù)占比較小的并行區(qū),通過(guò)為用戶提供指定無(wú)后繼任務(wù)的開(kāi)關(guān),由用戶直接判斷無(wú)后繼任務(wù),從而省去構(gòu)圖過(guò)程中end_tasks列表頻繁修改的開(kāi)銷。在實(shí)現(xiàn)上增加開(kāi)關(guān)SPECIFY_END_TASKS=true(false)和接口acemesh_specify_end_tasks()。如果應(yīng)用并行區(qū)內(nèi)無(wú)后繼任務(wù)占比較小,用戶設(shè)置SPECIFY_END_TASKS=true,AceMesh構(gòu)圖時(shí)將不再進(jìn)行無(wú)后繼任務(wù)列表end_tasks的收集,由用戶在提交任務(wù)時(shí)利用接口acemesh_specify_end_tasks() 指定無(wú)后繼任務(wù)并將其直接放入無(wú)后繼任務(wù)列表end_tasks中,所有任務(wù)提交完成后無(wú)后繼任務(wù)也收集完畢,避免對(duì)end_tasks列表頻繁的插入和刪除操作,提高構(gòu)圖效率。
航天飛行器應(yīng)用程序的循環(huán)有6層。外3層循環(huán)為速度空間,內(nèi)3層循環(huán)為位置空間,外3層循環(huán)在進(jìn)程級(jí)別對(duì)程序進(jìn)行劃分, 本研究只對(duì)內(nèi)3層循環(huán)即位置空間i,j,k的3個(gè)維度進(jìn)行劃分。對(duì)航天飛行器應(yīng)用程序進(jìn)行分析得到具有代表性的7個(gè)計(jì)算循環(huán),每個(gè)計(jì)算循環(huán)有不同的劃分方向和分塊尺寸,各循環(huán)的劃分方向和分塊尺寸如表1所示。各個(gè)循環(huán)在3個(gè)維度上的劃分如表1所示。
表1 計(jì)算循環(huán)分塊表
將7個(gè)計(jì)算循環(huán)作為熱點(diǎn)子程序進(jìn)行性能測(cè)試,由于在“神威·太湖之光”平臺(tái)上,AceMesh任務(wù)調(diào)度系統(tǒng)的構(gòu)圖階段是單線程執(zhí)行的,故無(wú)論采用多少計(jì)算線程,構(gòu)圖時(shí)間均不變。對(duì)各熱點(diǎn)子程序使用執(zhí)行效率最高的線程數(shù),在速度空間32×16×16、位置空間100×19×31、進(jìn)程網(wǎng)格1×1×1規(guī)模下,對(duì)AceMesh任務(wù)調(diào)度系統(tǒng)的構(gòu)圖階段測(cè)試5次,取5次測(cè)試結(jié)果的平均值,對(duì)比構(gòu)圖優(yōu)化前后的性能,說(shuō)明構(gòu)圖優(yōu)化的效果,如表2所示。
表2中可見(jiàn),對(duì)于不同的熱點(diǎn)程序,構(gòu)圖優(yōu)化對(duì)構(gòu)圖的性能提升程度不同,但加速比均在4.7以上,其中GaussLegendre的構(gòu)圖性能表現(xiàn)最好,加速比為7.18。因?yàn)锳ceMesh任務(wù)調(diào)度系統(tǒng)分為構(gòu)圖和執(zhí)行兩個(gè)依次進(jìn)行的階段,所以計(jì)算線程數(shù)對(duì)構(gòu)圖性能無(wú)影響。
表2 AceMesh任務(wù)調(diào)度系統(tǒng)的構(gòu)圖優(yōu)化性能對(duì)比
任務(wù)調(diào)度系統(tǒng)各優(yōu)化項(xiàng)構(gòu)圖優(yōu)化貢獻(xiàn)如圖8所示,以優(yōu)化前的構(gòu)圖作為基準(zhǔn),主、從核通信優(yōu)化、內(nèi)存池以及無(wú)后繼任務(wù)收集等優(yōu)化方法對(duì)構(gòu)圖有不同程度的加速貢獻(xiàn),其中無(wú)后繼任務(wù)收集優(yōu)化方法的加速貢獻(xiàn)最大,加速比為2.6以上,所有優(yōu)化方法總加速比最高達(dá)到8.19。
圖8 AceMesh任務(wù)調(diào)度系統(tǒng)各優(yōu)化項(xiàng)構(gòu)圖優(yōu)化加速比
AceMesh任務(wù)調(diào)度系統(tǒng)構(gòu)圖優(yōu)化的子程序總性能對(duì)比如圖9所示,因?yàn)楹教祜w行器應(yīng)用的7個(gè)子程序的任務(wù)數(shù)不同,構(gòu)圖優(yōu)化對(duì)7個(gè)熱點(diǎn)子程序的總體性能加速表現(xiàn)不同,但均在1.3倍以上,其中GaussLegendre的優(yōu)化加速最好,達(dá)到3.13倍;其次是fcta1和fcta2,總性能加速比趨于相同,達(dá)到2.6倍以上。
圖9 AceMesh任務(wù)調(diào)度系統(tǒng)構(gòu)圖優(yōu)化子程序總性能對(duì)比
測(cè)試采用“神威·太湖之光”平臺(tái)的測(cè)試隊(duì)列,由于使用權(quán)限所致,最大進(jìn)程數(shù)只能為64,運(yùn)行時(shí)間最長(zhǎng)為60 min。在速度空間64×64×64,位置空間100×19×31規(guī)模下,測(cè)試不同進(jìn)程數(shù)下應(yīng)用整體性能的提升。并對(duì)照神威OpenACC編程語(yǔ)言版本,說(shuō)明AceMesh任務(wù)圖并行化帶來(lái)的性能提升,如表3所示。
表3 AceMesh與神威OpenACC版本的航天飛行器應(yīng)用性能對(duì)比
表3數(shù)據(jù)表明,AceMesh編程語(yǔ)言的DAG并行版本比神威OpenACC的運(yùn)行效率要高,在不同的進(jìn)程數(shù)下,加速效果都約為OpenACC的1.5倍。究其原因,一是因?yàn)閬y序執(zhí)行是AceMesh獨(dú)有的特性,二是因?yàn)锳ceMesh通過(guò)對(duì)計(jì)算循環(huán)進(jìn)行多維度的劃分,在保證足夠任務(wù)數(shù)的同時(shí)每個(gè)任務(wù)有充足的計(jì)算量,充分利用訪存帶寬,使得DMA傳輸?shù)男侍岣?。隨著進(jìn)程數(shù)的增加,AceMesh并行版本和神威OpenACC并行版本的執(zhí)行時(shí)間均逐漸減小,在64線程時(shí),運(yùn)行速度最快,說(shuō)明AceMesh和神威OpenACC任務(wù)并行編程模型都具有良好的擴(kuò)展性。
為提高AceMesh的構(gòu)圖性能,從主、從核通信優(yōu)化、設(shè)計(jì)內(nèi)存池、無(wú)后繼任務(wù)收集等3個(gè)方面對(duì)AceMesh的構(gòu)圖進(jìn)行優(yōu)化,對(duì)航天飛行器應(yīng)用的7個(gè)熱點(diǎn)子程序在“神威·太湖之光”上進(jìn)行了測(cè)試,結(jié)果證明優(yōu)化為構(gòu)圖帶來(lái)5倍的性能提升。后兩個(gè)方面的優(yōu)化具有普適性,可為所有超算平臺(tái)上的優(yōu)化提供參考。以上構(gòu)圖效率提高的主要原因來(lái)自無(wú)后繼任務(wù)收集的優(yōu)化,進(jìn)一步可以考慮設(shè)計(jì)一種更高效的任務(wù)收集機(jī)制來(lái)減少哈希表的查找和修改開(kāi)銷。