馮 穎, 袁慶華, 沈健煒
(解放軍總后勤部檔案館, 北京 100842)
近年來,基于中央處理器(CPU)+圖形處理器(GPU)的混合異構(gòu)計算系統(tǒng)開始逐漸成為國內(nèi)外高性能計算領(lǐng)域的熱點研究方向。在實際應(yīng)用中,許多基于CPU+GPU的混合異構(gòu)計算機系統(tǒng)表現(xiàn)出了良好的性能。但是,由于各種歷史和現(xiàn)實原因的制約,異構(gòu)計算仍然面臨著諸多方面的問題,其中最突出的問題是程序開發(fā)困難,尤其是擴展到集群規(guī)模級別時這個問題更為突出。
基于 CPU+GPU的異構(gòu)計算系統(tǒng)是指在傳統(tǒng)計算機系統(tǒng)中加入GPU作為加速部件并配合CPU共同承擔(dān)計算任務(wù)的新型系統(tǒng)。相比于傳統(tǒng)的單純以 CPU作為計算部件的同構(gòu)系統(tǒng),異構(gòu)系統(tǒng)優(yōu)勢明顯。首先,GPU能夠更出色的完成某些特殊應(yīng)用,例如對于追求浮點運算性能的應(yīng)用來說,目前GPU的浮點運算能力已經(jīng)遠(yuǎn)遠(yuǎn)超過CPU,圖1說明了近幾年GPU與CPU浮點運算能力的對比[1];其次,原先只用于圖形處理領(lǐng)域的 GPU正在逐漸向通用計算方向發(fā)展,在各GPU生產(chǎn)廠商的大力推動下,一些原先制約GPU通用化的障礙(如硬件結(jié)構(gòu)、編程模型)已經(jīng)不同程度地得到了克服;最后,當(dāng)今單純由 CPU搭建的高性能計算機系統(tǒng)遇到了許多難以克服的問題,例如擴展性問題、功耗問題等,而使用GPU加速部件可以很好地解決這些問題。
圖1 CPU與GPU浮點性能比較
雖然基于CPU+GPU的異構(gòu)計算發(fā)展迅速,但是由于各種歷史和現(xiàn)實原因制約,異構(gòu)計算仍然面臨諸多方面的問題,其中,最突出的是程序開發(fā)困難的問題。究其原因:一是 GPU的最初設(shè)計目標(biāo)是專業(yè)圖形處理而非通用計算,這導(dǎo)致了GPU本身的體系架構(gòu)對通用計算存在很多硬件制約,例如數(shù)據(jù)傳輸限制、缺少數(shù)據(jù)校驗機制、雙精度性能偏低等,這使得程序開發(fā)人員在使用 GPU進(jìn)行通用計算時不得不專門考慮這些問題。二是 GPU軟件開發(fā)的編程模型及編程方式還不成熟,盡管英偉達(dá)(NVIDIA)公司推出的計算統(tǒng)一設(shè)備架構(gòu)(CUDA)技術(shù)已經(jīng)大大降低了GPU通用計算開發(fā)的難度,但是要程序開發(fā)人員轉(zhuǎn)變長期以來的CPU模式X86編程習(xí)慣并非易事,而如何處理以往應(yīng)用中的大量遺留代碼也是個挑戰(zhàn)。三是異構(gòu)計算的標(biāo)準(zhǔn)開放計算語言(OpenCL)推出時間還比較短,盡管各 GPU主要生產(chǎn)廠商都已經(jīng)宣布對OpenCL進(jìn)行支持,但就目前來看,基于OpenCL的應(yīng)用和開發(fā)還遠(yuǎn)未形成氣候。
目前,適合于CPU+GPU異構(gòu)計算的程序開發(fā)方法可以大致分為以下四類:基于底層圖形應(yīng)用程序接口(API)的開發(fā)方法、基于低層次抽象的輕量級 GPU編程工具、基于高層次抽象的函數(shù)庫或模板庫和基于高層次抽象的使用編譯器的方法。
這是GPU通用計算領(lǐng)域早期使用的主流方法,在新的GPU上一般仍可使用。這種方法要求開發(fā)者必須熟悉GPU硬件底層圖形 API,并需要設(shè)法將程序映射到圖形處理過程。一般使用開發(fā)圖形庫著色語言(GLSL)等圖形繪制語言進(jìn)行編程。
早期的GPU產(chǎn)品都是基于分離渲染架構(gòu),即圖形渲染過程分為頂點處理、片段處理等幾個過程,這時的 GPU可編程能力比較差。隨著2001年GeForce3的出現(xiàn),頂點級可編程開始普及,人們開始使用它進(jìn)行了通用編程。到了2002年人們開始利用紋理著色(Texture Shader)結(jié)合基于寄存器組合器(Register Combiner)來求解擴散方程,而到了2003年像素級可編程性出現(xiàn),很多人開始利用像素程序來求解一般代數(shù)問題,甚至有限差分方程組求解(PDEs)和優(yōu)化問題的求解。這個階段的GPU都是通過底層圖形API向圖形程序員提供可控制能力。最常見的圖形API有兩種:開發(fā)圖形語言(OpenGL)和DirectX。OpenGL作為事實上的工業(yè)標(biāo)準(zhǔn)已為學(xué)術(shù)界和工業(yè)界所普遍接受;DirectX作為微軟視窗的標(biāo)準(zhǔn),可以根據(jù) GPU新產(chǎn)品功能的擴充與進(jìn)展及時定義新的版本以擴充新的接口。
CUDA是一種將GPU作為數(shù)據(jù)并行計算設(shè)備的軟硬件體系,它是一個完整的用于通用目的計算的圖形處理器(GPGPU)的解決方案,提供了硬件的直接訪問接口,不用像傳統(tǒng)方式一樣必須依賴圖形API來實現(xiàn)GPU的訪問。CUDA采用 C語言作為編程語言,提供大量的高性能計算指令開發(fā)能力,使開發(fā)者能夠在GPU計算能力的基礎(chǔ)上建立起一種高效的密集數(shù)據(jù)計算解決方案。CUDA架構(gòu)如圖2 所示[2]。
圖2 CUDA架構(gòu)圖
OpenCL是第一個面向異構(gòu)系統(tǒng)通用目的并行編程的開放標(biāo)準(zhǔn)和統(tǒng)一的編程環(huán)境,適用于CPU、GPU、Cell類型架構(gòu)以及DSP等其他并行處理器。作為開放標(biāo)準(zhǔn),可以為CPU、GPU和其他分離的計算設(shè)備(這些設(shè)備被組織到單個平臺中)所組成的異構(gòu)群進(jìn)行編程。作為并行編程框架,OpenCL目前包括一種開發(fā)語言、API庫和一個運行系統(tǒng)來支持軟件開發(fā),不必將算法映射到底層圖形API上。
CUDA快速傅里葉變換(CUFFT)是一個利用GPU進(jìn)行傅里葉變換的函數(shù)庫,提供了與廣泛使用快速計算離散傅里葉變換的標(biāo)準(zhǔn)C語言程序庫(FFTW)相似的接口。不同的是FFTW操作的數(shù)據(jù)存儲在內(nèi)存中,而基于CUDA離散傅里葉變換(CUFFT)的操作數(shù)據(jù)存儲在顯存,不能直接相互取代,必須加入顯存與內(nèi)存之間的數(shù)據(jù)交換,進(jìn)行封裝后才能替FFTW庫。CUDA線性代數(shù)基礎(chǔ)子程序庫(CUBLAS)是一個基本的矩陣與向量的運算庫,提供了與BLAST相似的接口,可以用于簡單的矩陣計算,也可以作為基礎(chǔ)構(gòu)建更加復(fù)雜的函數(shù)包,如線性代數(shù)程序包(LAPACK)等。CUBLAS操作的數(shù)據(jù)也存儲在顯存中,同樣需要封裝后才能替代基本線性代數(shù)子程序(BLAST)中的函數(shù)[3]。
基于高層次抽象的使用編譯器的方法是指通過使用指示語句、算法模板以及十分復(fù)雜的代碼分析技術(shù)、編譯器或語言運行時系統(tǒng)自動生成GPU內(nèi)核程序。
PGI x86+GPU編譯器是意法半導(dǎo)體子公司Portland Group的高性能并行編譯器產(chǎn)品。它引進(jìn)一組新指示語句(PRAGMAS)以用來指示哪一部分的代碼可以被映射到GPU上執(zhí)行。指示語句定義了內(nèi)核程序區(qū)域,描述了循環(huán)結(jié)構(gòu)以及它們與GPU上的線程塊和線程之間的匹配。指示語句同時也用于指示哪個數(shù)據(jù)需要在主設(shè)備和GPU存儲器之間復(fù)制。
超立方體大規(guī)模并行處理語言(HMPP)一個基于標(biāo)簽語法的多語言程序設(shè)計環(huán)境,利用它能夠使軟件和目標(biāo)硬件設(shè)備保持獨立,提供將已有應(yīng)用程序部署到 GPU的有效工具。它同時擁有CUDA和OpenCL代碼生成器,使用HMPP目標(biāo)代碼生成器可以改進(jìn)硬件加速的關(guān)鍵程序段的性能。代碼生成器用來從原來的C或Fortran程序中提取可以并行化的部分,并將其轉(zhuǎn)換為CUDA或者OpenCL代碼,不需要使用新的GPU開發(fā)語言重寫程序。HMPP工作平臺包括一個C和 Fortran的編譯器、代碼生成器以及一個無縫集成進(jìn)開發(fā)環(huán)境中的運行時系統(tǒng),HMPP工作平臺架構(gòu)如圖3。
圖3 HMPP工作平臺架構(gòu)圖
在多GPU設(shè)備環(huán)境或GPU集群環(huán)境下開發(fā)程序,除了上面提到的四種程序開發(fā)技術(shù)之外,還需要其他必要輔助技術(shù)。一般來說,管理多個GPU設(shè)備可以使用OpenMP技術(shù),在使用CUDA時還能夠使用CUDA提供的特殊功能API來管理多GPU設(shè)備;在管理由CPU+GPU異構(gòu)系統(tǒng)作為節(jié)點構(gòu)造的集群時,可以使用 MPI技術(shù),也可以使用 Charm++技術(shù)。具體應(yīng)用中,OpenMP和MPI配合使用的情況居多。
對于在 GPU通用計算上發(fā)展階段積累了大量基于底層圖形API方法程序的開發(fā)者來說,繼續(xù)使用基于底層圖形API方法仍然適用,這樣可以解決如何處理遺留代碼的問題,不用對原來的程序做太多修改。缺點主要表現(xiàn)為:首先,編程人員必須編寫控制圖形流水線的程序,如分配紋理存儲、構(gòu)造圖形素元等,這要求編程人員對圖形API以及GPU硬件特點與限制需要有詳細(xì)了解。其次,編程人員仍然需要利用紋理、三角形等圖形素元表達(dá)他們的算法。此外,這種方式在新的基于統(tǒng)一渲染架構(gòu)的 GPU產(chǎn)品上運行時的代碼執(zhí)行效率會有些不足,在開發(fā)新程序時相比其他方法也沒有優(yōu)勢。
對于那些采用少量專業(yè)領(lǐng)域算法的應(yīng)用程序,這種場合中開發(fā)者往往無法在標(biāo)準(zhǔn)函數(shù)庫找到對應(yīng)程序,這時最佳的開發(fā)方法是使用諸如CUDA、OpenCL之類的基于低層次抽象的編程工具。在這種情況下,影響性能的關(guān)鍵代碼往往集中于少量程序段,由開發(fā)者完全自己編寫這些代碼是切實可行的,這樣可以充分利用 GPU的具體數(shù)據(jù)結(jié)構(gòu)以及其他的優(yōu)化方法,以獲得最佳的加速效果。缺點是一般需要學(xué)習(xí)一門新的編程語言,不適用于遺留代碼較多的場合。
對于大部分運行時間都用于執(zhí)行標(biāo)準(zhǔn)函數(shù)的應(yīng)用程序,使用 GPU加速版本的標(biāo)準(zhǔn)函數(shù)庫可以很容易地提高執(zhí)行效率,而獲得效率的關(guān)鍵是盡量減少 GPU與主機之間的通訊。基于高層次抽象的函數(shù)庫或模板庫方法的缺點是這類函數(shù)庫的靈活性稍差,并且有可能造成多余的存儲器訪問。
對于大量使用專業(yè)領(lǐng)域算法應(yīng)用程序的場合,在標(biāo)準(zhǔn)函數(shù)庫內(nèi)找不到對應(yīng),而開發(fā)者自己編寫全部代碼又不現(xiàn)實,這時可以使用基于編譯器的方法。由于發(fā)展時間較短,目前這種方法也存在很多缺點,以Portland Group并沒有很好地隱藏內(nèi)核程序并行化的復(fù)雜度,用戶仍需要去做所有較大的工作,例如如何將嵌套循環(huán)結(jié)構(gòu)映射到底層的流處理器。
CPU+GPU異構(gòu)計算模式在當(dāng)前的高性能計算領(lǐng)域逐漸成為熱點研究方向。文中分析了基于CPU+GPU異構(gòu)計算模式程序開發(fā)面臨的主要困難,總結(jié)了當(dāng)前主要的可用解決途徑和研究方向,并對各種編程方法的適用場合和各自的優(yōu)缺點進(jìn)行了詳細(xì)分析。目前,GPU產(chǎn)品的硬件架構(gòu)在向著有利于程序設(shè)計的方向不斷改進(jìn),學(xué)術(shù)界和工業(yè)界對基于CPU+GPU異構(gòu)計算的編程方法研究也在快速發(fā)展,可以預(yù)見,隨著 GPU編程方法研究的不斷深入,基于 CPU+GPU的異構(gòu)計算系統(tǒng)將會在高性能計算領(lǐng)域發(fā)揮更大的作用。
[1]NVIDIA Corporation. CUDA Programming Guide 2.3[Z/OL].(2009-11-02)[2010-06-03].http://developer.nvidia.com/objec t/cuda.html.
[2]NVIDIA Corporation. NVIDIA Tesla GPU Computing Technical Brief 1.0[Z/OL]. (2007-5-05)[2010-06-03]. http://developer.nvidia.com/object/cuda.html.
[3]張舒, 褚艷利. GPU高性能計算之CUDA[Z]. 北京:中國水利水電出版社, 2009.