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