靳慧亮 張波
DOI:10.16644/j.cnki.cn33-1094/tp.2021.11.001
摘? 要: 隨著國(guó)產(chǎn)計(jì)算機(jī)的推廣應(yīng)用,原X86平臺(tái)開(kāi)發(fā)的軟件經(jīng)常面臨國(guó)產(chǎn)化平臺(tái)適配的需求,且要求適配后的功能、性能不降低。以大批量實(shí)時(shí)圖像渲染類的應(yīng)用為例,性能問(wèn)題是國(guó)產(chǎn)化平臺(tái)適配時(shí)經(jīng)常遇到的難題。文章以主流的國(guó)產(chǎn)軟硬件平臺(tái)為研究基準(zhǔn),以對(duì)比實(shí)驗(yàn)形式論證了基于QtOpenGL的實(shí)時(shí)渲染軟件國(guó)產(chǎn)化適配性能優(yōu)化的關(guān)鍵技術(shù)點(diǎn)及解決方法。提出了六條切實(shí)可行的顯示性能優(yōu)化技術(shù)途徑,這些成果對(duì)于基于QtOpenGL的國(guó)產(chǎn)平臺(tái)顯示性能的優(yōu)化工作有借鑒意義。
關(guān)鍵詞: Qt; OpenGL; 國(guó)產(chǎn)計(jì)算機(jī); 性能優(yōu)化
中圖分類號(hào):TP311.1? ? ? ? ? 文獻(xiàn)標(biāo)識(shí)碼:A? ? ?文章編號(hào):1006-8228(2021)11-01-04
Research on performance optimization for large amount graph rendering with QtOpenGL
Jin Huiliang, Zhang Bo
(China Academy of Electronic and Information Technologies, Beijing 100041, China)
Abstract: ChinaProduced computer and operation systems are gradually applied for critical equipment, meanwhile the software for these platforms is progressing rapidly. Software performance is one of the major issues while migrating software from X86 platform to ChinaProduced platforms, especially the rendering of large amount real time graphs. Taking the mainstream domestic software and hardware platforms as the research benchmark, this paper demonstrates the key technical points and solutions for performance optimization of QtOpenGL based real-time rendering software on ChinaProduced platforms in the form of comparative experiments. Six feasible technical approaches for display performance optimization are proposed, these results can be used as a reference for the optimization of QtOpenGL based display performance of ChinaProduced platforms.
Key words: QtOpenGL; ChinaProduced computer; performance optimization
0 引言
當(dāng)前國(guó)產(chǎn)計(jì)算機(jī)在政府、企事業(yè)單位、關(guān)鍵型號(hào)裝備等領(lǐng)域應(yīng)用越來(lái)越廣泛,主流的國(guó)產(chǎn)CPU處理器也達(dá)到16核心以上,并發(fā)能力更強(qiáng),可以支持更多高性能的應(yīng)用。在裝備領(lǐng)域,具有人機(jī)顯示界面的軟件是最常見(jiàn)的應(yīng)用場(chǎng)景之一[1],該類軟件對(duì)計(jì)算機(jī)實(shí)時(shí)圖形顯示能力的要求很高。圖形顯示作為典型的性能密集型應(yīng)用,圖像渲染性能的高低能夠表現(xiàn)計(jì)算機(jī)硬件和軟件的綜合效能。在硬件配置相對(duì)固定的條件下,軟件層面的性能優(yōu)化就起到了決定性的作用。本文從OpenGL渲染入手,用對(duì)比實(shí)驗(yàn)的方式,論證了國(guó)產(chǎn)計(jì)算機(jī)平臺(tái)軟件顯示性能的優(yōu)化技術(shù)方法。
1 國(guó)產(chǎn)平臺(tái)介紹
按照CPU分類,當(dāng)前主流的國(guó)產(chǎn)計(jì)算機(jī)主要有以下三類。①飛騰處理器系列CPU國(guó)產(chǎn)計(jì)算機(jī),飛騰處理器是由國(guó)防科技大學(xué)研發(fā),兼容2011年發(fā)布的ArmV8指令集,典型型號(hào)為飛騰1500A,具有16核心,主頻2GHz[2]。②龍芯CPU國(guó)產(chǎn)計(jì)算機(jī),龍芯處理器是由中科院計(jì)算所研發(fā),采用MIPS指令集,典型型號(hào)為龍芯3A3000四核64位通用處理器,主頻1.5GHz[3]。③申威CPU國(guó)產(chǎn)計(jì)算機(jī),申威處理器是由上海高性能集成電路設(shè)計(jì)中心研發(fā),采用自主設(shè)計(jì)的指令集,申威1621單芯片中包含16核64位處理器,主頻2GHz[4]。上述三類國(guó)產(chǎn)CPU平臺(tái)在國(guó)產(chǎn)計(jì)算機(jī)領(lǐng)域占了很大份額,并都形成了各自的應(yīng)用生態(tài)。盡管是基于不同的CPU指令集,但在圖形渲染方面,通常采用OpenGL技術(shù)作為底層圖形庫(kù)通用技術(shù)方案。
2 OpenGL渲染管線
OpenGL是跨平臺(tái)計(jì)算機(jī)圖形應(yīng)用程序的應(yīng)用規(guī)范,廣泛應(yīng)用于仿真、游戲、GIS系統(tǒng)等領(lǐng)域,實(shí)現(xiàn)二三維圖形的渲染。OpenGL渲染過(guò)程需要經(jīng)歷CPU、GPU兩個(gè)階段,CPU中進(jìn)行圖形計(jì)算,完成之后調(diào)用OpenGL開(kāi)發(fā)接口在GPU中創(chuàng)建緩存區(qū)緩存繪制數(shù)據(jù),將生成的幾何數(shù)據(jù)(頂點(diǎn)坐標(biāo)、幾何單元等)輸入到一系列著色器中進(jìn)行處理。著色器(Shaders)是一段用著色器語(yǔ)言GLSL編寫(xiě)的腳本,在OpenGL渲染過(guò)程中通常依次經(jīng)過(guò)頂點(diǎn)著色、細(xì)分著色以及幾何著色階段,然后對(duì)數(shù)據(jù)進(jìn)行光柵化處理,生成片元數(shù)據(jù),最后經(jīng)過(guò)片元著色,將圖形渲染到屏幕上[5]。OpenGL的可編程管線著色器能直接對(duì)GPU的數(shù)據(jù)緩存進(jìn)行操作,渲染效率高, 在X86商用計(jì)算機(jī)上幀率通常能達(dá)到60FPS以上。
OpenGL的完整渲染過(guò)程如圖1所示,客戶端運(yùn)行于CPU中,通過(guò)驅(qū)動(dòng)程序?qū)?shù)據(jù)與渲染指令進(jìn)行連接,并發(fā)送到服務(wù)端執(zhí)行。服務(wù)端和客戶端為異步調(diào)用,因此兩端都能夠不間斷的工作。客戶端計(jì)算完畢后,將計(jì)算結(jié)果和命令塊組合在一起送入緩沖區(qū),然后緩沖區(qū)會(huì)發(fā)送到服務(wù)端執(zhí)行。服務(wù)端執(zhí)行緩沖區(qū)內(nèi)容的同時(shí),客戶端已經(jīng)在進(jìn)行下一個(gè)周期的計(jì)算,如此循環(huán)實(shí)現(xiàn)計(jì)算和圖形資源的最大化利用。
由于國(guó)產(chǎn)GPU當(dāng)前尚未大規(guī)模應(yīng)用,國(guó)產(chǎn)計(jì)算機(jī)通常采用國(guó)產(chǎn)CPU加商用GPU的整機(jī)方案。本文作者在進(jìn)行國(guó)產(chǎn)計(jì)算機(jī)平臺(tái)的軟件適配時(shí),同樣的圖形渲染軟件在國(guó)產(chǎn)計(jì)算機(jī)上無(wú)法達(dá)到商用機(jī)幀率,甚至在繪制批量大時(shí)會(huì)低于10FPS,即一個(gè)周期的圖形刷新時(shí)間大于100毫秒,人在交互時(shí)會(huì)感到明顯的操作卡滯和視覺(jué)延遲[6],因此需要有針對(duì)性地優(yōu)化國(guó)產(chǎn)機(jī)軟件顯示性能。本文設(shè)計(jì)了五組對(duì)比試驗(yàn),探討國(guó)產(chǎn)計(jì)算機(jī)平臺(tái)OpenGL渲染性能進(jìn)行優(yōu)化的技術(shù)途徑。由于原生OpenGL沒(méi)有提供窗口系統(tǒng)和用戶交互的函數(shù),本文使用跨平臺(tái)軟件框架Qt作為支持OpenGL的窗口和交互系統(tǒng)開(kāi)發(fā)環(huán)境。
實(shí)驗(yàn)采用的硬件配置為:飛騰1500A型16核心處理器,32G內(nèi)存,AMD Radeon HD7470顯卡。OpenGL核心版本為3.3,mesa版本為11.2.0,采用Qt5.9.2作為界面開(kāi)發(fā)環(huán)境。
3 性能優(yōu)化實(shí)驗(yàn)設(shè)計(jì)
針對(duì)OpenGL典型渲染流程中數(shù)據(jù)存儲(chǔ)、數(shù)據(jù)計(jì)算、數(shù)據(jù)提交等階段,結(jié)合筆者工作中對(duì)OpenGL顯示軟件的優(yōu)化經(jīng)驗(yàn),提煉出以下五種典型的可能出現(xiàn)性能問(wèn)題的關(guān)鍵環(huán)節(jié)。并設(shè)計(jì)對(duì)比實(shí)驗(yàn)。實(shí)驗(yàn)采用Qt提供的計(jì)時(shí)器類QTime作為基準(zhǔn),計(jì)算任務(wù)開(kāi)始到任務(wù)結(jié)束經(jīng)過(guò)的時(shí)間,作為度量計(jì)算性能的依據(jù)。時(shí)間單位為毫秒,耗時(shí)越短,說(shuō)明性能越高, 最終軟件顯示的幀率越高,操作越流暢。
3.1 數(shù)據(jù)存儲(chǔ)性能
OpenGL客戶端在進(jìn)行頂點(diǎn)坐標(biāo)、紋理坐標(biāo)、顏色矩陣計(jì)算前,首先要將渲染對(duì)象的原始坐標(biāo)存儲(chǔ)到內(nèi)存中。比如要在屏幕上繪制一些點(diǎn),要先將繪制點(diǎn)的原始坐標(biāo)存儲(chǔ)到內(nèi)存,數(shù)據(jù)存儲(chǔ)就需要用到軟件容器,如Qt提供的QVector容器和C++標(biāo)準(zhǔn)庫(kù)std::vector容器。QVector在內(nèi)存中連續(xù)存儲(chǔ)數(shù)據(jù),支持按序號(hào)快速查找,而std::vector的內(nèi)部結(jié)構(gòu)更為簡(jiǎn)單。此外,在數(shù)據(jù)長(zhǎng)度相對(duì)確定時(shí),也可以使用滿足最大數(shù)據(jù)存儲(chǔ)的數(shù)組保存坐標(biāo)對(duì)象。本實(shí)驗(yàn)采用上述三種典型的數(shù)據(jù)容器,依次插入float類型數(shù)據(jù),并比較三類容器數(shù)據(jù)存儲(chǔ)的時(shí)間。實(shí)驗(yàn)結(jié)果見(jiàn)表1和圖2。
從實(shí)驗(yàn)結(jié)果可以看出,小于100萬(wàn)次寫(xiě)入時(shí),std::vector和QVector的性能相當(dāng),在100萬(wàn)次以上,QVector的耗時(shí)幾乎是std::vector的兩倍。而同樣次數(shù)的寫(xiě)入,使用數(shù)組存儲(chǔ)的速度是std::vector的五倍,是QVector的將近十倍。這是由于QVector初始化時(shí)會(huì)預(yù)先分配兩倍于實(shí)際需要數(shù)據(jù)的空間大小[7],如果數(shù)據(jù)超出預(yù)先分配的空間,QVector會(huì)重新分配整個(gè)內(nèi)存空間,導(dǎo)致耗時(shí)增大。因此,在數(shù)據(jù)量較為確定時(shí),使用預(yù)先分配空間的數(shù)組能大大縮短OpenGL的數(shù)據(jù)存儲(chǔ)時(shí)間,進(jìn)而縮短整體的圖形渲染時(shí)間。
3.2 數(shù)據(jù)計(jì)算性能
OpenGL計(jì)算頂點(diǎn)坐標(biāo)、紋理坐標(biāo)等的過(guò)程可以抽象為矩陣的平移、縮放、旋轉(zhuǎn)。重新設(shè)計(jì)算法,將串行的計(jì)算過(guò)程并行化后,也能提升計(jì)算性能。本實(shí)驗(yàn)對(duì)比了采用單線程計(jì)算和多線程計(jì)算時(shí),分別需要的計(jì)算時(shí)間。計(jì)算過(guò)程基于3.1中存儲(chǔ)的float數(shù)據(jù),對(duì)數(shù)據(jù)逐一進(jìn)行一次乘法(旋轉(zhuǎn))和一次加法(平移)。多線程采用了Qt的并行計(jì)算框架QtConCurrent,使用該框架可以不用考慮線程鎖的問(wèn)題,并且QtConcurrent會(huì)根據(jù)可用CPU核數(shù)自動(dòng)調(diào)整線程數(shù)。
實(shí)驗(yàn)結(jié)果見(jiàn)表2。從實(shí)驗(yàn)可以看出,在10萬(wàn)次計(jì)算以下時(shí),多線程耗時(shí)要高于單線程,并且次數(shù)越少,多線程相對(duì)單線程耗時(shí)越大。在10萬(wàn)次計(jì)算以上時(shí),多線程計(jì)算的優(yōu)勢(shì)更加明顯(100萬(wàn)次三倍,1000萬(wàn)次六倍),實(shí)驗(yàn)結(jié)果證明,大批量計(jì)算時(shí)多線程能成倍縮短計(jì)算時(shí)間。但在計(jì)算次數(shù)較少時(shí),多線程的上下文切換耗時(shí)可能會(huì)高于多線程計(jì)算節(jié)省的時(shí)間,導(dǎo)致了多線程的耗時(shí)反而高過(guò)單線程[8]。批量切換的性能門限,與計(jì)算機(jī)配置、程序算法設(shè)計(jì)有直接關(guān)系,需要根據(jù)實(shí)際情況進(jìn)行摸底測(cè)試確定。
3.3 數(shù)據(jù)遍歷性能
在渲染數(shù)據(jù)計(jì)算時(shí),由于繪制對(duì)象的不同,會(huì)產(chǎn)生一些大小不確定的中間數(shù)據(jù),由于數(shù)據(jù)量大小未知,無(wú)法使用預(yù)先分配的數(shù)組存儲(chǔ),只能采用標(biāo)準(zhǔn)的數(shù)據(jù)容器。而對(duì)這些數(shù)據(jù)的遍歷時(shí)間也會(huì)對(duì)整體渲染時(shí)間產(chǎn)生影響。本文選取了三類Qt標(biāo)準(zhǔn)容器(QVector,QList和QLinkedList),對(duì)比數(shù)據(jù)遍歷性能。QVector存儲(chǔ)時(shí)占用連續(xù)存儲(chǔ)的內(nèi)存空間,而QList的數(shù)據(jù)存儲(chǔ)在堆上。QLinkedList是鏈表存儲(chǔ),使用迭代器而不是索引進(jìn)行遍歷。實(shí)驗(yàn)結(jié)果見(jiàn)表3,實(shí)驗(yàn)證明,在三類容器中,QVector的順序遍歷速度在三類容器中最優(yōu),但結(jié)果差距不明顯,結(jié)果與Qt官方推薦的結(jié)果一致。
3.4 數(shù)據(jù)繪點(diǎn)性能
點(diǎn)繪制是雷達(dá)等傳感器應(yīng)用的典型場(chǎng)景[9],本實(shí)驗(yàn)對(duì)OpenGL的點(diǎn)繪制性能進(jìn)行對(duì)比。OpenGL繪制管線中,提供了單點(diǎn)單次提交繪制的形式glVertex,和坐標(biāo)緩存批量提交繪制方式glDrawArrays,本實(shí)驗(yàn)對(duì)比了在不同點(diǎn)批量的情況下,采用單次和批量提交時(shí)繪制時(shí)間的差別,實(shí)驗(yàn)結(jié)果見(jiàn)表4和圖3。
結(jié)果證明在50萬(wàn)點(diǎn)以下,兩種點(diǎn)繪制方式的時(shí)間相差不大,在50萬(wàn)點(diǎn)以上,批量繪制點(diǎn)的時(shí)間明顯要短于單次提交。因?yàn)樵诖笈坷L制時(shí),采用批量提交的形式能減少CPU到GPU的數(shù)據(jù)提交次數(shù),成倍提升繪制速度。
3.5 調(diào)試打印
軟件人員在調(diào)試階段會(huì)在代碼中增加打印調(diào)試信息,如果軟件發(fā)布后沒(méi)有將打印刪除,頻繁的打印會(huì)嚴(yán)重拖慢性能,而打印耗時(shí)卻容易被忽視。本實(shí)驗(yàn)在3.2節(jié)計(jì)算處理基礎(chǔ)上,在每次計(jì)算時(shí)使用qDebug打印計(jì)算結(jié)果。對(duì)比在單線程和多線程情況下,需要的處理時(shí)間,實(shí)驗(yàn)結(jié)果見(jiàn)表5。對(duì)比表5和表2可見(jiàn),從10000次開(kāi)始,單線程增加打印的時(shí)間已經(jīng)是無(wú)打印計(jì)算的80倍,隨著計(jì)算次數(shù)的增加,這種差距不斷擴(kuò)大。而在多線程計(jì)算時(shí),打印耗時(shí)抵消了多線程計(jì)算縮短的時(shí)間。在1000萬(wàn)次計(jì)算時(shí),單線程和多線程的耗時(shí)均已經(jīng)超過(guò)了8分鐘,單線程下增加打印的耗時(shí)達(dá)到無(wú)打印耗時(shí)的400倍,多線程達(dá)2400倍。實(shí)驗(yàn)證明,在開(kāi)發(fā)那些對(duì)時(shí)間性能要求高的軟件時(shí),必須避免頻繁打印,從而提升軟件的性能。
4 結(jié)論
在OpenGL圖形渲染過(guò)程中,CPU客戶端的計(jì)算時(shí)間在整體渲染時(shí)間中占比很高。在國(guó)產(chǎn)化適配時(shí),降低CPU端的計(jì)算時(shí)間,就能夠顯著縮短整體的渲染用時(shí)??梢詮娜缦铝鶄€(gè)方面做CPU端性能優(yōu)化:
⑴ 在數(shù)據(jù)批量可預(yù)測(cè)的情況下,采用預(yù)先分配的數(shù)組進(jìn)行數(shù)據(jù)存儲(chǔ),提升數(shù)據(jù)存儲(chǔ)效率;
⑵ 采用多線程并行計(jì)算,降低圖形坐標(biāo)計(jì)算時(shí)間,充分利用國(guó)產(chǎn)處理器的多核性能;
⑶ 采用性能最高的數(shù)據(jù)容器,縮短大批量數(shù)據(jù)遍歷的耗時(shí),并且避免頻繁的隨機(jī)查找數(shù)據(jù);
⑷ 去掉減少代碼中的無(wú)效打印,減少由于打印帶來(lái)的CPU時(shí)間損耗;
⑸在圖形渲染階段,采用OpenGL批量繪制方式提交,加快渲染速度。
此外,在OpenGL繪制時(shí),可以根據(jù)渲染類型或者頻次的差別,應(yīng)用分層渲染的方式,將高頻渲染和低頻渲染元素放在不同的圖層中處理,以降低性能負(fù)載。
參考文獻(xiàn)(References):
[1] 趙星漢,于洋.基于自主可控計(jì)算平臺(tái)的信號(hào)采集處理系統(tǒng)
設(shè)計(jì)與實(shí)現(xiàn)[J].中國(guó)電子科學(xué)研究院學(xué)報(bào),2013.1:100-105
[2] 孫立明,吳慶波.國(guó)產(chǎn)飛騰1500A處理器的顯存管理優(yōu)化[J].
計(jì)算機(jī)技術(shù)與發(fā)展,2017.27(5):6-9
[3] 孟小甫,高翔,從明,張爽爽.龍芯3A多核處理器系統(tǒng)級(jí)性能
優(yōu)化與分析[J].計(jì)算機(jī)研究與發(fā)展,2012.49(S1):137-142
[4] 胡向東,楊劍新,朱英.高性能多核處理器申威1600[J].中國(guó)
科學(xué):信息科學(xué),2015.45:513-522
[5] Dave Shreiner等.OpenGL編程指南[M].機(jī)械工業(yè)出版社,
2016.
[6] A. B. Watson, "High Frame Rates and Human Vision: A
View through the Window of Visibility," in SMPTE Motion Imaging Journal[J].2013.122(2):18-32
[7] Marc Mutz, Understand the Qt Containers[], https://www.
cleanqt.io/blog/exploring-qt-containers, 2018.
[8] Jonas Trümper,Johannes Bohnet,Jürgen D?llner.
Understanding complex multithreaded software systems by using trace visualization[P].Software visualization,2010.
[9] 吉軍.雷達(dá)點(diǎn)跡的目標(biāo)智能特征提取方法研究[J].信息技術(shù),
2013.6.