所謂多媒體,包含三個模塊:圖形處理器(GPU),顯示模塊(Display),視頻模塊(Video)。顯示模塊負責把所有的內容輸出到屏幕,視頻模塊負責解碼片源,也負責編碼攝像頭的錄制內容。圖像信號處理(ISP)模塊暫時不算在內,以后另說。
GPU是大家喜聞樂見,津津樂道的部分,各種跑分評測都會把GPU性能重點考量。但是實際上,在定義一個手機芯片多媒體規(guī)格的時候,我們首先要確定的參數(shù),不是GPU有多強大,而是顯示輸出的分辨率:是720p,1080p,2K還是更高。這個參數(shù),決定了GPU填充率(fill rate)的下限,系統(tǒng)帶寬大小,內存控制器的數(shù)量,還會影響CPU和ISP的選擇,從而決定整體功耗及成本。所以,這一參數(shù)至關重要。
舉幾個典型的例子:
超低端:展訊的SC9832,顯示分辨率720p,ARM Cortex-A7MP4,Mali400MP2, 1xLPDDR3
低端:聯(lián)發(fā)科的MT6739,顯示分辨率1444x720,ARM Cortex-A53MP4@1.5GHz,IMG PowerVR GE8100,1xLPDDR3
中端:高通的驍龍652,顯示分辨率2560x1600,Cortex A72MP4/Cortex A53MP4,Adreno 510,2xLPDDR3
高端:海思的麒麟970,顯示分辨率不高于2K,Cortex A73MP4/Cortex A53MP4,G72MP12,4xLPDDR4
我們可以看到,隨著顯示分辨率上升,芯片規(guī)格越來越高,但到2K就停止了。下面通過定量分析,讓我們看看其中每個參數(shù)背后的考量。
如上圖所示,手機多媒體一定包含圖形,視頻和顯示三個模塊。為什么桌面圖形處理器囊括了視頻和顯示輸出,而手機要把它們分開?再極端一點,其實所有的多媒體和圖像處理都是計算,為什么不全用CPU做了?把省下來的面積全做成CPU,豈不更好?不好意思,這不可行。原因很簡單,功耗。請記住,由于沒有風扇,手機芯片無論怎么設計,在各種長時間運行場景下,功耗一定得低于2.5瓦,短時間運行也不宜超過5瓦,瞬時運行倒是可以更高。這個2.5瓦,除了跑多媒體,還得包括CPU,總線和內存帶寬。而多媒體的每個模塊,在做其擅長的事情時,功耗遠低于CPU。16nm上視頻編解碼器在處理4K30FPS幀的功耗在60毫瓦左右,而相同的事情讓CPU做,我粗略的估計了下,至少得四個跑在2Ghz的A53,還得是NEON指令(功耗為Dhrystonex2.5),那就是1.5瓦以上的功耗。相差25倍。
再看顯示模塊的功耗,分辨率2K60幀下,16nm工藝需要50毫瓦左右。而用GPU做相同的事情,粗略的算,需要300毫瓦左右。用CPU還要乘以2到3,近1瓦。
所以,只是放個4K的視頻并輸出到屏幕,就已經(jīng)到了功耗上限了,還沒有計算訪存功耗呢,更不用說支持10小時以上的視頻播放。所以,手機多媒體必須把GPU,視頻和顯示模塊分化出來。
當然,如果手機非常低端,一定要用CPU來進行軟件解碼,從而省了硬件面積(1080p30fps解碼是1平方毫米,不到A53單核2倍),也不是完全不可行。因為超低端可能只要支持1080p視頻就可以了,并且由于CPU數(shù)量小還是小核,功耗雖然高些但也不是完全不能接受。同時,低端的手機CPU本身處理能力弱,軟件優(yōu)化和多核負載均衡一定要做好。而中高端手機不會為了省面積這么做的。
看到這可能有人會問,為什么視頻是4K的,而顯示只有2K呢?分辨率不匹配,多出來的像素不是浪費么?確實如此。不過由于受到手機屏的限制,目前就算高端手機也還沒支持4K。并且屏幕分辨率提高一倍,功耗也提高一倍。這對于本就是耗電大戶的屏幕來說,是個大問題,要解決就等著以后更低功耗的屏幕出現(xiàn)了。
反過來,為什么不把視頻解碼降到2K呢?那是因為視頻源的格式是片源決定的,4K的片源沒法用2K的解碼器去解,只能解完再降分辨率。
還有一個問題,為什么上文中視頻是30幀,而顯示是60幀呢?我曾經(jīng)做過實驗,特意把屏幕刷新率改成30,結果完全沒發(fā)現(xiàn)什么不同。但是,據(jù)說大部分人的眼神比較好,動態(tài)視覺強,對于非自然圖像很敏感,所以對于手機背景等圖像,一定要做到60幀才能感到流暢。而對于自然圖像,比如看視頻,30幀就感到流暢了。所以,這兩類刷新率就約定成俗了。
下面,我們來看下,屏幕分辨率是如何影響GPU,系統(tǒng)帶寬以及內存控制器的。先看下圖的顯示模塊。
顯示模塊的任務和操作系統(tǒng)的用戶界面(UI)中圖層的概念有關系。我們看到的最終屏幕畫面就是多層圖層合成疊加的。同時,顯示模塊還可以對每一層進行旋轉,縮放等操作,最終生成一幅圖,轉成所需的信號格式輸出。顯示模塊的輸入可以是解碼后的視頻,也可以是GPU丟過來的完成初步合成的圖層。上圖中,顯示模塊支持3路輸入,外加背景圖輸入(Smart Layer),我們一般關注前者。
以安卓為例,用到的圖層一般在4-8層。假設顯示是1080p60fps,那每一層的帶寬就是1920x1080x60x4(RGBA)=480MB/s,8層就是4GB/s。這是系統(tǒng)給顯示模塊的輸入,總線上還得有輸出。假設這時候再播放4K30fps視頻,所需帶寬未壓縮是1.2Gx1.25=1.5GB/s,
如下:
而GPU跑用戶界面時的典型帶寬開銷如下:
根據(jù)UI的復雜度不同,每60幀需要的帶寬可達到1GB/s(壓縮后),沒壓縮時在1.5-2GB/s。其他的還有CPU跑驅動,APP等開銷,加一起算1GB/s的話,總共9GB/s左右。
單通道的LPDDR4帶寬大致在12.8GB/s,如果帶寬利用率70%,那差不多正好用滿一個DDR控制器,此時每GB帶寬消耗在DDR PHY的功耗是100毫瓦(16nm),加上總線和DDR控制器的功耗,總共需要1瓦左右。
這里我們可以算出來,除了CPU/GPU/Video/Display之外,帶寬也非常費電,而且增加帶寬會較明顯的增加內存控制器,DDR PHY和內存顆粒數(shù)量,成本上升。相應增加的總線面積和功耗到相對并不大,可以忽略。至于解決由此帶來的復雜度,那是設計SoC的基本功,架構篇提過,這里不再重復。
至此,我們已經(jīng)可以看到如何由顯示分辨率反推對于系統(tǒng)帶寬,功耗和成本的需求。而GPU的最小需求也可以由此推導出來。
在上圖我們可以看到GPU有三個參數(shù),三角形輸出率,像素填充率和理論浮點性能。對用戶界面來說,意義最大的是像素填充率。
填充率有什么意義?對于上文提到過的每層圖層,如果分辨率是1080p,那就需要1920x1080x60=120M/s的像素填充率。如果8個圖層全部由GPU畫出,那么就需要1G/s的填充率,對應上圖的MP2。這還不止。還記得顯示模塊里面的合成,縮放和旋轉功能嗎?這些其實GPU也能做。如果顯示模塊能力不夠,只支持4路輸入,那我們就需要GPU把8層圖層先合并為4層,然后才能交給顯示模塊。每兩層合成相當于重畫一層,于是又額外的需要4層,共1440M/s的像素。如果還涉及縮放和旋轉,那還需要更多。通常來說,顯示模塊不會支持到8層,因為這樣的場景并不多,會造成硬件冗余。而極端場景下,GPU就被用來完成額外工作,增加靈活性,又能防止屏幕因圖層過多造成的卡頓。
當然,由于系統(tǒng)延遲和帶寬的存在,像素利用率不可能達到100%.之前的幾年,我看到的有些系統(tǒng)只能做到70%的利用率,主要原因是平均延遲太長,而并行度不夠大。這時候,簡單的增加GPU核心數(shù)量并不是一個明智選擇,并且如果瓶頸是在系統(tǒng)帶寬不夠,或者系統(tǒng)調度沒做好,即使增加像素輸出率也無濟于事。近兩年的手機芯片基本上可以做到90%的利用率。但是,就算是低端手機,還是會留出更多的填充能力,來應付多圖層下復雜操作的突發(fā)情況。此時,提高利用率的意義就成了減小功耗。
此外,在很多移動GPU上,像素填充率還意味著同等的材質填充率。因為用戶界面基本都是拿圖片或者材質來貼圖然后混合,不需要大量計算三維圖形,三角形輸出和浮點能力用處不大,但是材質填充率必須匹配。
按照上文的功耗和面積,下面我們來看兩個極端的例子:
支持VR的芯片,顯示分辨率4K120fps(雙眼),在虛擬房間內播放4k視頻,顯示模塊支持8路輸入,那么就可能需要4x1080x1920x120x7=6.4G/s的像素填充率,外加一路4k視頻解碼。換成GPU就是至少G72MP8,而考慮3D性能,MP16都是不夠的。僅僅GPU部分的面積就要36平方毫米,功耗6瓦,系統(tǒng)不加風扇沒法跑。
低端的芯片,僅支持1080p,4k30幀播放視頻,4層場景,對于G72MP1就能搞定,面積2平方毫米,功耗0.4瓦。加上視頻和顯示模塊也不會超過5個平方毫米,功耗之前我們也算過,較低。
這里還沒有考慮GPU驅動對CPU的需求。滿負載的話,G72MP12就需要一個A73跑滿2.5Ghz且很難均衡負載(OpenGL ES的限制),而低端芯片只需一個A53就輕松完成。這里面大核小核,4核8核又造成了非常大的面積和功耗區(qū)別。
所以,提升顯示分辨率絕不僅僅是圖像細致一些這么簡單,提升一倍的話,系統(tǒng)成本和功耗基本也會上一大截。簡單來說,顯示分辨率決定了一個芯片的下限。
把GPU在系統(tǒng)中的基本角色介紹完,下面從設計GPU的角度來分析。
想要做好一款GPU,先要分析市場。GPU市場主要有四大塊:桌面和游戲機(3億顆以下),手機和平板(20億顆以下,其中近15億顆被高通和蘋果占住),電視和機頂盒(2億顆以下),汽車面板和自動駕駛(小于1億顆)。其中桌面和游戲機,自動駕駛暫不考慮,其他幾類需求如下:
手機和平板:顯示分辨率1080p到2K,4-8層圖層,3D性能從弱到強,功耗2.5瓦,成本敏感。
電視和機頂盒:顯示分辨率1080p到8K,8層圖層,3D性能弱,功耗2.5瓦,成本敏感,需要畫質增強。
汽車面板:顯示分辨率1080p到2K,4層圖層,3D性能弱,功耗2.5瓦,成本較敏感,不太需要汽車安全設計。
由于Vulkan成為安卓的下一代圖形接口,固定圖形流水線設計必將退出舞臺,通用圖形處理器,也就是所謂的GPGPU,成為必然趨勢。
分辨率的變化可以提煉為可配置多核設計,UI和游戲的不同需求可提煉為大小核的設計。這里,大小核代表著同樣填充率下不同的計算能力。兩者結合,以期達到最高能效比和面積比。說到大小核,自然就衍生出一個問題,有沒有必要像CPU那樣在一個芯片內集成GPU的大小核?答案是否定的。
CPU大小核之所以有用,是因為能效比會有4到5倍的差別,以及單線程性能的硬需求。而一個好的GPU設計,大小核無論跑UI還是圖形,由于存在天然的多線程屬性,同樣的性能所消耗的能量應該是一致的。大小核面積會有差別,但是即使某段時間只用UI,不用計算能力,也得把計算能力放在芯片里,所以小核的意義就不大了,除非就是以UI為主要應用場景的GPU,不追求3D性能。
渲染方式上,目前主要有即時渲染和塊渲染,這個話題已經(jīng)有些年頭了。前者是按照圖元為基準,渲染相關頂點,幾何,像素,然后合成輸出。后者是以像素為基準,選取相關頂點和三角形,計算覆蓋關系,最終合成輸出。初一看,塊渲染似乎更經(jīng)濟,因為它可以計算像素覆蓋關系,避免重復渲染。但是反過來,塊渲染時所需的三角形,頂點,屬性和Varying信息,都是需要從內存讀取的。如果存在大量的三角形,就需要多次重復讀取,很可能省掉的帶寬還不如用即時渲染。所以,決定哪個方式更優(yōu),關鍵在于頂點和像素的比例。就目前手機上的應用看來,像素遠大于三角形或者頂點數(shù)量,這個比例大致在50:1到30:1。這時,用塊渲染就更適合嵌入式設備。
從計算密度看,即時渲染的GPU面積一定小于塊渲染的GPU,但是增加了帶寬,變相增加了手機成本。至于增加的功耗,未必會比塊渲染方式多。所以定性的討論還是不夠的,需要經(jīng)過定量計算才能確定。
有個例子:某即時渲染的GPU A,填充率7200M p/s,曼哈頓3.0的跑分是25,T28nm下運行在450Mhz,功耗2.3瓦,面積13平方毫米,帶寬12.8GB/s。
對應的,塊渲染的GPU B,填充率1300M p/s,曼哈頓3.0跑4.5,T28下運行在650Mhz,功耗0.55瓦,面積4.8平方毫米,帶寬688MB/s。
作為比較,填充率和曼哈頓3.0跑分比例一致,兩個GPU都相差5.5倍。GPU A功耗低了30%,面積只有一半,但是帶寬卻是3.4倍。
這3倍多的帶寬,幾乎占了1.5個DDR4通道,并一下子帶來了2瓦的功耗(28納米),之前的GPU自身功耗優(yōu)勢當然無存,哪怕面積小一半也無濟于事。
反過來,如果按照GPU B的絕對性能,那GPU A其實只需要2.3GB/s的帶寬,雖然很大,卻遠不到一個DDR4通道最大帶寬,同時功耗也很低,達不到2.5瓦的功耗上限,還能省一半面積,何樂而不為呢?
由此可以得出結論,低端手機完全可以用即時渲染的GPU,而中高端上還是得使用塊渲染的GPU。隨著工藝進步,即時渲染的GPU適用范圍會更廣。這應該出乎很多人的意料。
接著我們來看看圖形渲染的流程:
每一步的過程不具體解釋,我們關心的是哪些可以用通用計算單元做,哪些還是要固化為硬件做,這和性能面積功耗強相關。我們把上圖流水對應到Mali GPU上,如下圖:
把著色器更細化一些,如下圖:
其中,頂點和像素的處理,計算量相對大,算法相對變化大,可以用通用的著色器,也就是上圖中的執(zhí)行單元Execution Engine。
曲面細分模塊Tessellation,由于并不是必須的,在Mali的Norr中,并沒有對應的硬件模塊,可以用軟件使用著色器通用處理單元來做。
深度和模板的測試以及合成,這些都屬于像素的后處理,可以用專用硬件直接做,因為操作簡單,計算量也和像素線性相關。
材質需要一個額外的單元來做,因為材質有許多專用的操作,而且每個像素點的輸出都需要材質單元參與,輸出線性相關。此外材質訪存帶寬也很大,所以擁有自己的訪存單元,不占用著色器的存取單元。
在頂點和像素計算中用來傳遞數(shù)據(jù)的屬性和Varying,需要根據(jù)頂點的屬性數(shù)據(jù),讀取數(shù)據(jù),插值計算像素的值,提供給像素著色器。計算量和頂點或者像素線性相關,適合固化為硬件單元。
根據(jù)圖元的頂點位置信息,計算轉換后的坐標與法向量,如果在邊界之外或者在背面,那就不用輸出,直接扔掉,節(jié)省帶寬。這步就是背面剔除Culling和裁剪Clipping,可以用專用模塊配合通用計算單元辦到。最后剩下的有效部分,可以用來生成三角形列表,并增加到基于塊狀像素的隊列中去,以便于光柵化。
接下去就是光柵化。這一步中涉及到深度和顏色等的計算,用通用著色器來做。具體做的時候,還需要一個硬件的三角形設置模塊,對于某一塊像素區(qū)域所涉及的三角形,讀取上一步中形成的三角形列表,計算三角形每條邊所對應方程的參數(shù),以及平面和重心。由于和三角形輸出率相關,算法固定,所以也適合固化。
此外,還需要一些額外的單元,來處理系統(tǒng)相關的事務,比如內存子系統(tǒng),內部總線,以及負責管理任務和線程的模塊。其中,任務管理模塊又可以在不同層面細分,是一個GPU設計的精華所在。
以Mali為例,在最上層,以圖元,頂點和像素為基準,把所有的任務都劃分成三類Job,交給不同的處理單元,也就是Tiler,頂點/像素著色器。下一層,按照像素塊為單元,又可以把整個屏幕分成很多像素點,也就是線程。在同一瞬間,每個著色器上都可以跑多個線程,這些線程的組合又被稱作一個Warp。而提高計算密度的秘密,就在于在一個核內塞入更多的線程數(shù)。
再下層,具體到每一個著色器里面的執(zhí)行引擎,每個時鐘的輸入是一個Clause。Clause就是某段沒有分支的程序,當所有的輸入數(shù)據(jù)都已經(jīng)從內存讀取并存放于寄存器后,這段程序會被無間斷執(zhí)行,直到結果輸出。當輸入數(shù)據(jù)還未取到,那么就切換到另一個準備就緒Clause。
所有這些任務,Warp和Clause的管理,需要有專門的硬件來做,以保持整個流水線利用率的最大化。
總之,只要是一直出現(xiàn)在圖形流水上的工序,操作固定,計算量穩(wěn)定,就可以用專用硬件單元來做,并不會浪費,相反還更省功耗面積。而計算變化較大的部分,就可以交給通用計算單元。
確定了通用和專用單元,接下來需要優(yōu)化渲染流程,并調整硬件。先看頂點計算,如上圖。在生成三角形列表的時候,有些三角形代表著背面,那只要算出法向量,那么就可以直接確定是否拋棄,省掉輸出。
更進一步,如果根據(jù)頂點的遠近關系,做某些簡單計算,直接可以得出某些三角形被完全覆蓋,那么也可以直接拋棄。在之后的像素渲染以及合成中,可以完全省掉處理。這被稱作Early-Z。不過這還存在一個限制,在多個繪制函數(shù)Draw call中,如果命令被先后發(fā)送到GPU,不同函數(shù)間不容易做early-Z優(yōu)化,因為如果要保留上一個同一區(qū)域繪制函數(shù)的結果一起做優(yōu)化,可能需要花更大的代價。但是其塊渲染的任務卻可以等到所有繪制函數(shù)都完成后再開始。在這種情況下,從后往前畫的繪制函數(shù)區(qū),就不容易優(yōu)化,而從前往后畫的直接就能完成覆蓋。這被稱為forward killing,需要圖形引擎預先計算出物體的深度信息,在生成腳本階段就做好預判,提高渲染效率。
以上優(yōu)化并不能解決所有的三角形覆蓋問題,還可以再進一步。在像素渲染階段,得到像素點對應的三角形以及深度信息后,一樣可以拋棄被遮住的三角形,只計算被看到的那個三角形的顏色和光照,紋理,同樣也免了后續(xù)的混合。這一步中的操作被稱為TBDR,延遲塊渲染。這是可以甚至是跨越Draw call的。如果頂點數(shù)足夠少,被覆蓋的三角形足夠多,Early-Z和TBDR可以極大的減少像素渲染計算量。
在合成階段,我們還可以做一個優(yōu)化,就是在輸出最終的塊內容時,對整個區(qū)域計算一個CRC值。如果是16x16的塊,其CRC大小通常只有1%,1080p的屏幕是100K字節(jié)左右。在下一次渲染時,我們再從DDR甚至內部緩存讀出這個CRC值,來判斷是不是內容有變化。如果沒有,那直接放棄輸出,節(jié)省帶寬。不過,之前所做的渲染計算還是沒法節(jié)省。
如果知道屏幕有一塊區(qū)域在一段時間內不會有內容變化,那我們可以預先就告訴GPU,讓它把這塊區(qū)域從像素渲染里直接取消,從而免掉上一段中的計算。不過這需要和顯示模塊一起配合完成。
類似的渲染流水層面的優(yōu)化還有很多,幾乎每一步都能找出來。
在綜合了所有的優(yōu)化之后,我們終于做出了一個初始GPU,并得出其面積分布:
其中EE是計算引擎,面積47%,TEX是材質單元,面積20%。顯然,我們優(yōu)化的核心應該放在這兩塊。這其實又引出了圖形處理器的一個奮斗目標:更高的計算密度。前面提到過,計算密度的定義,在以UI為主的低圖形處理器上以像素輸出率來衡量,在以游戲為主的高端上以浮點密度來衡量。
要提升UI像素輸出密度,在合成單元能力固定的情況下,計算單元不重要,材質單元必須與輸出能力匹配,一般是像素材質比1:2或者1:1。1:2的比例能做到兩個材質點混合為一個后,配合一個像素輸出,這在有些UI場景下很有用,提升了一倍的像素輸出率。但是反過來,如果用不到,那多出來的材質單元面積就是浪費。具體是什么比例,只能見仁見智。
要提升浮點密度,方法也不難,就是堆運算單元,然后匹配上相應的圖形處理器固化硬件,指令,緩存和帶寬。
在具體設計運算單元的時候,還是有些考量的。之前,ARM一直使用SIMD+VLIW的結構。也就是說,以一個像素為一個線程,以其RGBA四個維度為矢量,形成一個32位數(shù)據(jù)的SIMD指令。然后,盡量找出可以并行的6個線程,放到一起并行。這6個線程分別是向量乘,向量加,標量乘,標量加,指令跳轉還有查表。其實就是對應了運算單元的設計,如下圖:
由于Mali是基于塊渲染的,一個塊內有16x16個像素,也就是256個線程,這些線程可以處于不同的程序段,有些在計算深度,有些在計算顏色。如果線程管理器能夠一直找到這樣的6個像素,對應不同的運算單元,把這些單元一直排滿,那自然可以得到最高的單元利用率??上屡c愿違,這樣的高利用率場景并不好找,很多的時候是只有矢量單元被用上了,其余的都空著。
于是,Mali畫風一轉,把上圖的標量乘和加去掉,且放棄VLIW,從而把指令跳轉單元抽出來。最后形成了一個新的處理單元,如下圖:
這里,一個128位寬的乘加和同樣寬度的加法單元承擔了之前標量和向量乘加,而查表運算也和加法單元混合在一起。和之前完全不同的是,這里的輸入始終是128位寬的單個指令,而不是VLIW的6條指令,從而提高計算單元利用率。每時鐘周期進來的數(shù)據(jù),只能到FMA和ADD/TBL單元中的一個,沒法同時進去,某種程度上減少了面積的有效利用率。
為了配合這一設計,Mali還做出了一個新的調整,如上圖。由之前的按照像素點的RGBA四通道的矢量運算方式,改成四個像素各抽取一個顏色通道,塞到上面的FMA,同時運行四線程。由于大部分情況下,一個塊上的256個像素的相同通道總是做一樣的計算,保證了這個設計的高利用率。如果相鄰四個點每個通道的運算都不一樣,那效率自然會降低。
有些GPU還有另外一種運算單元形式:
在這里,乘加被放在小單元,比例更高;大單元除了乘加,還有查表,比例低;跳轉單元單獨放。這樣可以使得計算單元比例更合理,面積利用率更高。
確定了計算單元的能力之后,有沒有一個統(tǒng)一的方法,來精細的調整每個配套模塊的比例呢?答案是有,先確定跑分標準,然后細化成子測試,最后在模型上統(tǒng)計出來:
目前移動上比較流行的標準是GFXBench,主流的有三個版本,2.x,3.x和4.x。每一個版本都有側重,比如2.0側重三角形生成,3.0側重計算單元與材質,4.0側重計算。Antutu也是一個標準,目前側重陰影和三角形生成率。有時候,芯片和手機公司還會統(tǒng)計出主流的游戲,在芯片或者仿真平臺甚至模型上跑,以期得到下一代GPU對計算能力的需求。
定下了標準跑分,接下去就是細化成更小的目標,是三角形,頂點,像素,材質,ZS,Varying,混合還是帶寬要求。然后,在模型上,把這些細化需求翻譯成PPA,給到每一個小模塊,看看是不是還有壓縮的空間。這是最底層的優(yōu)化。
經(jīng)歷過上面的打磨之后,我們得到了一個更好的GPU。那是不是就沒什么好改進了呢?還不夠。從應用角度還是不停地有需求進來:
DRM,數(shù)據(jù)壓縮, 系統(tǒng)硬件一致性,統(tǒng)一內存地址,AR/VR/AI,CPU驅動。
首先,是版權保護,播放有版權的內容時,解密和解碼都是在保護世界完成的,而UI的操作可能需要GPU的參與。這塊在安全篇中有論述,此處不再展開。
第二,所有的媒體和材質數(shù)據(jù)都可以進行壓縮,以節(jié)省系統(tǒng)帶寬和成本。上文討論過,此處不再展開。
第三,系統(tǒng)雙向硬件一致性問題。要實現(xiàn)GPU和CPU以及加速器之間數(shù)據(jù)互訪而不用拷貝和刷新緩存,就需要支持雙向一致性的總線,比如CCI550,這在基礎篇已經(jīng)討論。最新的OpenCL2.0和Vulkan都支持這一新的特性。如下圖,在數(shù)據(jù)交互非常頻繁地情況下,可以節(jié)省30%甚至90%左右的運行時間。
不幸的是,由于OpenGL ES天生就不支持這個特性,所以對于目前絕大多數(shù)的圖形應用,哪怕接了CCI550,GPU也是不會發(fā)出任何帶有監(jiān)聽操作的傳輸?shù)?。這種情況到了Vulkan以后會有改善。
第四,和CPU的統(tǒng)一物理地址。在桌面上,CPU和GPU的訪問空間是完全獨立的,而移動處理器從開始就統(tǒng)一了物理地址。當然,他們的頁表還是分開的。在基礎篇我們就講過,統(tǒng)一的好處就是省帶寬和成本,恰好塊渲染的GPU的特點就是帶寬相對較小。剩下的只要把總線和內存控制器的調度做好,保持內存帶寬的利用率在一個相對較高的水平就行。
硬件一致性和統(tǒng)一地址有一個應用就是異構計算,CPU/GPU/DSP/加速器均可使用相同物理地址,并且硬件自動做好一致性維護。具體的計算可以是圖像,也可以是語音。不過很可惜,在高端手機上,如果把所有的處理單元都跑起來,那功耗肯定是遠高于2.5瓦的,甚至可以到10瓦。而且受限于GPU的軟件,雙向硬件一致性也沒有得到廣泛應用,目前最多是做一些ISP后處理。
第五,AI。在AI篇我們提到。如果AI跑在GPU,那肯定需要支持INT8甚至更小的乘加操作,這對于GPU沒有任何問題。不過,AI更需要的參數(shù)壓縮,Mali的GPU并沒有原生支持。這樣一來,本來的四核MP4差不多是用2個128位AXI接口,只能提供32GB/s左右的讀帶寬。不壓縮的話,也就能支持64GB INT8的計算量,遠小于GPU四核一般在1Tops的INT8計算量。
第六,VR。VR對于GPU來說有相當大的關系。首先,由于左右眼需要分別渲染,并且分辨率需要4K以上,這就對GPU性能提出了1080p時8倍的需求,對系統(tǒng)帶寬也是一種考驗。細分下來,有這樣一些需求:
左右眼獨立渲染:如下圖,VR場景中的三角形或者頂點部分,左右眼是共享的,但是旋轉和之后的像素處理,必須是分開的。由于頂點渲染只占整個工作量的10%,所以能節(jié)省的計算量相當有限,只是可以減少些頂點材質的讀取。
畸變矯正:這個可以在頂點渲染最后加一步矩陣乘法,輕易做到。不過,由于這個操作夾雜在頂點和像素渲染之間,所以還是需要額外的API來提醒硬件。
異步時間扭曲ATW:其原理是當發(fā)現(xiàn)計算下一幀需要的時間超出預期,索性就不去計算了,而是把當前幀按照頭部移動方向做一個插值,造一個假的圖像。這樣,就需要一個API,以估算下一幀生成時間,還需要一個額外的定時器,根據(jù)顯示模塊的Vsync信號計算剩余可用時間。如果時間不夠,會直接拿取插值后的圖像,而這個圖像計算也在GPU,計算量小且優(yōu)先級很高,保證趕上Vsync信號。
多視圖渲染Multi-View:也就是對于視圖的非焦點區(qū)域,使用低解析度,焦點區(qū)域,高解析度。要做到這點,使用高解析度,總的計算量可以降低一半左右。實際運用中,由于焦點區(qū)域的確定需要眼球跟蹤,比較復雜,所以會采用中心區(qū)域來替代。
Front buffer:原來的桌面GPU設計中,顯示緩沖分兩塊,front buffer和back buffer交替輸出,當中用Vsync做同步,按幀輸出?,F(xiàn)在只使用一塊front buffer,以hsync為同步標志,按行輸出,這樣,整個幀的渲染時間并不變,但是粒度變細。對于GPU來說,這需要加入按行渲染的次序關系。這和上一個Multi-View原理并不相同,前一個雖然分成了多視圖區(qū)域,但是并不規(guī)定渲染次序,塊與塊之間還是亂序的,只不過最后輸出的時候都是渲染完成好的。而Front buffer相當于在行與行間插入了一個同步指令,如果純粹交由硬件來調度,很可能會降低性能。也可以GPU的frame buffer保持原樣,用顯示模塊來做這個事情,更容易實現(xiàn)。
第七,AR。在AI篇中,我們提到,GPU其實也在做渲染,沒有什么特殊的需求,除非把識別的工作交給GPU來做。
還有很重要的一點,就是GPU驅動對CPU造成的負載。在OpenGL ES上,由于API本身的限制,很多驅動任務必須是一個線程內完成的。這就要求必須在一個CPU核上跑。GPU核越多,單個CPU核的負載越高。在Mali G71之前,差不多10-12個900Mhz的GPU核就需要一個跑在2.5Ghz的A73來負責跑驅動,其他的大核小核再多都幫不上忙。但事實上,由于大核的能效比小核差了4到5倍,所以一定是小核來跑驅動更省電。反過來,如果使用了更多的GPU核,那最后的瓶頸會變成單個CPU的性能,而不是GPU。解決的方法有幾個,一是使用Vulkan。Vulkan在設計階段就考慮到了這個問題,天然支持CPU多線程的負載均衡,能很好的解決這個問題。我曾經(jīng)看到過一款桌面GPU,在16核A53的服務器上只發(fā)揮出x86服務器上的30%性能,而從Open GL換成Vulkan后,才把瓶頸轉移到GPU自身。
不過,雖然Vulkan已經(jīng)是谷歌欽定的下一代圖形接口,基于Vulkan的圖形應用流行可能還需要3-5年時間。另外一個可行方法就是優(yōu)化GPU驅動軟件本身,并把一部分的軟件工作交給硬件來完成,比如內存管理模塊的硬件化,還可以使用一個MCU和內嵌緩存來翻譯和處理命令序列,替代CPU的工作。這個MCU可以只跑在幾百兆,功耗十幾毫瓦,遠低于小核的100多毫瓦,更低于大核的幾百毫瓦。
最后,做出來的GPU在PPA上還得和高通的Adreno對比(蘋果的GPU在計算密度上也不如高通)。目前世界上所有的塊渲染的GPU中,高通是能效比和性能密度最好的,比最新的Mali GPU高30%以上。其中,有幾個地方是Mali難以彌補的,比如系統(tǒng)緩存,針對少數(shù)幾個配置的前端優(yōu)化(Mali需要兼顧1-32核),以及確定的后端制程和優(yōu)化。這里的每一項都可以提供5%-10%的優(yōu)化空間,積累起來也是不小的優(yōu)勢。
總之,GPU的設計是一個不斷細化的過程,選好大方向,把標準跑分明確,再注意新的趨勢和需求,把模型和驗證流程跑熟,剩下的就是不斷打磨了。
評論
查看更多