溫故知新之GPU計(jì)算
據(jù)說(shuō),ChatGPT用了5000塊GPU,而對(duì)于普通工程師而言,看看過(guò)去,或許可以幫助望見(jiàn)未來(lái)。那么,GPU是什么呢?
圖形處理器(GPU,Graphic Processing Unit)是面向吞吐率設(shè)計(jì)、片上集成大量并行計(jì)算部件的處理器。2006年采用統(tǒng)一架構(gòu)的GPU和使用高級(jí)語(yǔ)言編程的開(kāi)發(fā)平臺(tái)的出現(xiàn),引發(fā)了GPU通用計(jì)算領(lǐng)域的迅猛發(fā)展。
1. GPU 溯源
早在計(jì)算機(jī)圖形學(xué)發(fā)展初期,圖形顯示受硬件條件的限制,僅作為計(jì)算機(jī)輸出的一種手段。圖形處理計(jì)算基本由軟件實(shí)現(xiàn),也稱為“軟解壓”,硬件負(fù)責(zé)輸出計(jì)算結(jié)果。隨著游戲市場(chǎng)和圖形計(jì)算領(lǐng)域的應(yīng)用需求迅速發(fā)展,其發(fā)展速度甚至超過(guò)了摩爾定律的限制。GPU的功能性越來(lái)越豐富,計(jì)算能力也越來(lái)越強(qiáng)大。每一代GPU的推出都會(huì)帶來(lái)新的變革,都深刻影響著其應(yīng)用領(lǐng)域。
第一代GPU出現(xiàn)在1998年,主要處理光柵化以及多紋理操作,但硬件不支持坐標(biāo)變換和光照變換。主要代表為NVIDIA TNT2等。
第二代GPU出現(xiàn)在1999年,增加了對(duì)坐標(biāo)變換和光照變換計(jì)算的硬件支持,可以使用硬件來(lái)完成光影處理以及幾何變換等特效,為CPU減輕了大量的計(jì)算任務(wù),但不具備可編程性。主要代表為NVIDIA GeForce256和ATI Radeon 7500等。
第三代GPU出現(xiàn)在2001年,實(shí)現(xiàn)了完全可編程的完整3D圖形處理流程。在頂點(diǎn)級(jí)上支持可編程性,在像素級(jí)上實(shí)現(xiàn)了有限的可編程性。主要代表為NVIDIA GeForce3/4和ATI Radeon 8500等。
第四代GPU出現(xiàn)在2003年,像素和頂點(diǎn)的可編程性更通用化,GPU進(jìn)入了完全可編程時(shí)代。同時(shí),GPU還配備了浮點(diǎn)計(jì)算功能。主要代表為NVIDIA GeForce FX和ATI Radeon 9700/9800。
第五代GPU出現(xiàn)在2004年,增加了更多的著色器功能。頂點(diǎn)著色器可以訪問(wèn)紋理,支持動(dòng)態(tài)分支操作。像素著色器支持分支操作、子函數(shù)調(diào)用、64位浮點(diǎn)紋理濾波和融合以及多目標(biāo)渲染等。主要代表有NVIDIA GeForce 6800 等。
新一代的GPU出現(xiàn)在2006年,采用完全統(tǒng)一渲染架構(gòu)設(shè)計(jì),將分離的可編程流水階段映射到統(tǒng)一的處理器陣列上,從而使得計(jì)算資源在頂點(diǎn)著色、幾何處理以及像素處理等任務(wù)之間動(dòng)態(tài)配置,取得良好的負(fù)載平衡。主要代表有NVIDIA Geforce 8800等。統(tǒng)一架構(gòu)GPU的出現(xiàn)帶來(lái)了革命性的變革,伴隨著相應(yīng)開(kāi)發(fā)平臺(tái)的推出,GPU不再限于傳統(tǒng)的圖形計(jì)算和游戲領(lǐng)域,開(kāi)始更廣泛地應(yīng)用于通用計(jì)算領(lǐng)域,推進(jìn)了高性能計(jì)算以及科學(xué)計(jì)算領(lǐng)域的快速發(fā)展。
2.GPU的處理流水線
2.1 固定功能流水線
在圖形流水線引入可編程性之前,GPU一直采用固定功能流水線,使用固定功能單元處理計(jì)算的各個(gè)步驟。應(yīng)用程序通過(guò)API庫(kù)(如微軟的DirectX和開(kāi)放性標(biāo)準(zhǔn)OpenGL)提供的接口函數(shù),實(shí)現(xiàn)應(yīng)用程序功能。固定功能圖形流水線中的主要步驟如下圖所示。
主機(jī)接口一般負(fù)責(zé)GPU和主機(jī)之間的數(shù)據(jù)傳輸。圖形處理之前圖像中物體表面被分解為三角形圖元的集合,頂點(diǎn)是指三角形圖元的角。頂點(diǎn)控制部件負(fù)責(zé)接收參數(shù)化的三角形圖元數(shù)據(jù),執(zhí)行數(shù)據(jù)轉(zhuǎn)化,存入頂點(diǎn)緩存中。頂點(diǎn)著色、變換和光照部件對(duì)頂點(diǎn)進(jìn)行坐標(biāo)變換、光照計(jì)算后,圖元裝配和光柵化操作對(duì)幾何圖元進(jìn)行紋理和顏色的插值,生成和窗口屏幕像素相對(duì)應(yīng)的片元(Fragment)。片元具有窗口坐標(biāo)、顏色、紋理坐標(biāo)、霧化坐標(biāo)等屬性。著色(Shader)階段則對(duì)片元實(shí)施紋理映射、顏色插值以及光照反射等操作,計(jì)算出三角形圖元中每個(gè)像素的最終顏色。最后,光柵操作部件(ROP,Raster OPeration)對(duì)像素執(zhí)行顏色混合、透明以及反鋸齒操作。幀緩沖區(qū)接口(FBI,F(xiàn)rame Buffer Interface)負(fù)責(zé)管理顯示的讀寫(xiě)操作。
2.2 可編程流水線
盡管GPU的硬件功能和圖形API不斷擴(kuò)展,但仍然滿足不了應(yīng)用快速變化的新需求。2001年3月,NVIDIA公司推出了具有著色器可編程能力的GeForce 3系列,相關(guān)圖形API升級(jí)到DirectX 8和頂點(diǎn)著色器擴(kuò)展OpenGL。之后,為了與DirectX 9匹配,GPU又?jǐn)U展了像素著色階段的通用可編程性和浮點(diǎn)計(jì)算功能。GPU的可編程流水線如下圖所示——
GPU的可編程性主要體現(xiàn)在兩個(gè)部分:頂點(diǎn)處理器(VP,Vertex Processor/Engine)和片元處理器(FP,F(xiàn)ragment Processor/Engine)??删幊添旤c(diǎn)處理器主要負(fù)責(zé)執(zhí)行頂點(diǎn)著色程序,執(zhí)行幾何變換和光照計(jì)算等操作??删幊唐幚砥髦饕?fù)責(zé)執(zhí)行像素著色程序,執(zhí)行紋理混合等操作??删幊绦缘囊霂?lái)了圖形處理的多樣化和可變性。而固定功能頂點(diǎn)處理器只能實(shí)現(xiàn)固定的光照模型和坐標(biāo)轉(zhuǎn)換,固定功能片元處理器只能實(shí)現(xiàn)有限的顏色混合和紋理映射。使用靈活的程序設(shè)計(jì)代替流水線中的固定操作,不但促進(jìn)了圖形計(jì)算領(lǐng)域和游戲市場(chǎng)的飛躍性發(fā)展,同時(shí)還引發(fā)了GPU在通用計(jì)算領(lǐng)域中的廣泛應(yīng)用。
2.3 統(tǒng)一架構(gòu)圖形流水線
雖然GPU引入了可編程性,但仍采用功能部件的分離設(shè)計(jì)。由于應(yīng)用特征決定了各流水線階段的負(fù)載不同,計(jì)算任務(wù)分離的功能單元設(shè)計(jì)會(huì)導(dǎo)致應(yīng)用性能受限于各階段計(jì)算量比例與功能單元配置之間的不匹配,從而導(dǎo)致計(jì)算資源的閑置。而實(shí)現(xiàn)不同任務(wù)的不同類型著色程序之間具有數(shù)據(jù)不相關(guān)和執(zhí)行獨(dú)立的特征,促使了GPU設(shè)計(jì)從可編程流水線階段向大規(guī)模并行統(tǒng)一架構(gòu)處理器的結(jié)構(gòu)變遷,下圖給出了GPU設(shè)計(jì)從分離設(shè)計(jì)到統(tǒng)一架構(gòu)的示意。
AMD于2005年初在Xenos中實(shí)現(xiàn)了統(tǒng)一處理架構(gòu),并于2006年率先宣布了面向高性能計(jì)算的流處理器(Stream Processor)。NVIDIA也于2006發(fā)布了采用統(tǒng)一架構(gòu)G80,并于同年11月引入了統(tǒng)一架構(gòu)計(jì)算平臺(tái)(CUDA,Compute Unified Device Architecture)。G80架構(gòu)嚴(yán)格遵守了微軟Direct X10統(tǒng)一渲染架構(gòu)的規(guī)范,使用統(tǒng)一計(jì)算陣列以及采用多線程并行執(zhí)行模式處理頂點(diǎn)著色器(VS,Vertex Shader)、像素著色器(PS,Pixel Shader)以及新引入的幾何著色器(GS,Geometry Shader)的計(jì)算任務(wù)。統(tǒng)一計(jì)算陣列在進(jìn)行頂點(diǎn)著色、幾何計(jì)算以及像素處理時(shí),能夠動(dòng)態(tài)劃分計(jì)算資源。由于不同的渲染算法在三個(gè)處理階段存在不同的負(fù)載,因此統(tǒng)一架構(gòu)能夠充分利用計(jì)算資源,取得很好的負(fù)載平衡。
3.基于GPU的通用計(jì)算
直到2006年統(tǒng)一架構(gòu)計(jì)算平臺(tái)的出現(xiàn),GPU在通用計(jì)算領(lǐng)域中的研究才成為業(yè)界的研究熱點(diǎn)。
3.1 可編程GPU
可編程GPU中的頂點(diǎn)處理器和片元處理器都是典型的流處理器,沒(méi)有大容量的存儲(chǔ)器以供讀寫(xiě),只是在芯片上利用臨時(shí)寄存器執(zhí)行流數(shù)據(jù)相關(guān)的操作。在GPU,流數(shù)據(jù)即為頂點(diǎn)圖元和光柵化后的像素。GPU處理的流數(shù)據(jù)元素為4單元向量,用以表示四維坐標(biāo)、三維空間齊次向量以及顏色等。頂點(diǎn)處理器和片元處理器都采用SIMD執(zhí)行模式并行執(zhí)行不同的流數(shù)據(jù)元素。因此,GPU兼具流處理器和向量處理器的特征。
這種流處理并行結(jié)構(gòu)為通用計(jì)算提供了并行計(jì)算的平臺(tái)。頂點(diǎn)處理器比較適用于除圖形繪制以外的幾何操作類應(yīng)用,而片元處理器由于擁有大容量的“紋理”存儲(chǔ)空間,因此可以更廣泛地用于各種通用計(jì)算。將可編程GPU應(yīng)用于通用計(jì)算領(lǐng)域,必須采用圖形繪制語(yǔ)言或流編程語(yǔ)言來(lái)編寫(xiě)程序,如OpenGL著色語(yǔ)言等。
GPU計(jì)算是基于矢量的運(yùn)算,一般先將待解決問(wèn)題轉(zhuǎn)化為能夠用矢量表示的問(wèn)題,強(qiáng)制轉(zhuǎn)化、分解為圖形操作。使用圖形繪制語(yǔ)言編寫(xiě)程序,調(diào)用DirectX或OpenGL等圖形API啟動(dòng)計(jì)算過(guò)程。輸入的數(shù)據(jù)集合必須存儲(chǔ)在紋理圖像中,再以三角形圖元的形式提交給GPU處理,光柵化操作的結(jié)果數(shù)據(jù)強(qiáng)制轉(zhuǎn)化為像素集的形式輸出。這種間接的實(shí)現(xiàn)方式極大地限制著GPU在通用計(jì)算領(lǐng)域中的應(yīng)用。同時(shí),GPU本身固有的訪存模式也限制了GPU領(lǐng)域發(fā)展的主要因素。計(jì)算之間傳遞數(shù)據(jù)需要通過(guò)像素幀緩沖區(qū),作為紋理映射輸入,再把幀緩沖區(qū)用于其它計(jì)算。
3.2 基于統(tǒng)一架構(gòu)的GPU
NVIDIA G80統(tǒng)一架構(gòu)如下圖所示:
由于G80統(tǒng)一架構(gòu)采用多線程并行執(zhí)行模式處理頂點(diǎn)著色器、像素著色器以及幾何著色器的計(jì)算任務(wù),因此體系結(jié)構(gòu)中的線程管理器實(shí)際上由頂點(diǎn)處理線程邏輯、像素處理線程邏輯以及幾何處理線程邏輯等三個(gè)指令分派單元構(gòu)成,分別負(fù)責(zé)頂點(diǎn)指令、像素指令和幾何處理指令的譯碼和分發(fā)。
目前,統(tǒng)一架構(gòu)GPU已廣泛應(yīng)用于高性能計(jì)算、科學(xué)計(jì)算和工程計(jì)算等領(lǐng)域,具體的應(yīng)用領(lǐng)域包括:醫(yī)學(xué)成像、分子動(dòng)力、生物醫(yī)藥、視頻轉(zhuǎn)換、金融分析、線性代數(shù)、天體物理、基因排序、天氣預(yù)報(bào)、石油勘探以 及地震探測(cè)等。
4. GPU 硬件架構(gòu)
G80系列是NVIDIA公司最早推出的統(tǒng)一架構(gòu)GPU,總體上看,G80由兩部分組成,分別為流處理器陣列(SPA,Stream Processor Array)和存儲(chǔ)系統(tǒng),這兩部分由一個(gè)片上交叉互連網(wǎng)絡(luò)連接,因此系統(tǒng) 具有良好的擴(kuò)展性。NVIDIA將統(tǒng)一結(jié)構(gòu)中的基本計(jì)算單元稱為流多處理器(SM,Streaming Multiprocessors)
AMD-ATI的第一代統(tǒng)一架構(gòu)RV670架構(gòu)與NVIDIA統(tǒng)一架構(gòu)設(shè)計(jì)理念不同的是,R600的設(shè)計(jì)思想兼顧線程級(jí)并行和指令級(jí)并行。早期的R600架構(gòu)具備64個(gè)5D VLIW線程處理器(TP,Thread Processor),每16個(gè)線程處理器構(gòu)成一個(gè)SIMD引擎(SE,SIMD Engine),采用SIMD執(zhí)行模式執(zhí)行VLIW指令。每個(gè)線程處理器中有5個(gè)異構(gòu)流核心(SC,Stream Core),負(fù)責(zé)執(zhí)行編譯器打包的VLIW指令。
而NVIDIA統(tǒng)一架構(gòu)中一個(gè)SM中的8個(gè)流核心完全對(duì)稱,采用SIMD執(zhí)行模式在不同數(shù)據(jù)上執(zhí)行相同指令。線程處理器中的T-Stream Core功能最強(qiáng),負(fù)責(zé)執(zhí)行超越函數(shù);另外四個(gè)稱為x、y、z和w的通用流核心則是完全相同,負(fù)責(zé)執(zhí)行基本的32位整數(shù)和浮點(diǎn)操作。線程處理器以VLIW模式來(lái)控制5個(gè)核心同時(shí)執(zhí)行運(yùn)算操作。除計(jì)算陣列之外,AMD GPU統(tǒng)一架構(gòu)中還包括了一些主要控制模塊,如命令處理器(Command Processor)、存儲(chǔ)控制器(Memory Controller)以及超線程管理調(diào)度器(Ultra-Threaded Dispatch Processor)。
NVIDIA于2010年推出的基于Fermi架構(gòu)的GTX480,采用40nm制造工藝,片上集成30億個(gè)晶體管,雙精度浮點(diǎn)計(jì)算性能達(dá)到768 GFLOPS。Fermi架構(gòu)在全芯片架構(gòu)上進(jìn)行了全新的設(shè)計(jì),在面向通用計(jì)算的架構(gòu)設(shè)計(jì)上實(shí)現(xiàn)了飛躍。
GPU在持續(xù)演進(jìn)與發(fā)展,2020年,NVIDIA推出了基于Ampere架構(gòu)的GPU A100。Ampere架構(gòu)仍然沿用了成熟的GPC-TPC-SM多級(jí)架構(gòu),GA100內(nèi)部包含8組GPC,每組GPC包含8組TPC,每組TPC又包含8組SM。主要的區(qū)別點(diǎn)在于,中間的L2緩存不再是統(tǒng)一的一組,而是被分割成了兩組。實(shí)際上,GA100的L2緩存相比起前代的GV100要大上近7倍——從原本的6MB直接跳到了40MB。大容量的L2緩存會(huì)在一定程度上減輕計(jì)算單元對(duì)顯存帶寬的依賴,不過(guò)為了避免訪問(wèn)遠(yuǎn)端L2緩存時(shí)出現(xiàn)延遲過(guò)高的問(wèn)題,它被分成了兩塊,保證延遲不過(guò)高。這種大容量特性和分割結(jié)構(gòu)讓GA100的L2緩存帶寬提升了2.3倍,同時(shí)硬件的緩存一致性保證應(yīng)用程序可以自動(dòng)利用大容量的L2緩存提升性能。
基于NVIDIA Ampere架構(gòu)的NVIDIA A100 GPU旨在通過(guò)其許多新的架構(gòu)功能和優(yōu)化提供盡可能多的AI和HPC計(jì)算能力。A100基于臺(tái)積電 7nm N7 FinFET制造工藝,與特斯拉V100中使用的12nm FFN工藝相比,該工藝提供了更高的晶體管密度、改進(jìn)的性能和更好的功率效率。新的多實(shí)例GPU(MIG)功能為多租戶和虛擬化GPU提供了增強(qiáng)的客戶端/應(yīng)用程序故障隔離和對(duì)云服務(wù)提供商特別有利的環(huán)境。第三代NVIDIA的NVLink互連速度更快、更具容錯(cuò)能力,為超大規(guī)模數(shù)據(jù)中心提供了改進(jìn)的多GPU性能擴(kuò)展。
5. GPU開(kāi)發(fā)平臺(tái)
CUDA(Compute Unified Device Architecture)是在NVIDIA統(tǒng)一架構(gòu)GPU上面向通用計(jì)算的并行編程開(kāi)發(fā)平臺(tái)。CUDA開(kāi)發(fā)平臺(tái)中包含了不同層次的調(diào)用接口,其中包括一組運(yùn)行時(shí)API、一組設(shè)備驅(qū)動(dòng)API以及CUDA提供的函數(shù)庫(kù)API。CUDA平臺(tái)的體系結(jié)構(gòu)如圖2.13所示。
CUDA驅(qū)動(dòng)API能夠直接控制底層硬件結(jié)構(gòu),CUDA運(yùn)行時(shí)API則是對(duì)驅(qū)動(dòng)API的封裝。程序設(shè)計(jì)過(guò)程中既可以調(diào)用CUDA驅(qū)動(dòng)API實(shí)現(xiàn)對(duì)硬件更高效的控制,也可以使用CUDA運(yùn)行時(shí)API更便捷、更直觀地實(shí)現(xiàn)CUDA開(kāi)發(fā)平臺(tái)提供的計(jì)算模式。
開(kāi)發(fā)庫(kù)是基于 CUDA 技術(shù)所提供的應(yīng)用開(kāi)發(fā)庫(kù)。其中,CUDA 包含了兩個(gè)重要的標(biāo)準(zhǔn)數(shù)學(xué)運(yùn)算庫(kù)——CUFFT(離散快速傅立葉變換)和 CUBLAS(離散基本線性計(jì)算)。這兩個(gè)數(shù)學(xué)運(yùn)算庫(kù)所解決的是典型的大規(guī)模的并行計(jì)算問(wèn)題,也是在密集數(shù)據(jù)計(jì)算中非常常見(jiàn)的計(jì)算類型。
運(yùn)行時(shí)環(huán)境提供了應(yīng)用開(kāi)發(fā)接口和運(yùn)行時(shí)組件,包括基本數(shù)據(jù)類型的定義和各類計(jì)算、類型轉(zhuǎn)換、內(nèi)存管理、設(shè)備訪問(wèn)和執(zhí)行調(diào)度等函數(shù)?;?CUDA 開(kāi)發(fā)的程序代碼在實(shí)際執(zhí)行中分為兩種,一種是運(yùn)行在 CPU 上的宿主代碼(Host Code),一種是運(yùn)行在GPU上的設(shè)備代碼(Device Code)。不同類型的代碼由于其運(yùn)行的物理位置不同,能夠訪問(wèn)到的資源不同,因此對(duì)應(yīng)的運(yùn)行期組件也分為公共組件、宿主組件和設(shè)備組件三個(gè)部分,基本上囊括了所有在 GPGPU 開(kāi)發(fā)中所需要的功能和能夠使用到的資源接口,開(kāi)發(fā)人員可以通過(guò)運(yùn)行期環(huán)境的編程接口實(shí)現(xiàn)各種類型的計(jì)算。CUDA 提供的運(yùn)行時(shí)環(huán)境是通過(guò)驅(qū)動(dòng)來(lái)實(shí)現(xiàn)各種功能的。
CUDA 支持 Windows、Linux、MacOS 三種主流操作系統(tǒng),支持 CUDA C 語(yǔ)言和 OpenCL 及 CUDA Fortran 語(yǔ)言。無(wú)論使用何種語(yǔ)言或接口,指令最終都會(huì)被驅(qū)動(dòng)程序轉(zhuǎn)換成 PTX(Parallel Thread Execution,并行線程執(zhí)行,CUDA架構(gòu)中的指令集,類似于匯編語(yǔ)言)代碼,交由顯示核心計(jì)算。
6.小結(jié)
本文簡(jiǎn)要回顧了對(duì)GPU流水線和體系結(jié)構(gòu)的變遷,初步了解了NVIDIA及AMD的統(tǒng)一架構(gòu),及其設(shè)計(jì)理 念上的異同,以及GPU開(kāi)發(fā)平臺(tái)編程模型和執(zhí)行機(jī)制。據(jù)說(shuō),ChatGPT用了5000塊GPU,而對(duì)于普通工程師而言,看看過(guò)去,或許可以幫助照見(jiàn)未來(lái)。
【參考資料】
- Evolution of the Graphics Processing Unit (GPU),https://ieeexplore.ieee.org/document/9623445
- https://images.nvidia.com/aem-dam/en-zz/Solutions/data-center/nvidia-ampere-architecture-whitepaper.pdf
- https://docs.nvidia.com/cuda/cuda-c-programming-guide/
- https://zhuanlan.zhihu.com/p/521471323
- http://cjc.ict.ac.cn/quanwenjiansuo/2013-4/whf.pdf