GPU通用計算與CUDA

目前,主流計算機中的處理器主要是中央處理器CPU和圖形處理器GPU。傳統上,GPU只負責圖形渲染,而大部分的處理都交給了CPU。

21世紀人類所面臨的重要科技問題,如衛星成像數據的處理、基因工程、全球氣候準確預報、核爆炸模擬等,數據規模已經達到TB 甚至PB量級,沒有萬億次以上的計算能力是無法解決的。與此同時,我們在日常應用中(如遊戲、高清視頻播放)面臨的圖形和數據計算也越來越複雜,對計算速度提出了嚴峻挑戰。

GPU在處理能力和存儲器帶寬上相對CPU有明顯優勢,在成本和功耗上也不需要付出太大代價,從而爲這些問題提供了新的解決方案。由於圖形渲染的高度並行性,使得GPU可以通過增加並行處理單元和存儲器控制單元的方式提高處理能力和存儲器帶寬。GPU設計者將更多的晶體管用作執行單元,而不是像 CPU那樣用作複雜的控制單元和緩存並以此來提高少量執行單元的執行效率。圖1-1對CPU與GPU中晶體管的數量以及用途進行了比較。



受遊戲市場和軍事視景仿真需求的牽引,GPU性能提高速度很快。最近幾年中,GPU的性能每一年就可以翻倍,大大超過了CPU遵照摩爾定律(每 18~24月性能翻倍)的發展速度。爲了實現更逼真的圖形效果,GPU支持越來越複雜的運算,其可編程性和功能都大大擴展了。

目前,主流GPU的單精度浮點處理能力已經達到了同時期CPU的10倍左右,而其外部存儲器帶寬則是CPU的5倍左右;在架構上,目前的主流GPU 採用了統一架構單元,並且實現了細粒度的線程間通信,大大擴展了應用範圍。2006年,隨着支持DirectX 10的GPU的發佈,基於GPU的通用計算(General Purpose GPU,GPGPU)的普及條件成熟了。

NVIDIA公司於2007年正式發佈的CUDA(Compute Unified Device Architecture,計算統一設備架構)是第一種不需藉助圖形學API就可以使用類C語言進行通用計算的開發環境和軟件體系。與以往的傳統 GPGPU開發方式相比,CUDA有十分顯著的改進。經過兩年多的發展,CUDA與支持CUDA的GPU在性能上有顯著提高,功能上也在不斷完善。

由於在性能、成本和開發時間上較傳統的CPU解決方案有顯著優勢,CUDA的推出在學術界和產業界引起了熱烈反響。現在,CUDA已經在金融、石油、天文學、流體力學、信號處理、電磁仿真、模式識別、圖像處理、視頻壓縮等領域獲得廣泛應用,並取得了豐碩的成果。隨着GPU的進一步發展和更多的開發人員參與到GPU通用計算的開發中來,可以預見,GPU將在未來的計算機架構中扮演更加重要的角色,甚至許多以往被認爲不可能的應用也會因爲GPU的強大處理能力而成爲現實。


1.1  多核計算的發展

並行是一個廣義的概念,根據實現層次的不同,可以分爲幾種方式。如圖1-2所示,最微觀的是單核指令級並行(ILP),讓單個處理器的執行單元可以同時執行多條指令;向上一層是多核(multi-core)並行,即在一個芯片上集成多個處理器核心,實現線程級並行(TLP);再往上是多處理器(multi-processor)並行,在一塊電路板上安裝多個處理器,實現線程和進程級並行;最後,可以藉助網絡實現大規模的集羣或者分佈式並行,每個節點(node)就是一臺獨立的計算機,實現更大規模的並行計算。




伴隨着並行架構的發展,並行算法也在不斷成熟與完善。從歷史上看,並行算法研究的高峯是在20世紀七八十年代。這一階段,出現了很多采用不同互連架構和存儲器模型的SIMD機,以及許多優秀的並行算法,在整個並行算法研究歷史上譜寫了輝煌的一頁。20世紀90年代中期以後,並行算法的研究更加註重面向應用,不但研究並行算法的設計與分析,也兼顧並行機體系結構與並行應用程序的設計。

工藝、材料和功耗的物理限制,處理器的頻率不會在短時間內有飛躍式的提高,因此採用各種並行方式提高計算能力勢在必行。現代CPU的每個核心中都採用了超標量 、超級流水線 、超長指令字 、SIMD 、超線程、分支預測等手段發掘程序內的指令級並行,並且主流的CPU中也有多個處理器核心。而GPU與生俱來就是一種衆核並行處理器,在處理單元的數量上還要遠遠超過CPU。

目前計算機中的處理器主流是擁有2~8個核心的多核CPU,及擁有數十乃至上百個核心的衆核GPU,並且兩者的核心數量仍會繼續增加。多核和衆核處理器的普及使得並行處理走入了尋常百姓家,不再是大型機和集羣的專利。這也使得並行算法和並行編程成爲程序員必須瞭解和掌握的內容。


1.1.1  CPU多核並行

過去20年間,Intel、AMD等廠家推出的CPU性能在不斷提高,但發展速度與20世紀80年代末90年代初的飛躍相比,已經不能相提並論。按照摩爾定律,每18~24個月芯片上可集成的晶體管數量就會翻倍,這一速度帶來了處理能力和速度的飛速增長。

CPU提高單個核心性能的主要手段是提高處理器的工作頻率,以及增加指令級並行。這兩種傳統的手段都遇到了問題:隨着製造工藝的不斷提高,晶體管的尺寸越來越接近原子的數量級,漏電流問題愈加顯著,單位尺寸上的能耗和發熱也越來越大,使得處理器的頻率提高速度越來越慢。另一方面,通用計算中的指令級並行並不多,因此費盡苦心設計獲得的性能提高與投入的大量晶體管相比,顯得很不划算。使用流水線可以提高指令級並行,但更多更深的流水線可能會導致效率問題,例如,Intel的Pentium 4架構中有更長的流水線,但運算性能還不及同頻的Pentium Ⅲ。爲了實現更高的指令級並行,就必須用複雜的猜測執行機制和大塊的緩存保證指令和數據的命中率。現代CPU的分支預測正確率已經達到了99%以上,沒有什麼提高餘地。緩存的大小對CPU的性能有很大影響,過去低端的賽揚和主流的奔騰處理器用於計算的單元基本一樣,主要區別就在於緩存的大小。但是繼續增加緩存大小,最多也就是讓真正用於計算的少量執行單元滿負荷運行,這顯然無助於CPU性能的進一步提高。

由於上述原因限制了單核CPU性能的進一步提高,CPU廠商開始在單塊芯片內集成更多的處理器核心,使CPU向多核方向發展。2005 年,Intel和AMD正式向主流消費市場推出了雙核CPU產品,2007年推出4核CPU,2009年Intel CPU進入8核時代,Intel CPU核心數量及製程的變化如圖1-3所示。隨着多核CPU的普及,現代的普通PC都擁有數個CPU核心,實際上已經相當於一個小型集羣。可以預見,未來 CPU中的核心數量還將進一步增長。與此同時,多核架構對傳統的系統結構也提出了新的挑戰,如存儲器壁壘、芯片、板極、系統級均衡設計以及可移植性等方面的問題。

隨着CPU從單核發展爲多核,越來越多的程序員也意識到了多線程編程的重要性。多線程編程既可以在多個CPU核心間實現線程級並行,也可以通過超線程等技術更好地利用每一個核心內的資源,充分利用CPU的計算能力。除了直接使用操作系統提供的線程管理API實現多線程外,還可以通過一些庫或者語言擴展等方法實現多線程並行計算。目前常見的多線程編程語言擴展有OpenMP和Intel的TBB(Thread Building Block)等。


表1-1  計算機的Flynn分類

分類 說明
SISDSingle Instruction Single Data)系統 傳統的計算機是單CPU,同一時刻只能執行一條指令,處理一個數據,即一個控制流和一個數據流的順序執行。SISD也可以並行,只要各CPU執行不同的指令流,處理不同數據空間的數據流,就仍是SISD模式
SIMDSingle Instruction Multiple Data)系統 向量機中,一個指令部件同時控制多個執行部件,一條指令可以同時操作多個數據,即一個控制流多個數據流。向量機執行操作時,向量處理單元並行處理由同類數據組成的數組,結果按若干個週期的頻率輸出。相對於細粒度的SIMD,粗粒度的有SPMDSPMT等,可視作SIMD的子類
MISDMultiple Instructions Single Data)系統 MISD系統結構只適用於某些特定的算法。MISD機中,各個處理單元排成線性陣列,對流經的同一數據流,執行不同的指令流,這種應用非常有限
MIMDMultiple Instruction Multiple Data)系統 多處理器在不同的數據流上執行不同的指令流,與SISD的本質區別在於不同處理器處理的指令與數據彼此相關,往往是並行地在執行同一工作的不同部分。高性能服務器與超級計算機大多是MIMD



1.1.2  超級計算機、集羣與分佈式計算

超級計算機一般指在性能上居於世界領先地位的計算機,通常有成千上萬個處理器,以及專門設計的內存和I/O系統。它們採用的架構與通常的個人計算機有很大區別,使用的技術也隨着時代和具體應用不斷變動。儘管如此,超級計算機與PC的關係仍然十分緊密。一部分超級計算機使用的處理器在PC市場上也能找到;而超級計算機使用的一些技術,如SIMD向量機、多核處理器,以及處理器封裝技術等也都已普及到普通計算機中。支持CUDA的GPU可以看成是一個由若干個向量處理器組成的超級計算機,性能也確實可以和小型的超級計算機相比。爲了將更多的資源用於計算,過去的超級計算機的界面往往都很簡單,往往拆掉顯卡以降低功耗。CUDA技術推出以後,越來越多的超級計算機開始安裝GPU以提高性能,降低計算成本。

計算機集羣(簡稱集羣)是一種通過一組鬆散集成的計算機軟件和/或硬件連接起來高度緊密地協作完成計算工作的系統。分佈式計算則將大量的計算任務和數據分割成小塊,由多臺計算機分別計算,在上傳運算結果後,將結果統一合併得出結果,組織較爲鬆散。兩者一般都採用網絡將各個節點連接起來,性價比都高於專門的超級計算機。例如進行蛋白質摺疊計算的Folding@home分佈式計算項目,現在有大約十萬臺計算機參加,計算能力甚至超過了大多數超級計算機。值得一提的是,在該項目中,僅有的11370顆支持CUDA的GPU提供了總計算能力的一半;而運行Windows的CPU共計208268顆,卻只能實現198萬億次浮點運算,僅相當於該項目總處理能力的6%。

目前在超級計算機、集羣與分佈式計算程序開發中常用的工具是MPI(Message Passing Interface,消息傳遞接口)。MPI是一個免費和開源庫,可以被C/Fortran77/C++/ Fortran90調用,幾乎得到所有並行計算機製造商的支持。它是一種消息傳遞編程模型,廣泛應用於多類並行機,特別適用於分佈式存儲的並行機和服務器集羣。



1.1.3  CPU+GPU異構並行

目前主流計算機的處理能力主要來自CPU和GPU。CPU與GPU一般經北橋 通過AGP或者PCI-E總線連接,各自有獨立的外部存儲器,分別是內存和顯存。在一些芯片組中使用的集成GPU沒有采用獨立的顯存芯片,直接從內存中分出一塊區域作爲顯存。Intel和AMD提出的CPU-GPU融合產品還準備直接將CPU和GPU通過QPI或者HT總線連接,集成在一塊芯片內。可以預見,受面積、功耗和散熱的限制,此類融合產品不大可能集成性能很高的GPU,並且有可能不爲GPU提供獨立顯存。
傳統的CPU+GPU異構並行處理的典型任務是圖形實時渲染。在這類應用中,CPU負責根據用戶的輸入和一定的規則(如遊戲的AI)確定在下一幀需要顯示哪些物體,以及這些物體的位置,再將這些信息傳遞給GPU,由GPU繪製這些物體並進行顯示。兩者的計算是並行的:在GPU繪製當前幀的時候,CPU可以計算下一幀需要繪製的內容。

在這些處理中,CPU負責的是邏輯性較強的事務計算,GPU則負責計算密集度高的圖形渲染。爲了滿足事務計算的需要,CPU的設計目標是使執行單元能夠以很低的延遲獲得數據和指令,因此採用了複雜的控制邏輯和分支預測,以及大量的緩存來提高執行效率;而GPU必須在有限的面積上實現很強的計算能力和很高的存儲器帶寬,因此需要大量執行單元來運行更多相對簡單的線程,在當前線程等待數據時就切換到另一個處於就緒狀態等待計算的線程。簡而言之,CPU對延遲將更敏感,而GPU則側重於提高整體的數據吞吐量。CPU和GPU的設計目標的不同決定了兩者在架構和性能上的巨大差異,具體來說有:


1.CPU線程與GPU線程

CPU的一個核心通常在一個時刻只能運行一個線程的指令。CPU的多線程機制通過操作系統提供的API實現,是一種軟件粗粒度多線程。當一個線程中斷,或者等待某種資源時,操作系統就保存當前線程的上下文,並裝載另外一個線程的上下文。這種機制使得CPU切換線程的代價十分高昂,通常需要數百個時鐘週期。某些具有超線程功能的CPU可以將一個物理核心虛擬成多個核心,但每個虛擬核心在一個時刻也只能運行一個線程。

GPU採用的則是由硬件管理的輕量級線程,可以實現零開銷的線程切換。線程的切換在這裏成爲一件好事:當一個線程因爲訪問片外存儲器或者同步指令開始等待以後,可以立即切換到另外一個處於就緒態的線程,用計算來隱藏延遲。當線程中的計算指令需要的時間較多,而訪存相對較少,即計算密集度比較高時,延遲就可以被計算隱藏,而且線程越多,延遲隱藏得更好。


2.多核與衆核

當前的主流CPU中一般有2~8個核心,每個核心中有3~6條執行流水線。這些核心極採用了很多提高指令級並行的技術,如超標量超深流水線、亂序執行、預測執行,以及大容量緩存等,也採用瞭如SSE、3Dnow!一類的數據級並行技術。由於緩存和控制邏輯需要很大面積,因此在一塊芯片上能夠集成的核心數量也就被限制了。

當前的NVIDIA GPU中有1~30個包含完整前端的流多處理器,每個流多處理器可以看成一個包含8個1D流處理器的SIMD處理器。CUDA就利用了多個流多處理器間的粗粒度任務級或數據級並行,以及流多處理器內的細粒度數據並行。

儘管GPU的運行頻率低於GPU,但更多的執行單元數量還是使GPU能夠在浮點處理能力上獲得優勢,即使是芯片組裏集成的低端GPU,在單精度浮點處理能力上也能和主流的CPU打成平手,而主流GPU的性能則可以達到同時期主流CPU性能的10倍左右,如圖1-4所示。

  





3.外部存儲器

GT200 GPU的顯存帶寬達到了140GB/s,是同時期CPU最高內存帶寬的5倍,圖1-5是CPU與GPU同期帶寬的比較。造成GPU與CPU外部存儲器帶寬差異的主要原因有兩個:

   



首先,顯存中使用的GDDR存儲器顆粒與內存的DDR存儲器顆粒在技術上基本相同,但顯存顆粒是直接固化在顯卡的PCB板上的,而內存則爲了兼顧可擴展性的需要,必須通過DIMM插槽與主板相連。直接焊在PCB板上的顯存的信號完整性問題比通過插槽連接的內存更容易解決,顯存的工作頻率也通常比使用相同技術的內存要高一些。

其次,目前的CPU存儲器控制器一般基於雙通道或者三通道技術的,每個通道位寬64bit;而GPU中則存在數個存儲器控制單元,例如GTX280 GPU中就有8個存儲器控制器,每個控制兩片位寬32bit的顯存芯片,使總的存儲器位寬達到512bit。這樣,儘管內存中的DDR存儲器顆粒比顯卡上的GDDR存儲器顆粒還要多,但CPU能夠同時訪問的存儲器顆粒反而少於GPU。


4.緩存

CPU中的緩存主要用於減小訪存延遲和節約帶寬。緩存在多線程環境下會發生失效反應:在每次線程上下文切換之後,都需要重建緩存上下文,一次緩存失效的代價是幾十到上百個時鐘週期。同時,爲了實現緩存與內存中數據的一致性,還需要複雜的邏輯進行控制。

在GPU中則沒有複雜的緩存體系與替換機制。GPU緩存是隻讀的,因此也不用考慮緩存一致性問題。GPU緩存的主要功能是用於過濾對存儲器控制器的請求,減少對顯存的訪問。所以GPU上緩存的主要功能不是減小訪存延遲,而是節約顯存帶寬。

從上面的分析可以看出,GPU的主要設計目標是以大量線程實現面向吞吐量的數據並行計算,適合於處理計算密度高、邏輯分支簡單的大規模數據並行任務。而CPU則有複雜的控制邏輯和大容量的緩存減小延遲,能夠適應各種不同的情況,尤其擅長複雜邏輯運算。使用GPU處理數據並行任務,而由CPU進行復雜邏輯和事務處理等串行計算,就可以最大限度地利用計算機的處理能力,實現桌面上的超級計算。CPU+GPU並行不只是計算能力的提高,也不只是節省了成本和能源;將高性能計算普及到桌面,使得許多以往不可能的應用成爲了現實,這種靈活性本身就是一種革命性的進步。



1.2  GPU發展簡介

自1999年NVIDIA發佈第一款GPU以來,GPU的發展就一直保持了很高的速度。爲了實時生成逼真3D圖形,GPU不僅採用了最先進的半導體制造工藝,在設計上也不斷創新。傳統上,GPU的強大處理能力只被用於3D圖像渲染,應用領域受到了限制。隨着以CUDA爲代表的GPU通用計算API的普及,GPU在計算機中的作用將更加重要,GPU的含義也可能從圖形處理器(Graphic Processing Unit)擴展爲通用處理器(General Purpose Unit)。


1.2.1  GPU渲染流水線

GPU的渲染流水線的主要任務是完成3D模型到圖像的渲染(render)工作。常用的圖形學API(Direct3D/OpenGL)編程模型中的渲染過程被分爲幾個可以並行處理的階段,分別由GPU中渲染流水線的不同單元進行處理。GPU輸入的模型是數據結構(或語言)定義的對三維物體的描述,包括幾何、方向、物體表面材質以及光源所在位置等;而GPU輸出的圖像則是從觀察點對3D場景觀測到的二維圖像。在GPU渲染流水線的不同階段,需要處理的對象分別是頂點(vertex)、幾何圖元(primitive)、片元(fragment)、像素(pixel)。如圖1-6所示,典型的渲染過程可以分爲以下幾個階段:


1.頂點生成

圖形學API用簡單的圖元(點、線、三角形)表示物體表面。每個頂點除了(x,y,z)三維座標屬性外還有應用程序自定義屬性,例如位置、顏色、標準向量等。


2.頂點處理

本階段主要是通過計算把三維頂點座標映射到二維屏幕,計算各頂點的亮度值等。這個階段是可編程的,由vertex shader完成。輸入與輸出一一對應,即一個頂點被處理後仍然是一個頂點,各頂點間的處理相互獨立,可以並行完成。


3.圖元生成

根據應用程序定義的頂點拓撲邏輯,把上階段輸出的頂點組織起來形成有序的圖元流。頂點拓撲邏輯定義了圖元在輸出流中的順序,一個圖元記錄由若干頂點記錄組成。


4.圖元處理

這一階段也是可編程的,由geometry shader完成。輸入和輸出不是一一對應,一個圖元被處理後可以生成0個或者多個圖元,各圖元處理也是相互獨立的。本階段輸出一個新的圖元流。


5.片元生成

這一階段將對每一個圖元在屏幕空間進行採樣,即光柵化。每一個採樣點對應一個片元記錄,記錄該採樣點在屏幕空間中的位置、與視點之間的距離以及通過插值獲得的頂點屬性等。


6.片元處理

片元處理階段是可編程的,由pixel shader完成,主要完成圖形的填色功能。模擬光線和物體表面的交互作用,決定每個片元的顏色及透明程度等屬性。


7.像素操作

用每個片元的屏幕座標來計算該片元對最終生成圖像上的像素的影響程度。本階段計算每個採樣點離視點的距離,丟棄被遮擋住的片元。當來自多個圖元的片元影響同一個像素時,往往都根據圖元處理輸出流中定義的圖元位置進行像素更新。

下面以繪製一朵玫瑰爲例來說明GPU圖形流水線的工作流程。首先,GPU從顯存讀取描述玫瑰3D外觀的頂點數據,生成一批反映三角形場景位置與方向的頂點;由vertex shader計算2D座標和亮度值,在屏幕空間繪出構成玫瑰的頂點;頂點被分組成三角形圖元;geometry shader進行進一步細化,生成更多圖元;隨後,GPU中的固定功能單元對這些圖元進行光柵化,生成相應的片元集合;由pixel shader從顯存中讀取紋理數據對片元上色和渲染;最後一個階段,根據片元信息更新玫瑰圖像,主要是可視度的處理。由ROP完成像素到幀緩衝區的輸出,幀緩衝區中的數據經過D/A輸出到顯示器上以後,就可以看到繪製完成的玫瑰圖像了。

  




圖形渲染過程具有內在的並行性:頂點之間、圖元之間、片元之間的數據相關性很弱,對它們的計算可以獨立並行進行。這使得通過並行處理提高吞吐量成爲可能。

首先,渲染流水線具有時間上的功能並行。流水線的各級可以同時工作,當各級都能滿負荷工作時,能夠獲得最高性能。

其次,渲染流水線具有數據並行性。不僅可以通過SIMD提高每一個可編程着色器的性能,還可以在一個GPU內集成多條渲染流水線實現更高的吞吐量。



1.2.2  着色器模型

在圖形渲染中,GPU中的可編程計算單元被稱爲着色器(shader),着色器的性能由DirectX中規定的shader model來區分。GPU中最主要的可編程單元是頂點着色器和像素着色器。爲了實現更細膩逼真的畫質,GPU的體系架構從最早的固定功能流水線到可編程流水線,再到DirectX 10時代的以通用的可編程計算單元爲主、圖形固定功能單元爲輔的形式。在這一過程中,着色器的可編程性也隨着架構的發展不斷提高。附錄G給出了不同版本着色器模型的性能參數,這裏的表1-2給出了每代模型的大概特點。

表1-2  Shader Model版本

 

Shader Model

GPU代表

顯卡時代

特點

 

1999年第一代NV GeForce 256

DirectX 7

19992001

GPU可以處理頂點的矩陣變換和進行光照計算(T&L),操作固定,功能單一,不具有可編程性

SM 1.0

2001年第二代NV GeForce3

DirectX 8

將圖形硬件流水線作爲流處理器來解釋,頂點部分出現可編程性,像素部分可編程性有限(訪問紋理的方式和格式受限,不支持浮點)

SM 2.0

2003年第三代NV GeForceFxATI R300

DirectX 9.0b

頂點和像素可編程性更通用化,像素部分支持FP16/24/32浮點,可包含上千條指令,紋理使用更加靈活:可用索引進行查找,也不再限制在[0,1]範圍,從而可用作任意數組(這一點對通用計算很重要)

SM 3.0

2004年第四代NV GeForce 6ATI X1000

DirectX 9.0c

頂點程序可以訪問紋理VTF,支持動態分支操作,像素程序開始支持分支操作(包括循環、if/else等),支持函數調用,64位浮點紋理濾波和融合,多個繪製目標

SM 4.0

2007第五代NV G80AMD/ATI R600

DirectX 10

20072009

統一渲染架構,支持IEEE754浮點標準,引入geometry shader(可批量進行幾何處理),指令數從1K提升至64K,寄存器從32個增加到4096個,紋理規模從16+4個提升至128個,材質texture格式變爲硬件支持的RGBE格式,8192*8192的最高紋理分辨率比原先的2048*2048高很多

 

 


傳統的分離架構中兩種着色器的比例是固定的。在GPU核心設計完成時,各種着色器的數量便確定下來,比如著名的"黃金比例"--頂點着色器與像素着色器數量爲1∶3。但不同的遊戲對頂點着色器和像素着色器計算能力的需求是不同的,如果場景中有大量的小三角形,頂點着色器就必須滿負荷工作,而像素着色器則會被閒置;如果場景中只有少量的大三角形,又會發生相反的情況。因此,固定比例的設計無法完全發揮GPU中所有計算單元的性能。

兩種着色器的架構既有相同之處,又有一些不同。兩者處理的都是四元組數據(頂點着色器處理用於表示座標的w、x、y、z,但像素着色器處理用於表示顏色的a、r、g、b)頂點渲染,需要比較高的計算精度;而像素渲染則可以使用較低的精度,從而可以增加在單位面積上的算術單元數量。在shader model 4.0前,兩種着色器的精度都在不斷提高,但同時期頂點着色器的精度要高於像素着色器。

shader model 4.0對頂點着色器和像素着色器的規格要求完全相同,都支持32位浮點數。這是GPU發展的一個分水嶺:過去只能處理頂點和只能處理像素的專門處理單元被通用的統一着色器(Unified Shader)架構取代了。統一渲染架構能夠充分利用可編程着色器的處理能力,也更加適應通用計算的需要。

 

 


1.2.3  NVIDIA GPU發展簡介

NVIDIA公司是全球視覺計算技術的行業領袖及GPU的發明者。作爲高性能處理器的GPU可在工作站、個人計算機、遊戲機和移動設備上生成令人歎爲觀止的互動圖形效果。

1993年,黃仁勳與Curtis Priem和Chris Malachowsky共同成立了NVIDIA公司,在接下來的幾年裏研製了NV-1和NV-2顯示芯片,並在市場上推出了自己的產品,做出了最初的嘗試。David Kirk也在這一階段加入了NVIDIA。

1997年,NVIDIA發佈了NV-3顯示芯片,即RIVA-128。RIVA-128具有在當時來說優秀的2D性能和不錯的3D性能,在市場上獲得了成功。與當時的PCI接口Voodoo圖形加速卡相比,RIVA-128是一塊基於AGP接口的完整的顯卡。在1997年底,NVIDIA又發佈了 RIVA-128ZX和TNT顯示芯片。

1999年2月,TNT-2顯示芯片發佈並投放市場。TNT-2具有當時最強大的3D圖形性能,並且有面向不同市場的多個版本。TNT-2在市場上取得了空前的成功,奠定了NVIDIA在視覺計算領域的領導地位。

1999年8月,NVIDIA發佈了全球第一顆GPU--GeForce-256。它主要由兩個模塊組成,一個是頂點轉換和頂點光照處理器,由進行 32位浮點數運算的固定功能單元組成;另一個是像素着色流水線(或片元着色流水線),由進行定點數運算的固定功能單元組成。GeForce 256 可以支持OpenGL和微軟公司的DirectX 7標準API接口。在DirectX 7時代,NVIDIA推出了GeForce 2系列產品。

2001年,NVIDIA推出了第一款擁有可編程頂點着色器的GPU--GeForce 3。它使用了可編程的頂點處理器和不可編程的像素處理器(或片元處理器),並且兩者都能完成32bit單精度浮點運算。GeForce 3可以支持DirectX 8和OpenGL API。在DirectX 8時代,NVIDIA的主要產品是GeForce 3系列和GeForce 4系列,以及面向低端市場的GeForce MX系列,其中GeForce MX系列只支持DirectX 7。

2002年,NVIDIA推出的GeForce Fx是第一款使用32位浮點流水線作爲可編程的頂點處理器的GPU,可以支持DirectX 9.0,呈現電影級畫質。隨後幾年推出的GeForce 6系列和GeForce 7系列能夠支持DirectX 9.0C API,改進了着色引擎,能夠支持更多的特效。

2006年的GeForce 8系列GPU率先採用了統一渲染架構,以通用渲染單元替代了原來分離的頂點着色單元和像素着色單元,能夠支持DirecrtX 10.0。從GeForce 8系列開始,NVIDIA的GPU開始支持CUDA。

2007年,CUDA正式發佈,引發了GPU通用計算的革命。

2008年,NVIDIA發佈了能夠支持CUDA計算能力1.1的GeForce 9系列GPU,以及支持CUDA計算能力1.3的GT200 GPU。NVIDIA在GT 200中引入了大量重要改進,使得GT200不僅具有極高的處理能力和存儲器帶寬,用於通用計算時的可編程性和靈活性也更加出色。同年,NVIDIA發佈了Tegra系列產品,進軍移動處理器市場。

目前,NVIDIA在桌面、專業設計、高性能計算及嵌入式等不同領域推出了性能出衆的GPU產品,分別對應不同的產品線。

GeForce系列主要面向家庭和企業的娛樂應用,能夠爲用戶提供身臨其境的視覺體驗。該系列又可以分爲面向性能的GTX系列,面向主流市場的 GTS和GT系列,以及具有高性價比的GS系列。

Quadro系列主要應用於圖形工作站中,對專業領域應用進行了專門優化。Quadro系列按照不同應用領域劃分,有爲AutoCAD設計優化的 VX系列,爲專業圖形渲染優化的FX系列,用於移動和專業顯示的NVS系列,以及爲圖像和視頻應用優化的CX系列。

Tesla系列是專門用於高性能通用計算的產品線,以有限的體積和功耗實現了強大的處理能力。Tesla系列包括以擴展卡形式安裝的C系列,包含兩個GPU的D系列和包含4個GPU的S系列,以及將CPU和GPU安裝於同一單元內的M系列。D、S和M系列適合作爲集羣或者超級計算機的基本單元,而C 系列則可以爲普通研究人員提供強大的計算能力。

Tegra系列是NVIDIA爲便攜式和移動領域推出的全新解決方案,在極爲有限的面積上集成了通用處理器、GPU、視頻解碼、網絡、音頻輸入輸出等功能,並維持了極低的功耗。Tegra可以提供長達數天的續航能力及強大的圖形和視頻功能,是一種革命性的新產品。未來Tegra系列產品可能引入 GPU通用計算功能,這將極大地提高移動便攜設備的計算能力和應用領域。



1.3  從GPGPU到CUDA

傳統上,GPU的應用被侷限於處理圖形渲染計算任務,無疑是對計算資源的極大浪費。隨着GPU可編程性的不斷提高,利用GPU完成通用計算的研究漸漸活躍起來。將GPU用於圖形渲染以外領域的計算稱爲GPGPU(General-purpose computing on graphics processing units,基於GPU的通用計算)。GPGPU計算通常採用CPU+GPU異構模式,由CPU負責執行復雜邏輯處理和事務管理等不適合數據並行的計算,由GPU負責計算密集型的大規模數據並行計算。這種利用GPU強大處理能力和高帶寬彌補CPU性能不足的計算方式在發掘計算機潛在的性能,在成本和性價比方面有顯著優勢。但是,傳統的GPGPU受硬件可編程性和開發方式的制約,應用領域受到了限制,開發難度也很大。


1.3.1  傳統GPGPU開發

DirectX 10.0規範推出前的GPU中的主要可編程單元是頂點着色器和像素着色器。在沒有采用統一渲染架構的GPU中,兩者在物理上是分離的,數量上的比例也是固定的。一個具體的應用程序很難同時完全利用兩種可編程着色器的性能。此外,傳統GPU不允許計算單元之間通過片內的存儲器進行通信,因此GPGPU也只能採用嚴格的SIMD模型。不允許數據間的通信,限制了很多算法,也就制約了傳統GPGPU的應用範圍和代碼效率。

最早的GPGPU開發直接使用了圖形學API編程。這種開發方式要求編程人員將數據打包成紋理,將計算任務映射爲對紋理的渲染過程,用匯編或者高級着色器語言(如GLSL、Cg、HLSL)編寫shader程序,然後通過圖形學API(Direct3D、OpenGL)執行。這種"曲線救國"的方式要求編程人員不僅要熟悉自己需要實現的計算和並行算法,還要對圖形學硬件和編程接口有深入的瞭解。由於開發難度大,傳統GPGPU沒有被廣泛應用。

2003年,斯坦福大學的Ian Buck等人對ANSI C進行擴展,開發了基於NVIDIA Cg的Brook源到源編譯器。Brook可以將類似C的brook C語言通過brcc編譯器編譯爲Cg代碼,隱藏了利用圖形學API實現的細節,大大簡化了開發過程。但早期的Brook編譯效率很低,並且只能使用像素着色器進行運算。受GPU架構限制,Brook也缺乏有效的數據通信機制。AMD/ATI公司在其GPGPU通用計算產品Stream中採用了Brook的改進版本Brook+作爲高級開發語言。Brook+的編譯器的工作方式與Brook不同,提高了效率。在2009年推出Brook+ 1.3以前,Brook+早期版本與Brook相比在語法和編程模型上沒有顯著改進,同樣缺乏有效的線程間數據通信手段。


1.3.2  CUDA開發

2007年6月,NVIDIA推出了CUDA(Compute Unified Device Architecture,統一計算設備架構)。CUDA是一種將GPU作爲數據並行計算設備的軟硬件體系。到目前爲止,CUDA的版本已經進行了三次版本提升,功能不斷完善,能夠很好地支持新硬件的特性。

CUDA不需要藉助於圖形學API,並採用了比較容易掌握的類C語言進行開發。開發人員能夠從熟悉的C語言比較平穩地從CPU過渡到GPU,而不必重新學習語法。當然,要開發高性能的GPU通用計算程序,開發人員仍然需要掌握並行算法和GPU架構方面的知識。

與以往的GPU相比,支持CUDA的GPU在架構上有了顯著的改進,這兩項改進使CUDA架構更加適用於GPU通用計算。一是採用了統一處理架構,可以更加有效地利用過去分佈在頂點渲染器和像素渲染器的計算資源;二是引入了片內共享存儲器,支持隨機寫入(scatter)和線程間通信。

CUDA爲開發人員有效利用GPU的強大性能提供了條件。自推出後,CUDA被廣泛應用於石油勘測﹑天文計算﹑流體力學模擬﹑分子動力學仿真﹑生物計算﹑圖像處理﹑音視頻編解碼等領域,在很多應用中獲得了幾倍、幾十倍,乃至上百倍的加速比。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章