GPU是協(xié)處理器,CPU才是主人,GPU并不是一個獨立運(yùn)行的計算平臺,而需要與CPU協(xié)同工作,可以看成是CPU的協(xié)處理器,因此GPU并行計算,是指CPU+GPU的異構(gòu)計算架構(gòu)。在異構(gòu)計算架構(gòu)中,GPU與CPU一般通過PCI-E總線連接在一起來協(xié)同工作,CPU所在的位置稱為主機(jī)端(host),而GPU所在的位置稱為設(shè)備端(device)。
早期的CPU都是針對整數(shù)運(yùn)算的,也有的CPU有少量的浮點運(yùn)算處理,處理低像素還湊合。隨著像素數(shù)越來越高,需要大量的浮點運(yùn)算處理器,GPU就出現(xiàn)了。所以標(biāo)準(zhǔn)意義的GPU其性能參數(shù)為FLOPS,F(xiàn)loating-pointOperations Per Second。最常用來測量FLOPS的基準(zhǔn)程式(benchmark)之一,就是Linpack。一個GFLOPS(gigaFLOPS)等于每秒十億(=10^9)次的浮點運(yùn)算,一個TFLOPS(teraFLOPS)等于每秒一萬億(=10^12)次的浮點運(yùn)算。而CPU的性能單位一般是DMIPS,DhrystoneMillion Instructions executed Per Second,每秒百萬次整數(shù)運(yùn)算指令執(zhí)行數(shù)。AI的性能單位則是TOPS,TeraOperations Per Second,1TOPS代表處理器每秒鐘可進(jìn)行一萬億次(10^12)操作,不區(qū)分整數(shù)還是浮點,也不是指令而是operation。通常只有CPU才能做任務(wù)調(diào)度,是host,AI處理器和GPU都是需要CPU配合,是協(xié)處理器device。
典型GPU架構(gòu)圖
圖片來源:互聯(lián)網(wǎng)
典型GPU架構(gòu),從2010年的Fermi開始NVIDIA使用類似的原理架構(gòu),使用一個Giga Thread Engine來管理所有正在進(jìn)行的工作,GPU被劃分成多個GPCs (Graphics Processing Cluster),每個GPC擁有多個SM(SMX、SMM,Streaming Multiprocessor流多處理器)和一個光柵化引擎(Raster Engine),它們其中有很多的連接,最顯著的是Crossbar,它可以連接GPCs和其它功能性模塊(例如ROP或其他子系統(tǒng))。 GPU制造廠商經(jīng)常宣傳說他們擁有“240”個“core”,但他們所有的core其實是指 “ALUs/FPUs”,與CPU中提到的core還是有區(qū)別的,一般NVIDIA或ATI稱core為SP (streamingprocessor)或者SC (shadercore)或者TP (Threadcore),都是一個東西,一個SM中包含多個SP,但這些SP并不是完全獨立的執(zhí)行單元,每個SP雖然有單獨的register file,獨立的指令指針,但SP并沒有完整的獨立front-end比如取指和指令派發(fā),因此SP更像是CPU中執(zhí)行部分。
Fermi的SM處理器內(nèi)部框架
圖片來源:互聯(lián)網(wǎng)
Fermi是英偉達(dá)2010年發(fā)布的GPU架構(gòu),從此英偉達(dá)的GPU架構(gòu)開始都以科學(xué)家的名字做代號,其前端結(jié)構(gòu)差別不大。
Warp Scheduler管理一組32個線程作為Warp(線程束,可以想象是紡紗機(jī)器把多條線紡織在一起)并將要執(zhí)行的指令移交給Dispatch(派遣,發(fā)送)Units。英偉達(dá)升級GPU一般都是升級Core內(nèi)核,別的都與Fermi高度一致。Fermi有32768個32-bit寄存器,F(xiàn)ermi有512個SM,也就是每個SM(每個線程束)分到64個寄存器,每個線程兩個。
Fermi的Core包含一個整數(shù)運(yùn)算單元,一個浮點運(yùn)算單元。每個SM還有SFU (SpecialFunction Units,特殊數(shù)學(xué)運(yùn)算單元),它們用于進(jìn)行三角函數(shù)和指對數(shù)等特殊運(yùn)算。每一個核都相當(dāng)于GPU中的ALU,一個CPU內(nèi)核最多有8個ALU,GPU則可以輕易達(dá)到數(shù)千個。但GPU通常只能應(yīng)對一種算法,CPU中的可以勝任非常多算法,ALU像一個教授,從加減乘除到微積分無所不能,GPU像幾千個小學(xué)生的集合,通常只做乘法。FP后來在GPGPU時代變?yōu)镕MA或FFMA (Fusedmultiply-and-accumulate),基本上所有所謂人工智能算法拆解到最底層都是乘積累加計算,也特指乘積累加指令集。
英偉達(dá)用于AI的采用Ampere架構(gòu)的A100GPU物理架構(gòu)
圖片來源:互聯(lián)網(wǎng)
2019年推出的Ampere架構(gòu)與Fermi架構(gòu)整體一致。
英偉達(dá)安培架構(gòu)中的SM內(nèi)部框架
圖片來源:互聯(lián)網(wǎng)
英偉達(dá)安培架構(gòu)中的SM內(nèi)部框架中,將ALU分得更細(xì),INT32即整數(shù)32位,F(xiàn)P32為浮點32位,F(xiàn)P64為浮點64位。專門針對矩陣運(yùn)算則有Tensor核。
實際CPU與GPU最大的區(qū)別是帶寬,CPU像法拉利,跑的很快,但要是拉貨,就不如重卡。GPU像重卡,跑的不快,但一次拉貨多。有些貨可以全部打包裝車運(yùn)輸,如這些貨都來自一個地方,大小相同,需要運(yùn)輸?shù)揭粋€地方,這就是計算密集型任務(wù)。有些貨不行,比如這些貨要去不同地方,體積大小不一,不能多個打包,只能多次運(yùn)輸,這就是控制密集型任務(wù)。CPU在緩存、分支預(yù)測、亂序執(zhí)行方面花了很多精力,用大量寄存器實現(xiàn)這些功能,保證了高速度,頻率一般都遠(yuǎn)高于GPU,每次速度很快,但大量寄存器占用大量空間,考慮到成本以及半導(dǎo)體的基本定律(單顆die面積不超過800平方毫米,否則良率會急速下降),CPU的核心數(shù)非常有限,每次能帶的貨很少。GPU相反,不考慮分支預(yù)測與亂序執(zhí)行,用最快的寄存器代替緩存,結(jié)構(gòu)簡單,晶體管數(shù)量少,可以輕易做到幾千核心,每次能帶的貨很多,但速度不快。
深度學(xué)習(xí)或者說人工智能都是計算密集型任務(wù),數(shù)據(jù)一般占用大塊連續(xù)的內(nèi)存空間,GPU可以提供最佳的內(nèi)存帶寬,并且線程并行帶來的延遲幾乎不會造成影響。
除此之外,GPU的并行計算架構(gòu),通常來說與執(zhí)行單元(指的是CPU的核心或者GPU的流處理器)的距離越近,則訪問速度越快,其中寄存器和L1緩存與CPU距離最近。GPU的優(yōu)勢在于:GPU為每個處理單元(流處理器或者SM)均配備了一些寄存器,而GPU成百上千個處理單元就使得寄存器總的數(shù)量非常多(為CPU的30倍,高達(dá)14MB)且速度達(dá)到80TB/s。
相比之下,CPU的寄存器大小通常為64-128KB,運(yùn)行速度為10-20TB/s。當(dāng)然以上的比較在數(shù)值上會不太精確,并且CPU寄存器和GPU寄存器并不相同。兩者的大小和速度的差異是主要關(guān)鍵點。最后一點GPU的優(yōu)勢在于:大量且快速的寄存器和L1緩存的易于編程性,使得GPU非常適合用于深度學(xué)習(xí)。
英偉達(dá)Volta V100 GPU的存儲架構(gòu)圖
圖片來源:互聯(lián)網(wǎng)
上圖可以看出每個處理block都有高達(dá)64KiB的寄存器,寄存器是速度最快的,只要一個周期,緩存或者說SRAM還是要通過總線訪問的,速度遠(yuǎn)遠(yuǎn)不及寄存器。
早期GPU
早期的GPU和目前的GPGPU差別還是不小的,早期的GPU主要是圖形生成與渲染,第一步就是畫三角形,三角形光柵器一次要處理一堆東西:跟蹤三角形的形狀,插值出坐標(biāo)u和v (對于透視矯正映射,是u/z,v/z和1/z),執(zhí)行Z緩沖測試(對于透視矯正映射,可以用1/z緩沖替代),然后處理實際的紋理(還有著色)。這些都是浮點運(yùn)算,早期的CPU都是針對整數(shù)運(yùn)算的,也有的CPU有少量的浮點運(yùn)算處理,處理低像素還湊合,隨著像素數(shù)越來越高,GPU就出現(xiàn)了。
GPU的圖形處理邏輯管線
圖片來源:互聯(lián)網(wǎng)
通常把圖形邏輯管線叫渲染管線,渲染流水線是在顯存中開啟的。CPU將網(wǎng)格、材質(zhì)、貼圖、著色器等注入顯存后,GPU開始渲染流水線。渲染流水線分為幾何階段和光柵化階段(也被稱為像素階段),并最終將運(yùn)算結(jié)果送到顯示器的緩沖區(qū)中。幾何階段分為頂點著色器->曲面細(xì)分著色器(DirectX11和OpenGL4.x以上可編程)->幾何著色器->裁剪->屏幕映射五個步驟。
光柵(ROP)化階段分為三角形設(shè)置->三角形遍歷->片元著色器->逐片元操作四個步驟。渲染流水線重點強(qiáng)調(diào)的和CPU的指令流水線并不同。它實際不是流水線,不同階段運(yùn)行的是同一次Draw Call(Draw Call指令是由CPU發(fā)出的),但一次Draw Call中先提交的數(shù)據(jù)可以不等待它之后的數(shù)據(jù)就進(jìn)入下一個流水線階段。
頂點渲染單元(也叫頂點著色或頂點著色引擎),主要負(fù)責(zé)描繪圖形,也就是建立模型。一個就是像素渲染管線(也叫像素渲染管道),主要負(fù)責(zé)把頂點繪出的圖形填上顏色。然后再加上紋理貼圖單元貼上紋理,一個精美的圖形就出來了。在微軟的DIRECTX10出來后,頂點渲染和像素渲染將淡出我們的視線,因為它將采用統(tǒng)一架構(gòu)。也就是一個核心中是由一組專門的通道既負(fù)責(zé)頂點渲染又負(fù)責(zé)像素渲染的。不過道理還是一樣的。
這就引出了GPU的兩個關(guān)鍵參數(shù)像素填充率和紋理填充率。當(dāng)然是越高越好,這樣顯示圖像幀率高且更細(xì)膩,分辨率更高。 像素填充率=顯卡的顯示核心頻率乘以像素渲染管線(即光柵單元)數(shù)量。單位是GB Pixel/s
紋理填充率=核心頻率乘以像素渲染管線數(shù)量再乘以紋理貼圖單元數(shù)量。單位是GB texture/s
GPU的CPU開銷即Draw Call驅(qū)動開銷
長久以來人們都覺得ARM的GPU即MALI效果不如高通的Adreno,實際單論像素填充率和紋理填充率,MALI更強(qiáng),但ARM的缺點就是Draw Call驅(qū)動開銷太高。調(diào)用一次圖像編程接口(圖形API),以命令GPU進(jìn)行渲染的過程就稱為一次Draw Call,圖像編程接口(圖形API),是對GPU硬件的抽象,其地位類似C語言,屬于GPU編程的中低層。幾乎所有GPU都既可以和OpenGL合作也可以和DirectX合作。OpenGL是純粹的圖形API;DirectX是多種API的集合體,其中DirectX包含圖形API——Direct3D和Direct2D。DirectX支持Windows和Xbox;OpenGL支持Windows、MacOS、Linux等更多平臺,在Android、iOS上允許使用OpenGL的簡化版本OpenGL ES。OpenGL相對來說易上手,門檻低;DirectX難上手,門檻高。OpenGL渲染效率相對低,特性少;DirectX相對效率高,特性多。如DirectX12提供了底層API,允許用戶一定程度上繞過顯卡驅(qū)動之間操縱底層硬件。
對于圖像生成的應(yīng)用,第一步,CPU把一個網(wǎng)格的頂點數(shù)據(jù)從硬盤中加載到內(nèi)存中(存在這一步的原因是大規(guī)模3D渲染中內(nèi)存可能不足)。
第二步,CPU對這個網(wǎng)格設(shè)置渲染狀態(tài)(每個網(wǎng)格不等于每個模型/圖片,因為存在批處理)。所謂渲染狀態(tài)包括紋理貼圖、材質(zhì)屬性和被編譯為二進(jìn)制文件的著色器。隨著渲染狀態(tài)一起被傳遞到GPU的還有光照和攝像機(jī)相關(guān)的信息。圖形API可以更深層次的定義渲染狀態(tài)需要的數(shù)據(jù)。
第三步,CPU將網(wǎng)格頂點數(shù)據(jù)與渲染狀態(tài)打包,將數(shù)據(jù)包按照指定格式交給DMA,由DMA將數(shù)據(jù)包傳入顯卡。DMA (Direct Memory Access,內(nèi)存直接訪問)。 指令到達(dá)GPU驅(qū)動程序后,驅(qū)動會首先檢查指令的合法性,如果指令非法,驅(qū)動會通過DMA向CPU發(fā)送錯誤信息。如果指令合法,驅(qū)動通過DMA確認(rèn)Draw Call接收,然后將指令放入GPU緩沖。 一段時間后當(dāng)顯卡中存在空閑流水線,或者CPU顯式發(fā)送flush命令后,驅(qū)動程序把緩沖區(qū)中的一份指令發(fā)送給GPU,GPU通過主機(jī)接口接受命令,并開始處理命令。
GPU將所有頂點存入頂點緩沖區(qū)(Vertex Buffer),GPU中的“圖元分配器(Primitive Distributer)”開始通過頂點生成三角形,并將他們分成批次(batch),發(fā)送給一個或多個GPCs,如果顯卡不存在GPCs,則直接分發(fā)給SMs。SM獲得數(shù)據(jù)后,束管理器安排多邊形引擎將三角形數(shù)據(jù)提取出來存入SM的L1緩存,隨后開始頂點著色器階段。
GPU會依次處理緩存中的每一個網(wǎng)格,網(wǎng)格的處理順序與CPU的提交順序有關(guān)。正因如此,CPU總是最后提交透明物體。等一幀中的所有Draw Call處理完畢后,顯示器才會將圖像打印在屏幕上。
Draw Call的性能瓶頸是CPU而非GPU。CPU每進(jìn)行一次Draw Call,都要調(diào)用一次DMA將數(shù)據(jù)輸入顯存。在每次調(diào)用時,對顯存的映射尋址、DMA控制塊的注入、等待DMA響應(yīng)等系統(tǒng)消耗都會浪費時間周期,多次進(jìn)行Draw Call就會有多次消耗。同時,DMA擅長一次傳輸大量數(shù)據(jù),而不擅長多次傳輸少量數(shù)據(jù)。這使得降低Draw Call對于優(yōu)化顯示性能很有必要。
ARM MALI系列GPU
ARM的GPU設(shè)計項目最早從上個世紀(jì)90年代末期開始,由挪威科技大學(xué)開始開展,隨后在2001年,這個項目的Mali小組成員從研究中脫離出來,成立了一個名為Falanx Microsystems的公司。Falanx公司的人員剛開始瞄準(zhǔn)的是PC圖形市場,但當(dāng)時已是后3DFX時代,群雄并起,包括S3、Rendition、Revolution以及Imagination等公司最后都失敗了,最終Falanx無法籌集到足夠的資金,被迫放棄了PC圖形市場。
在那個“緊迫期”,由于資金有限和PC圖形硬件極高的研發(fā)成本,F(xiàn)alanx最終決定轉(zhuǎn)向移動SoC GPU設(shè)計。因為移動GPU設(shè)計更簡單且較容易成功。Falanx的產(chǎn)品Mali GPU也迎來了他們的第一個客戶—美國Zoran公司,使用了Mali-55作為他們Approach 5C SoC芯片的GPU,這顆芯片還被用在LG's Viewty這樣廣受歡迎的手機(jī)產(chǎn)品中。即使如此,F(xiàn)alanx還不滿足,最終在2006年迎來了他們的“大魚”。鑒于SoC市場持續(xù)增長以及將帶來的移動計算大潮,ARM公司終于決定買下Falanx,組建自己的GPU事業(yè)部,并聯(lián)合ARM的CPU一起推動整個產(chǎn)業(yè)的增長。ARM作為一個處于上升期、資金充裕的公司,完全有能力給Falanx充足的資金和研發(fā)資源來實現(xiàn)夢想。
ARM第一代微架構(gòu)Utgard(北歐神話人物:烏特加德)。這一代架構(gòu)出來的比較早,主要是圖形加速IP??梢宰匪莸?007年的Mali-200。不過最讓人驚訝的是Mali-4xx系列,現(xiàn)在很多電視芯片都還在用這個IP。比如小米的智能電視,還有很多是Mali-4xx系列的。第二代微架構(gòu)Midgard(北歐神話人物:米德加德)。Midgard這一代GPU開始屬于同一著色器的架構(gòu),也就是上面說的vertex shader和fragment shader已經(jīng)統(tǒng)一在一起了,相當(dāng)于同一個shader計算單元可以處理多種著色器。當(dāng)然也開始支持通用計算。特別是對OpenCL的支持。第三代微架構(gòu)Bifrost(北歐神話中連接天宮和大地的:彩虹橋)。第四代微架構(gòu)Valhall(北歐神話中的瓦爾哈拉神殿,是戰(zhàn)死的勇士死后進(jìn)入奧丁神的神殿)是2019年第二季度推出來的。該系列是基于超標(biāo)量實現(xiàn)的。
常見高通與ARM MALI GPU參數(shù)對比
資料來源:互聯(lián)網(wǎng)
ARM MALI-G710
目前ARM最新的GPU為G710,ARM的架構(gòu)變動比較頻繁。G710可能是ARM最成功的GPU架構(gòu),采用4納米制造工藝。 與英偉達(dá)桌面級GPU比,ARM的架構(gòu)差異比較大,ARM采用大核設(shè)計,一般寫為MALI G710 MPX或MCX,X代表核心數(shù),MALI的核心就是渲染核即Shader Core,可以近似于英偉達(dá)的SM流多處理器。渲染核里有執(zhí)行引擎,可以算是CPU領(lǐng)域的ALU。
MALIG710渲染核
圖片來源:互聯(lián)網(wǎng)
早期ARM是SIMD設(shè)計,近期變?yōu)镚PU常用的SIMT。G710的執(zhí)行引擎比G77翻倍,有兩個執(zhí)行引擎,每個執(zhí)行引擎包含兩個簇,執(zhí)行16位寬的線程,等于是64個ALU,G710支持7-16核設(shè)計,也就是最高1024個ALU。
MALIG710執(zhí)行引擎
圖片來源:互聯(lián)網(wǎng)
G710的執(zhí)行核,前端沒有透露具體信息,應(yīng)該與G77一樣,是64個warp或1024個線程。每個處理單元都有三個ALU:FMA(混合的乘積累加計算)和CVT(Convert)單元是16-wide,而SFU(特殊功能單元)是4-wide。每個FMA每周期可以做16次運(yùn)算,運(yùn)算數(shù)據(jù)精度為FP32,換成FP16就是32次,8位整數(shù)INT8就是64次,像英偉達(dá)的桌面級GPU,F(xiàn)P16和FP32是分開計算的,也就是說可以同時計算,但移動級的MALI不需要這樣設(shè)計。Convert單元處理基本整數(shù)操作和自然類型轉(zhuǎn)換操作,并充當(dāng)分支端口。
MALI-G77的渲染核
圖片來源:互聯(lián)網(wǎng)
圖片來源:互聯(lián)網(wǎng)
ARM MALI GPUCSF
G710最大的變化,添加了CSF。G710首次將Mali的Job Manager換成了所謂的Command Stream Frontend。這個CSF負(fù)責(zé)處理調(diào)度和draw call,CSF這個模塊由CPU、HW和固件構(gòu)成。ARM表示,HW本身是全新設(shè)計的;而固件層的引入,能夠針對一些比較復(fù)雜的圖形負(fù)載提供更具彈性的性能,而且能夠減少驅(qū)動開銷、提升效率;對諸如Vulkan等API提供更簡捷的支持等。固件處理來自host的請求和通知,負(fù)責(zé)硬件資源調(diào)度,減少諸如protected mode進(jìn)出的開銷,還能通過指令模擬來提供硬件原本不具備的特性。