劉闖,何峰,肖兮,董小社,張興軍
(西安交通大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)系,710049,西安)
通過(guò)計(jì)算流體力學(xué)程序模擬真實(shí)情景是提高流體機(jī)械的制造精度和節(jié)約成本的重要手段,計(jì)算流體力學(xué)程序具有計(jì)算密集、處理數(shù)據(jù)量大的特性,因此常需要大量的計(jì)算資源。盡管計(jì)算機(jī)的計(jì)算能力有了飛速的發(fā)展,計(jì)算流體力學(xué)程序?qū)τ?jì)算性能的利用率仍然存在不充分的現(xiàn)象,導(dǎo)致計(jì)算資源的浪費(fèi)。
目前對(duì)于流體計(jì)算程序性能提升的研究主要體現(xiàn)在并行化或異構(gòu)加速上[1-3],例如采用多核系統(tǒng)并行處理或采用協(xié)處理器加速計(jì)算。超級(jí)計(jì)算機(jī)上部署的大型計(jì)算流體力學(xué)程序大多都采用了上面兩種計(jì)算方式,但是作為一個(gè)重要的影響因素,程序的單核執(zhí)行效率并沒(méi)有得到足夠的重視,很多程序的單核性能只能達(dá)到系統(tǒng)理論峰值的5%~10%[4],導(dǎo)致大量的計(jì)算資源被浪費(fèi),因此對(duì)程序單核性能的優(yōu)化應(yīng)引起重視。
針對(duì)流體計(jì)算程序的優(yōu)化,一些文獻(xiàn)提出了綜述性的優(yōu)化方案和思路[5-7],或針對(duì)具體程序進(jìn)行了優(yōu)化[8],但是這種優(yōu)化主要集中于對(duì)云計(jì)算、網(wǎng)格計(jì)算等并行化計(jì)算的優(yōu)化,對(duì)單核級(jí)優(yōu)化的工作不夠深入;針對(duì)單核級(jí)的程序優(yōu)化的研究中,主要優(yōu)化方案是流水優(yōu)化或訪存優(yōu)化,優(yōu)化步驟一般是首先分析程序特性或測(cè)試程序熱點(diǎn)以找到瓶頸,然后通過(guò)調(diào)整代碼結(jié)構(gòu)流水性能[9]或調(diào)整數(shù)據(jù)的組織方式優(yōu)化訪存性能[4,10-12];從處理器的角度,賀愛(ài)香、Oyarzun等根據(jù)ARM處理器的計(jì)算特性對(duì)問(wèn)題提出優(yōu)化方案[13-14],這些研究具有一定的通用價(jià)值,但是對(duì)于大型計(jì)算程序常用的Intel處理器并沒(méi)有深入研究;申小偉等通過(guò)對(duì)編譯器等運(yùn)行環(huán)境的優(yōu)化來(lái)提升程序性能[15],但是這種方法對(duì)于跨專業(yè)的程序優(yōu)化人員具有一定的門檻,且在公用的計(jì)算環(huán)境中難以部署。根據(jù)上述背景,本文針對(duì)軸流壓氣機(jī)模擬的流體計(jì)算程序,提出一種針對(duì)計(jì)算流體力學(xué)程序單核的優(yōu)化方法。總體優(yōu)化思路有3個(gè)方面:①優(yōu)化指令結(jié)構(gòu),減少由相關(guān)引起的指令流水?dāng)嗔?使程序充分發(fā)揮CPU的計(jì)算能力;②調(diào)整存儲(chǔ)結(jié)構(gòu)和訪存結(jié)構(gòu)并進(jìn)行容器優(yōu)化,從而增強(qiáng)存儲(chǔ)和訪存的性能;③減少冗余指令,優(yōu)化底層代碼數(shù)量和結(jié)構(gòu)從而減少程序執(zhí)行所需的時(shí)間空間。本文在軸流壓氣機(jī)模擬程序上實(shí)現(xiàn)優(yōu)化方法,在TIANHE-1A超級(jí)計(jì)算機(jī)和商用服務(wù)器上進(jìn)行測(cè)試實(shí)驗(yàn),實(shí)驗(yàn)結(jié)果表明,本文提出的優(yōu)化方法可以有效地提高程序的緩存命中率、優(yōu)化流水連續(xù)性、減少目標(biāo)代碼數(shù),從而大幅提升程序單核執(zhí)行效率。
本文采用軸流壓氣機(jī)模擬程序[16-17]對(duì)軸流壓氣機(jī)轉(zhuǎn)子進(jìn)行模擬,程序采用有限體積法進(jìn)行空間離散,3步Runge-Kutta法進(jìn)行時(shí)間推進(jìn),控制方程組采用笛卡爾坐標(biāo)系下的相對(duì)流動(dòng)控制方程組,形式如下
(1)
湍流模型采用SA湍流模型,為加速收斂程序采用三層網(wǎng)格,通過(guò)在不同網(wǎng)格層上輪流迭代從而使不同頻率的誤差分量得到有效地衰減。
程序模擬36葉片壓縮機(jī)工作時(shí)的流體狀態(tài),采用36個(gè)進(jìn)程,每個(gè)進(jìn)程對(duì)一個(gè)葉片進(jìn)行模擬,單葉片網(wǎng)格數(shù)約為42萬(wàn),總計(jì)約1 535萬(wàn)。在邊界處理時(shí)需進(jìn)行通信,通信采用MPI完成。程序主要開(kāi)銷是在單個(gè)進(jìn)程的計(jì)算上,通信等待時(shí)間相對(duì)整個(gè)程序時(shí)間占比較少,且優(yōu)化不涉及通信時(shí)間的優(yōu)化,因此并行開(kāi)銷可忽略不計(jì)。
考慮程序的緩存命中率對(duì)程序的存儲(chǔ)和計(jì)算特性進(jìn)行分析。存儲(chǔ)方面,程序中網(wǎng)格的存儲(chǔ)采用STL庫(kù)中的Vector容器進(jìn)行存儲(chǔ),采用該容器的主要原因是Vector容器是順序存儲(chǔ)容器,有較好的隨機(jī)存取性能,以及可以利用STL中提供的豐富的操作,功能強(qiáng)大。根據(jù)物理網(wǎng)格模型,容器的維度為四維,存儲(chǔ)維度順序?yàn)閤、y、z、n,其中x、y、z為空間維度,n為多層網(wǎng)格的層號(hào)。
計(jì)算方面,程序計(jì)算主體的運(yùn)行時(shí)間約占整個(gè)運(yùn)行時(shí)間的95%以上,剩余時(shí)間做程序流程控制、數(shù)據(jù)的通信與保存等操作,因此程序優(yōu)化的主體在計(jì)算部分。在計(jì)算部分中,程序?qū)φ麄€(gè)網(wǎng)格層采用for循環(huán)進(jìn)行更新,大多數(shù)循環(huán)深度為3層,由于邊界上存在虛擬網(wǎng)格,循環(huán)次數(shù)約為43.5萬(wàn)次,略多于網(wǎng)格數(shù),每次迭代中更新一個(gè)或多個(gè)變量。此外,為實(shí)現(xiàn)復(fù)雜計(jì)算,程序還調(diào)用了math庫(kù)中的部分計(jì)算函數(shù),考慮到計(jì)算函數(shù)計(jì)算開(kāi)銷較大,在某些調(diào)用中可采用等價(jià)短指令替換。
為進(jìn)一步分析程序計(jì)算性能,本文采用性能分析軟件對(duì)程序進(jìn)行分析。結(jié)果顯示,程序的流水線性能未充分發(fā)揮,雙向中斷率均超過(guò)50%,暫停周期數(shù)較高,導(dǎo)致執(zhí)行某個(gè)程序的指令平均時(shí)鐘周期(CPI)與理論值有差距。因此,在優(yōu)化時(shí)應(yīng)考慮流水優(yōu)化;緩存命中率約為50%,訪存上也有優(yōu)化空間;此外程序執(zhí)行指令數(shù)為38 534×109條,在優(yōu)化中需尋找潛在的指令優(yōu)化來(lái)減少冗余代碼。
本文所述方法應(yīng)用在TIANHE-1A超級(jí)計(jì)算機(jī)系統(tǒng)中Intel Xeon X5670 CPU上,采用Intel CPU作為示例是考慮到大多數(shù)的高性能計(jì)算環(huán)境都采用Intel處理器,且Intel CPU中采用的加速部件在其他處理器中有類似部件設(shè)計(jì),因此以Intel CPU為基礎(chǔ)設(shè)計(jì)的優(yōu)化方案具有較好的普適性。

圖1 Intel CPU架構(gòu)示意圖
圖1給出了Intel CPU的架構(gòu)示意圖,該示意圖基于Intel Xeon X5670 CPU所采用的Nehalem架構(gòu),主要體現(xiàn)CPU針對(duì)單核程序的加速方式,對(duì)其余部件做了省略和簡(jiǎn)化。圖1中CPU包含兩個(gè)核,每個(gè)核內(nèi)設(shè)置獨(dú)立的計(jì)算部件,從邏輯上分為取值部件、解碼部件、順序回退部件、計(jì)算單元,圖1中的箭頭代表了部件間的數(shù)據(jù)通路。基于上述架構(gòu),Nehalem CPU架構(gòu)部署了取指(IF)、譯碼(ID)、執(zhí)行(EXE)、寫(xiě)回(WB)四階段流水機(jī)制。此外,Nehalem架構(gòu)還采用了超標(biāo)量技術(shù),在CPU中建立了4條流水線,因此理論上可以同時(shí)執(zhí)行4條流水指令。每個(gè)核設(shè)置獨(dú)立的L1和L2緩存,多個(gè)核間共享L3緩存,方便進(jìn)行數(shù)據(jù)緩存,提升訪存性能。其中一級(jí)緩存分為數(shù)據(jù)緩存和指令緩存,每個(gè)緩存容量為32 KB,采用8×64組相連的映射方式,訪存速度為4個(gè)時(shí)鐘周期;L2緩存容量為256 KB,采用8×512組相連映射方式,訪存速度為10個(gè)時(shí)鐘周期;L3緩存容量為8 MB,采用16×8 192組相連映射方式,訪存速度為40~75個(gè)時(shí)鐘周期。
基于對(duì)Nehalem架構(gòu)的分析,程序優(yōu)化的思路主要集中在使程序充分發(fā)揮流水性能和訪存性能上。
除針對(duì)CPU架構(gòu)的優(yōu)化外,還需考慮程序本身的簡(jiǎn)潔性。對(duì)于不同形式的程序,通過(guò)編譯器編譯得到的目標(biāo)代碼有很大差距,若有冗余和過(guò)多同義代碼會(huì)導(dǎo)致性能下降。為保證程序性能,在編碼時(shí)需考慮高級(jí)語(yǔ)言被編譯后得到的目標(biāo)代碼是否簡(jiǎn)潔高效。
結(jié)合上述分析,本文提出的流體計(jì)算程序單核優(yōu)化方案主要考慮3個(gè)方面:①優(yōu)化存儲(chǔ)結(jié)構(gòu)和訪存結(jié)構(gòu),發(fā)揮高速緩存效率;②調(diào)整程序的指令結(jié)構(gòu),發(fā)揮流水性能;③優(yōu)化程序指令,使程序底層指令數(shù)得到削減和優(yōu)化。前兩個(gè)方面面向CPU對(duì)單核指令執(zhí)行的高速訪存和流水優(yōu)化部件展開(kāi),目的是充分發(fā)揮CPU加速部件的加速效果。第3個(gè)方面針對(duì)程序代碼本身優(yōu)化,考慮到不同指令在底層執(zhí)行時(shí)采用不同的匯編指令翻譯,程序的目標(biāo)代碼應(yīng)足夠精簡(jiǎn)高效。
訪存優(yōu)化的目的是使程序在數(shù)據(jù)訪問(wèn)時(shí)緩存的利用率更高,主要優(yōu)化手段是調(diào)整數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)和訪存結(jié)構(gòu),首先考慮存儲(chǔ)結(jié)構(gòu)。

(a)訪存在內(nèi)存上連續(xù)

(b)訪存在內(nèi)存上離散
程序的訪存方式是通過(guò)循環(huán)遍歷的方式對(duì)網(wǎng)格進(jìn)行訪問(wèn),優(yōu)先訪問(wèn)網(wǎng)格層號(hào)n,其次為x、y、z軸,這種存儲(chǔ)結(jié)構(gòu)和訪存方式的不匹配造成了緩存效率較低。圖2給出了不同存儲(chǔ)方式下訪存情況的對(duì)比,對(duì)于M×N矩陣,規(guī)定訪存順序?yàn)閺?0,1)到(0,N),若矩陣采取aM,N的形式存儲(chǔ),則矩陣在內(nèi)存中的物理分布如圖2a所示,在訪存時(shí)數(shù)據(jù)分布在連續(xù)的內(nèi)存中,緩存會(huì)將連續(xù)內(nèi)存存入,在下次訪存時(shí)可直接取用緩存,減少內(nèi)存訪問(wèn)。若矩陣采取aN,M的形式存儲(chǔ),則矩陣在內(nèi)存中分布如圖2b所示,在訪存時(shí)會(huì)產(chǎn)生跳躍,因此緩存無(wú)法命中,需要進(jìn)行內(nèi)存訪問(wèn),影響程序運(yùn)行效率。
為解決訪存問(wèn)題,將數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)調(diào)整為an,z,y,x,這樣調(diào)整的好處有:①存儲(chǔ)結(jié)構(gòu)更改后x網(wǎng)格內(nèi)相鄰各點(diǎn)在內(nèi)存中存儲(chǔ)的更近,更有利于程序的連續(xù)訪問(wèn);②對(duì)于多維容器來(lái)說(shuō),由于x>y>z>n,更改后的存儲(chǔ)形式減少了容器在較低維度所創(chuàng)建的數(shù)量,減少了目標(biāo)代碼的指令數(shù)。例如,對(duì)于容器a20,10,需先創(chuàng)建一個(gè)容量為20的容器,每個(gè)容器中再創(chuàng)建一個(gè)容量為10的容器,總共創(chuàng)建21個(gè),若改為a10,20,則僅需創(chuàng)建11個(gè)容器。
下面根據(jù)存儲(chǔ)結(jié)構(gòu)調(diào)整訪存結(jié)構(gòu),訪存順序的控制由for循環(huán)語(yǔ)句進(jìn)行。為使訪存順序更適合存儲(chǔ)結(jié)構(gòu),將循環(huán)結(jié)構(gòu)和存儲(chǔ)維度調(diào)整為一一對(duì)應(yīng)的關(guān)系。即對(duì)于an,z,y,x形式的數(shù)據(jù),處理循環(huán)為最外層循環(huán)處理n、次外層處理z、內(nèi)層處理y、最內(nèi)層處理x。對(duì)不滿足這種處理方式的操作,考察操作的相關(guān)性,若無(wú)相關(guān)性可通過(guò)拆分循環(huán)來(lái)優(yōu)化訪存順序。
訪存方式的優(yōu)化和存儲(chǔ)結(jié)構(gòu)的優(yōu)化有類似的優(yōu)點(diǎn):調(diào)整訪存結(jié)構(gòu)有利于高速緩存;調(diào)整后循環(huán)的控制變量初始化次數(shù)減少,消減底層指令數(shù)。
考慮影響流水線性能的問(wèn)題,在程序一級(jí)影響因素主要有:由分支轉(zhuǎn)移引起的控制相關(guān)會(huì)導(dǎo)致流水失效;由寫(xiě)后讀引起的數(shù)據(jù)相關(guān),這些相關(guān)會(huì)導(dǎo)致流水暫停,使流水性能下降。Nehalem CPU架構(gòu)部署了四階段流水機(jī)制,雖然該架構(gòu)加入了分支預(yù)測(cè)和數(shù)據(jù)旁路的方式減少流水線中斷,但是仍不足以完全消除相關(guān)性引起的性能損失,因此在優(yōu)化時(shí)仍可消除相關(guān)性。
考慮計(jì)算中的循環(huán)部分,由于循環(huán)在每次迭代時(shí)需進(jìn)行一次判斷,若循環(huán)內(nèi)指令較少會(huì)導(dǎo)致計(jì)算和分支的比例過(guò)低,產(chǎn)生控制相關(guān)導(dǎo)致性能下降,同時(shí)循環(huán)中對(duì)同一變量的反復(fù)讀寫(xiě)可能引起數(shù)據(jù)相關(guān)。針對(duì)控制相關(guān)和數(shù)據(jù)相關(guān)問(wèn)題,一般采用循環(huán)展開(kāi)并引入多中間變量的方法進(jìn)行優(yōu)化,循環(huán)展開(kāi)可以在以下方面得到優(yōu)化:①減少分支數(shù);②減少循環(huán)控制的指令開(kāi)銷;③減少循環(huán)內(nèi)計(jì)算的數(shù)據(jù)相關(guān)。循環(huán)展開(kāi)示例如下
for(i=0;i s+=a[i]; 改為: for(i=0;i s1+=a[i]; s2+=a[i+1]; } s=s1+s2; 展開(kāi)因子k=2,即每次循環(huán)計(jì)算次數(shù)為兩次。兩種代碼的流水情況如圖3所示,流水性能得到了提升。 (a)循環(huán)拆分前 (b)循環(huán)拆分后 理論上,在展開(kāi)足夠多循環(huán)的情況下可以完全消除流水中斷,展開(kāi)因子應(yīng)大于硬件標(biāo)量數(shù)與執(zhí)行周期的乘積,如對(duì)于具有3個(gè)浮點(diǎn)乘器件,每個(gè)浮點(diǎn)乘需5個(gè)時(shí)鐘周期的指令集,展開(kāi)因子應(yīng)大于15;但是實(shí)際操作中需考慮寄存器溢出,即中間變量過(guò)多導(dǎo)致寄存器不夠,觸發(fā)訪存。為此還需保證最優(yōu)循環(huán)因子k滿足 max{k};F(k)≤r,k∈Z (3) 式中F(k)為k次展開(kāi)需要的寄存器數(shù)。 此外,解除數(shù)據(jù)相關(guān)還可以采用長(zhǎng)計(jì)算拆分為短計(jì)算、創(chuàng)建臨時(shí)變量的方式解除相關(guān)、多個(gè)連續(xù)的寫(xiě)后讀相關(guān)語(yǔ)句交叉等方法。 對(duì)if語(yǔ)句引起的控制相關(guān),分支預(yù)測(cè)部件往往不能正確預(yù)測(cè)走向,預(yù)測(cè)錯(cuò)誤的懲罰往往達(dá)到十幾個(gè)到幾十個(gè)時(shí)鐘周期,帶來(lái)流水性能損失。在X86指令集中,條件數(shù)據(jù)傳輸指令可以被編譯為普通指令流水線的一部分,在判斷失敗時(shí)沒(méi)有懲罰,因此采用條件數(shù)據(jù)傳送代替條件控制轉(zhuǎn)移能提升程序性能。常用的條件數(shù)據(jù)傳輸指令是三目運(yùn)算符,條件傳輸形式如s=a x=a x′=b boolT=(a if (!T)x=x′ 可以看出,這種編譯方式將分支轉(zhuǎn)移操作放在偽代碼最后一行的if語(yǔ)句中,在目標(biāo)代碼中這個(gè)if語(yǔ)句通過(guò)條件拷貝指令cmov實(shí)現(xiàn),分支的結(jié)果只在這一條指令中體現(xiàn),與上下文無(wú)關(guān),從而消除了分支開(kāi)銷。通過(guò)這種轉(zhuǎn)換可以提升分支在流水線中的穩(wěn)定性,減少預(yù)測(cè)錯(cuò)誤的懲罰。 指令優(yōu)化的目的是從指令一級(jí)減少冗余代碼。冗余代碼主要指程序編譯后的目標(biāo)代碼中產(chǎn)生的冗余,一般主要產(chǎn)生于如下兩種情況。 (1)完成相同功能的不同語(yǔ)句在經(jīng)過(guò)編譯器編譯后會(huì)產(chǎn)生不同的目標(biāo)代碼,若選擇不合適的語(yǔ)句會(huì)引起冗余的目標(biāo)代碼。這種冗余包括兩種,一種是目標(biāo)代碼量的增加,指對(duì)于同樣功能的代碼由于實(shí)現(xiàn)方法不同導(dǎo)致編譯后代碼條數(shù)不同;另一種是代碼復(fù)雜度的增加,CISC指令集中的指令執(zhí)行時(shí)間不同,因此同樣的指令條數(shù)下指令執(zhí)行時(shí)間有所不同。 (2)為實(shí)現(xiàn)方法調(diào)用,操作系統(tǒng)需保存當(dāng)前運(yùn)行時(shí)信息,并在運(yùn)行時(shí)棧開(kāi)辟新的空間,在調(diào)用結(jié)束時(shí)恢復(fù)信息并釋放空間。這種調(diào)度工作會(huì)體現(xiàn)在目標(biāo)代碼中,雖然一般認(rèn)為正常的調(diào)用過(guò)程對(duì)程序性能影響不大,但當(dāng)調(diào)用在程序中占比過(guò)大時(shí)會(huì)影響程序性能。調(diào)用引起代碼冗余的一種示例如下。 非調(diào)用版指令如下 s=a+b; 目標(biāo)代碼為 1 mov %rdi,%rbp 2 mov %rax,rbp 3 add %rbx,%rax 調(diào)用版指令如下 Sum (inta,intb) {returna+b;} 目標(biāo)代碼為 1 push %rbp 2 push %rbx 3 sub %8,%rsp 4 mov %rdi,%rbp 5 mov %rax,rbp 6 add %rbx,%rax 7 add %8,%rsp 8 pop %rbx 9 pop %rbp 10 ret 調(diào)用版的第1、2行用來(lái)實(shí)現(xiàn)現(xiàn)場(chǎng)保存,第3行為新調(diào)用棧分配空間,然后執(zhí)行加法功能,第7行釋放調(diào)用棧,第8、9行恢復(fù)現(xiàn)場(chǎng),最后返回。可以看出,當(dāng)實(shí)現(xiàn)同樣加法功能的s=a+b被替換為方法調(diào)用Sum(a,b)后,運(yùn)行時(shí)棧調(diào)度的開(kāi)銷超過(guò)了方法本身。雖然編譯器中有對(duì)高級(jí)語(yǔ)言的自動(dòng)優(yōu)化功能或調(diào)用產(chǎn)生冗余代碼的問(wèn)題,如自動(dòng)將短調(diào)用進(jìn)行內(nèi)聯(lián)處理,但是編譯器優(yōu)化的前提是保證程序的安全,因此面對(duì)具有內(nèi)存別名使用或變量類型未知等問(wèn)題的代碼不能進(jìn)行自動(dòng)優(yōu)化,需手動(dòng)對(duì)高級(jí)語(yǔ)言進(jìn)行優(yōu)化。 分析本程序得出,導(dǎo)致性能下降的主要問(wèn)題是:①部分庫(kù)函數(shù)調(diào)用時(shí)產(chǎn)生的隱藏代碼增加了代碼量,增加包括調(diào)用棧引起的代碼開(kāi)銷和庫(kù)函數(shù)本身復(fù)雜性引起的代碼開(kāi)銷;②代碼及代碼結(jié)構(gòu)本身的計(jì)算復(fù)雜度較高,因?yàn)橛休^多耗時(shí)的除法計(jì)算需求。為解決上述問(wèn)題,考慮使用簡(jiǎn)單指令代替復(fù)雜指令,并結(jié)合訪存優(yōu)化及流水優(yōu)化考慮匯編指令在系統(tǒng)中的運(yùn)行狀態(tài)進(jìn)行優(yōu)化。 下面討論指令優(yōu)化的具體實(shí)現(xiàn)。針對(duì)庫(kù)函數(shù)調(diào)用的問(wèn)題,結(jié)合程序分析發(fā)現(xiàn),程序主要調(diào)用的庫(kù)函數(shù)為數(shù)學(xué)庫(kù)和容器類庫(kù)。數(shù)學(xué)庫(kù)的乘方、開(kāi)方等操作一般不可替代,但是對(duì)于低階乘方,可以直接使用數(shù)乘代替。如pow(a,2)可以改寫(xiě)為a*=a,這種替換可以減少調(diào)用開(kāi)銷,同時(shí)簡(jiǎn)化方法本身的復(fù)雜度。 對(duì)容器類庫(kù)函數(shù)的修改可考慮對(duì)C++語(yǔ)言自帶容器數(shù)組進(jìn)行二次封裝代替庫(kù)容器,在本文的程序中為采用數(shù)組代替Vector容器。從可行性分析,Vector和數(shù)組有較為類似的存儲(chǔ)結(jié)構(gòu),因此在存取功能上具有可替代性。Vector相對(duì)數(shù)組的優(yōu)勢(shì)在于靈活的操作方式和內(nèi)存分配方式,程序中對(duì)容器的主要操作方式為隨機(jī)訪問(wèn),此外有少量的動(dòng)態(tài)內(nèi)存分配操作,因此在二次封裝數(shù)組時(shí)需要為數(shù)組增加隨機(jī)訪存函數(shù),從而實(shí)現(xiàn)對(duì)Vector的替代,所以用數(shù)組代替Vector具有可行性。從必要性分析,Vector是STL封裝的容器庫(kù),在使用時(shí)涉及庫(kù)調(diào)用會(huì)增加底層代碼量,容器的存儲(chǔ)結(jié)構(gòu)上,Vector為實(shí)現(xiàn)動(dòng)態(tài)增長(zhǎng),在分配空間時(shí)會(huì)分配額外的內(nèi)存,在多維空間上,這種存儲(chǔ)空間的浪費(fèi)變得更加明顯,在訪存時(shí)也會(huì)增加額外開(kāi)銷,高速緩存的命中率也會(huì)下降。 針對(duì)代碼結(jié)構(gòu)結(jié)合訪存特性考慮編譯器對(duì)語(yǔ)句的處理方式,由于對(duì)變量的訪問(wèn)常被編譯為寄存器訪問(wèn)操作,對(duì)引用的訪問(wèn)被編譯為內(nèi)存訪問(wèn)操作,因此為優(yōu)化訪存性能,需將循環(huán)中頻繁引用訪問(wèn)修改為變量訪問(wèn)。針對(duì)代碼本身,考慮科學(xué)計(jì)算中常出現(xiàn)的乘除法指令,在Intel提供的參考機(jī)中部分算數(shù)指令性能見(jiàn)表1,其中延遲表明實(shí)際運(yùn)算周期數(shù),發(fā)射表明兩次運(yùn)算最小間隔周期數(shù),容量表明該功能的運(yùn)算單元數(shù)。 表1 Intel參考機(jī)算數(shù)指令性能 由表1可以看出,乘除法運(yùn)算執(zhí)行時(shí)間較長(zhǎng),除法尤為明顯,因此對(duì)乘除法的優(yōu)化也應(yīng)加以考慮。針對(duì)非浮點(diǎn)數(shù)的乘除法指令,采用移位運(yùn)算代替乘除法的方法進(jìn)行處理。該方法在乘除法數(shù)量較多且乘數(shù)或除數(shù)較為規(guī)律時(shí)可產(chǎn)生較好的優(yōu)化效果。對(duì)于浮點(diǎn)數(shù)除法,可采用公共除法移出的方法將除法轉(zhuǎn)換為乘法,減少執(zhí)行時(shí)間。 對(duì)第一節(jié)中的流體計(jì)算程序采用上述優(yōu)化方案進(jìn)行優(yōu)化,并在商用服務(wù)器對(duì)各版本程序采用perf性能檢測(cè)工具對(duì)程序進(jìn)行小規(guī)模性能分析。商用服務(wù)器采用Intel Xeon CPU E7-8850 @ 2.00 GHz(8×10核)CPU,內(nèi)存125 GB,編譯器采用gcc 4.8.5。在三層網(wǎng)格上迭代輪次為5、5、10。程序優(yōu)化前后的主要指標(biāo)的分析結(jié)果和執(zhí)行時(shí)間見(jiàn)表2。由于對(duì)容器以及對(duì)指令的優(yōu)化,程序所使用的運(yùn)行時(shí)空間的大小也有所下降,內(nèi)存占用實(shí)驗(yàn)結(jié)果見(jiàn)表3。 表2 程序主要指標(biāo)優(yōu)化前后的比較 表3 優(yōu)化前后占用內(nèi)存情況 由表2、3可以看出,程序性能的主要提升在于優(yōu)化后導(dǎo)致指令數(shù)的減少,在系統(tǒng)級(jí)優(yōu)化后緩存性能和流水性能也有所提升。在規(guī)模為5、5、10的程序中,經(jīng)過(guò)優(yōu)化的程序每周期指令數(shù)提升24.24%,指令暫停周期下降25.86%,流水中斷率下降6%,緩存命中率提升14%,執(zhí)行時(shí)間下降70.56%,空間消耗下降49.97%。 將程序部署在TIANHE-1A超級(jí)計(jì)算機(jī)系統(tǒng)中測(cè)試性能,采用4節(jié)點(diǎn)運(yùn)行36進(jìn)程。采用的CPU為Intel Xeon X5670(2×6核),內(nèi)存24 GB,編譯器為icc_xe_2013.0.07。三層網(wǎng)格迭代輪次采用50、50、10 000作為程序完整規(guī)模運(yùn)行的實(shí)驗(yàn),測(cè)試結(jié)果見(jiàn)表4。 由表4結(jié)果可以看出,在TIANHE-1A系統(tǒng)上,三層網(wǎng)格迭代輪次分別為50、50、10 000計(jì)算規(guī)模時(shí),程序耗時(shí)下降68.34%,空間消耗減少55.43%,與商用服務(wù)器上測(cè)試結(jié)果類似。根據(jù)測(cè)試結(jié)果可以看出,本文的優(yōu)化方法能有效提升程序?qū)PU計(jì)算能力的發(fā)揮,大幅減少程序的底層代碼,在測(cè)試程序中取得較好的優(yōu)化效果。 表4 程序完整規(guī)模運(yùn)行的實(shí)驗(yàn)測(cè)試結(jié)果 根據(jù)計(jì)算機(jī)系統(tǒng)單核級(jí)指令執(zhí)行的加速特性和編譯特性,提出一種針對(duì)計(jì)算流體力學(xué)程序的單核優(yōu)化方案,主要優(yōu)化方面包括:①優(yōu)化指令結(jié)構(gòu),減少指令流水的斷流,使程序充分發(fā)揮CPU的計(jì)算能力;②調(diào)整存儲(chǔ)結(jié)構(gòu)和訪存結(jié)構(gòu),增強(qiáng)存儲(chǔ)和訪存的性能;③減少冗余指令,優(yōu)化指令結(jié)構(gòu),從而減少程序執(zhí)行所需的時(shí)間開(kāi)銷和空間消耗。 將本文方法應(yīng)用在壓氣機(jī)轉(zhuǎn)子模擬程序中,測(cè)試結(jié)果顯示優(yōu)化方案能有效減少程序指令數(shù)、增加緩存命中率,減少指令流水?dāng)嗔?在TIANHE-1A計(jì)算機(jī)系統(tǒng)中進(jìn)行測(cè)試,結(jié)果顯示優(yōu)化后時(shí)間性能提升約68.34%,空間性能提升約55.43%,加速比提升3倍以上,具有較好的優(yōu)化效果。

2.3 指令優(yōu)化

3 實(shí)驗(yàn)結(jié)果



4 結(jié) 論