咼 濤 熊庭剛 黃 亮
(武漢數(shù)字工程研究所 武漢 430205)
近年來,隨著大數(shù)據(jù)時代的到來,在科學(xué)研究、互聯(lián)網(wǎng)應(yīng)用、電子商務(wù)等諸多應(yīng)用領(lǐng)域?qū)τ诖笠?guī)模圖形顯示、數(shù)據(jù)處理的需求變的日益迫切,通用CPU與單GPU 協(xié)同的計算能力已經(jīng)無法滿足要求[1]。目前國內(nèi)基本上都是采用進(jìn)口的GPU 芯片,缺乏自主高性能GPU 芯片,國產(chǎn)GPU 的研究勢在必行,多GPU 并行渲染技術(shù)作為現(xiàn)代GPU 發(fā)展的重要趨勢也是其重要的研究方向[2~10]。
多GPU 并行渲染技術(shù)包含兩種不同的渲染方法:交替幀渲染(Alternate Frame Rendering,AFR)和分割幀渲染(Split Frame Rendering,SFR)[11]。交替幀渲染方法將一組連續(xù)圖像分成奇數(shù)幀和偶數(shù)幀,由兩個GPU 單獨渲染,渲染完成后合成輸出;分割幀渲染方法將畫面分成幾個部分,每個GPU分別執(zhí)行相關(guān)的任務(wù)渲染,主CPU 同步和合成數(shù)據(jù)。下面介紹這些技術(shù)的主要工作流程。
交替幀渲染:CPU根據(jù)GPU的個數(shù)N將渲染畫面劃分成N 組,由第N 個GPU 渲染第N 幀。如圖1所示,將一組連續(xù)畫面分為奇數(shù)幀和偶數(shù)幀,然后交給兩個GPU 進(jìn)行渲染,由主GPU 統(tǒng)一合成并完整地顯示出最終畫面。
分割幀渲染:CPU根據(jù)GPU的個數(shù)N將當(dāng)前的渲染畫面按屏幕大小平均分為N 個區(qū)域并將每個區(qū)域交給一個GPU 渲染,然后再由主GPU 合成一個完整畫面。如圖2 所示,渲染畫面分為上部和下部,主GPU 完成畫面的上部,輔助GPU 完成畫面的下部,然后輔助GPU 將渲染后的畫面?zhèn)鬏數(shù)街鱃PU,主GPU將其與渲染畫面的上半部分組合成完整畫面。同樣,如果四個GPU 并行工作,圖像將分為四個部分進(jìn)行渲染。

圖1 交替幀渲染原理示意圖

圖2 分割幀渲染原理示意圖
CPU 對屏幕不同區(qū)域所需的像素著色能力進(jìn)行預(yù)測,對每一幀進(jìn)行動態(tài)分割,保證每個GPU 的渲染任務(wù)均衡。如果單幀的上半部分比較簡單,所需的像素著色能力較弱,則CPU通過預(yù)測進(jìn)行重新分割,將該幀的大半部分像素分配給負(fù)責(zé)主GPU進(jìn)行渲染,剩余部分的像素交給輔助GPU 進(jìn)行渲染。由于每幀的復(fù)雜性不一致,其分配比例也會動態(tài)變化。這種動態(tài)幀分割方法將有助于GPU 的負(fù)載均衡。
SFR 和AFR 模式都只能擴(kuò)展系統(tǒng)的三角生成速率和像素填充速率,并不能擴(kuò)大紋理緩存。因為每個GPU 在進(jìn)行渲染時都是使用本地緩存,渲染結(jié)果必須以廣播的形式發(fā)送到其他GPU。盡管GPU生產(chǎn)廠商針對游戲應(yīng)用做了很大的優(yōu)化,Monfort 等也在AFR、SFR 的基礎(chǔ)之上提出了Hybrid 模式并在游戲應(yīng)用中得到了較好的性能提升,但是這些配置方案在通用程序中作用有限[12]。目前SLI和Crossfire 技術(shù)最多支持8 個GPU[13~14],價格昂貴的Nvidia Tesla 系統(tǒng)可組成更多數(shù)量的多GPU 系統(tǒng),GPU 間的數(shù)據(jù)處理和共享由專門硬件實現(xiàn)[15],其主要面向科學(xué)計算。
基于分割幀的渲染思想,本文提出了一種基于分割幀的多GPU 并行渲染方法,根據(jù)各GPU 完成計算的時間參數(shù),確定各GPU 的分割因子,并實時更新各GPU 的有效光柵化區(qū)域,以使各個GPU 完成計算的時間趨于一致,提升多GPU 系統(tǒng)的效能,如圖3所示。

圖3 基于分割幀的多GPU圖形處理流程圖
每個GPU 從CPU 和主存儲器獲取圖形處理命令和數(shù)據(jù),主要包括頂點數(shù)據(jù),紋理數(shù)據(jù)等,圖3 以兩個GPU 為例進(jìn)行說明。每個GPU 根據(jù)圖形處理命令完成頂點處理,圖元裝配,裁剪,并將原始坐標(biāo)轉(zhuǎn)換為屏幕坐標(biāo)空間。各GPU 根據(jù)圖形處理命令,讀取圖形處理數(shù)據(jù),如頂點、紋理等,進(jìn)行圖形處理計算,其中頂點處理由統(tǒng)一渲染著色器完成頂點坐標(biāo)轉(zhuǎn)換、光照計算等,圖元裝配單元根據(jù)圖元類型把頂點組裝成點、線、三角形圖元,裁剪單元移除椎體外的圖元,然后將圖元坐標(biāo)從剪切空間轉(zhuǎn)換為標(biāo)準(zhǔn)化的設(shè)備空間,再轉(zhuǎn)換到二維屏幕坐標(biāo)空間。
分割因子是本渲染方案的重點。根據(jù)分割因子確定各GPU 在一幀圖形數(shù)據(jù)中的有效光柵化區(qū)域。基于分割幀的多GPU 計算中,在轉(zhuǎn)化為屏幕坐標(biāo)空間之后,需要對后續(xù)圖形計算區(qū)域進(jìn)行劃分,各GPU 負(fù)責(zé)不同區(qū)域的圖形計算。設(shè)顯示區(qū)域的分辨率為M*N,包含2 個GPU 的系統(tǒng)中,基于水平分割的有效光柵化區(qū)域的示意圖如圖4 所示,根據(jù)分割因子不同,GPU0 的有效光柵化區(qū)域可為P*N,P0*N或P1*N等。

圖4 水平分割幀示意圖
復(fù)雜圖形應(yīng)用場景中,各區(qū)域計算復(fù)雜度隨著應(yīng)用實時改變,因此要實時更新各GPU 的有效光柵化區(qū)域,對于所需時間較長的GPU,需要減小其有效光柵化區(qū)域,降低其計算量;對于所需時間較短的GPU,需要增大其有效光柵化區(qū)域,提高其計算量。使各GPU 完成圖形計算的時間趨于一致,從而最大化多GPU 圖形處理系統(tǒng)計算性能。根據(jù)分割因子實時更新各GPU 有效光柵化區(qū)域的流程如圖5 所示,首先初始化分割因子,各GPU 完成相關(guān)圖形計算,獲取各GPU 完成圖形計算的時間,確定分割因子,根據(jù)分割因子更新各GPU 有效光柵化區(qū)域。
對于包含2個GPU 的圖形計算系統(tǒng),分割因子可初始化為1/2,即每個GPU 的有效光柵化區(qū)域為M/2*N;各GPU 完成圖形計算,并讀取各GPU 完成計算的時間,設(shè)當(dāng)前計算中GPU0,GPU1 的有效光柵化區(qū)域分別為P0*N,P1*N,其中:

GPU0,GPU1 完成圖形計算的時間分別為T0,T1,分割因子F計算公式為


圖5 根據(jù)分割因子實時更新各GPU有效光柵化區(qū)域流程圖
根據(jù)分割因子,更新下一幀圖形計算中各GPU有效光柵化區(qū)域,GPU0的有效光柵化區(qū)域行數(shù)為

GPU1的有效光柵化區(qū)域行數(shù)為

各GPU 對其有效光柵化區(qū)域之外的圖元進(jìn)行裁剪。確定有效光柵化區(qū)域之后,對有效光柵化區(qū)域以外的圖元進(jìn)行剔除,同時對與有效光柵化區(qū)域相交的圖元進(jìn)行裁剪,水平分割幀時圖元裁剪示意圖如圖6所示,設(shè)GPU0的有效光柵化區(qū)域為P0*N,則三角形圖元HGI 由GPU0 進(jìn)行計算,三角形圖元DEF 由GPU1 進(jìn)行圖形計算,三角形圖元ABC 與有效光柵化區(qū)域相交,需要進(jìn)行裁剪操作,三角形圖元ABC 與有效光柵化區(qū)域相交于M、N,裁剪產(chǎn)生新的三角形圖元MAN,CMN,CNB,其中三角形圖形MAN 由GPU0 進(jìn)行計算,三角形圖元CMN,CNB由GPU1進(jìn)行計算。

圖6 分割幀圖元裁剪示意圖
各GPU 對其有效光柵化區(qū)域的圖元進(jìn)行光柵化、片段處理及像素處理,像素處理的結(jié)果被寫入幀緩沖區(qū),各GPU 采用雙幀緩沖區(qū)結(jié)構(gòu)。副GPU將其計算產(chǎn)生的像素數(shù)據(jù)通過DMA 傳送到主GPU,主GPU 經(jīng)過同步與幀數(shù)據(jù)合成,由顯示控制器輸出到顯示設(shè)備。
以雙GPU 系統(tǒng)為例,本文設(shè)計的多GPU 并行處理結(jié)構(gòu)如圖7 所示。將兩塊帶GPU 芯片的顯卡插入主板PCI-E 的兩個插槽中,或通過PCI-E 橋?qū)⑺鼈兗稍谕伙@卡上。CPU 通過PCI-E 總線完成GPU 之間的數(shù)據(jù)傳輸,GPU 處理完的幀數(shù)據(jù)被集合起來處理,然后作為整體輸出。為了確保雙GPU的任務(wù)劃分和協(xié)同工作,CPU將任務(wù)分配給兩個GPU渲染,最后輸出完整的圖形。

圖7 支持多種渲染方式的多GPU并行處理結(jié)構(gòu)
兩顆GPU 是非對等的,一顆GPU 作為主GPU,另一顆則作為輔助GPU。CPU 負(fù)責(zé)任務(wù)分配、渲染、后期合成、輸出等,主GPU 從CPU 接收任務(wù)進(jìn)行相關(guān)處理,負(fù)責(zé)渲染和輸出;而輔助GPU 只是接收來自CPU的任務(wù)進(jìn)行相關(guān)渲染,然后將渲染后的結(jié)果通過PCI-E 總線傳送回主GPU。為了正常運行,兩顆GPU 除了各自擁有獨立的命令緩沖區(qū)和PCI-E 存儲空間外,還共享部分系統(tǒng)內(nèi)存。驅(qū)動程序根據(jù)應(yīng)用程序和渲染模式,為每顆GPU 分配渲染工作量。
根據(jù)上述方案搭建測試平臺,對雙GPU 系統(tǒng)進(jìn)行測試,測試的硬件平臺見表1。其中測試顯卡使用中船重工第七〇九所自主研發(fā)的國產(chǎn)顯卡GP101。測試步驟及方法如下所示:

表1 測試硬件平臺
1)在開發(fā)板上,插入兩個PCI-E 顯卡,兩個顯卡完全一致,Device ID 及Vendor ID 也一致。加載驅(qū)動后,識別兩個設(shè)備,說明兩個顯卡分別加載驅(qū)動成功。
2)運行繪制程序,離CPU 較近的顯卡HDMI輸出系統(tǒng)內(nèi)容,而離CPU 較遠(yuǎn)的顯卡HDMI輸出顯示為花屏,與操作系統(tǒng)有關(guān),操作系統(tǒng)選擇顯卡中的一個為主顯卡,輸出系統(tǒng)內(nèi)容,而另一個顯卡在驅(qū)動加載后,在沒有往里面寫數(shù)據(jù)之前,為幀緩沖區(qū)的默認(rèn)數(shù)據(jù),即花屏。
3)運行繪制程序,看到離CPU較遠(yuǎn)的顯卡的顯示輸出由花屏(驅(qū)動加載后的默認(rèn)初始值)變?yōu)殇秩镜娜齻€矩形。此時兩個顯卡驅(qū)動加載成功,顯示正確。
進(jìn)一步,通過在應(yīng)用層讀寫寄存器,可以實現(xiàn)兩個顯卡分別繪制矩形。測試步驟如下所示:
1)編寫應(yīng)用程序。
2)通過MMAP 把兩個顯卡的顯存,MMIO 分別映射到用戶層。
3)讀寫寄存器,畫矩形的函數(shù),編寫用戶層程序,寫寄存器,操作硬件,畫矩形。
4)安裝驅(qū)動,運行應(yīng)用程序后,可以看到效果,兩個顯卡分別連接顯示器,都有矩形顯示。
繪制階段與各個GPU 所分配的繪制數(shù)據(jù)大小相關(guān)。在1024×768、2048×1080 和3840×2160 分辨率下,雖然光柵化操作差異巨大,但是由于GPU 具有較好的數(shù)據(jù)并行處理能力,繪制時間都約13ms且相差不大。復(fù)雜幾何模型的數(shù)據(jù)繪制會增大繪制階段開銷,但不會影響流水線中的其他階段。軟件繪制與顯示階段主要負(fù)責(zé)對合成結(jié)果圖像進(jìn)行2D 繪制并寫入GPU 顯示寄存器,其主要受顯示策略和2D繪制時間影響。實驗中采用CPU單線程繪制對應(yīng)區(qū)域的結(jié)果圖像,與GPU 硬件繪制相比,高分辨率條件下軟件繪制開銷較大,約5ms~10ms。
通過對兩塊國產(chǎn)顯卡GP101進(jìn)行測試可知,本設(shè)計可支持多GPU 對繪制任務(wù)進(jìn)行并行處理,其繪制效率與單塊GPU 相比提高了90%。本設(shè)計不僅達(dá)到了預(yù)期的效果,也填補了多GPU 并行處理技術(shù)在國產(chǎn)化方面的空白。
本文提出了一種基于分割幀的國產(chǎn)GPU 并行渲染方法,使用兩塊國產(chǎn)顯卡進(jìn)行驗證。兩顆GPU是非對等的,一顆GPU 作為主GPU,另一顆則作為輔助GPU。CPU負(fù)責(zé)任務(wù)分配,渲染,后期合成,輸出等,主GPU 從CPU 接收任務(wù)進(jìn)行相關(guān)處理,負(fù)責(zé)渲染和輸出;而輔助GPU 只是接收來自CPU 的任務(wù)進(jìn)行相關(guān)渲染,然后將渲染后的結(jié)果通過PCI-E總線傳送回主GPU。通過對兩塊國產(chǎn)顯卡GP101進(jìn)行測試可知,本設(shè)計可支持多GPU 對繪制任務(wù)進(jìn)行并行處理,其效率比單塊GPU提高了90%。