葉毅嘉
摘要:近年來,圖形處理器(Graphic Process Unit,GPU)的快速發展使得其逐步用于通用計算。在性能各異的并行計算平臺中,英偉達(NVIDIA)公司推出的計算統一設備架構(compute Unified Device Architecture,CUDA)因為充分利用GPU(Graphic Processing Unit)強大的計算能力實現了通用并行計算而受到研究者們的青睞。
關鍵詞:圖形處理器;CUDA;并行處理
0 引言
CUDA(Compute Unified Device Architecture)模型是由英偉達(NVIDIA)公司推出的一種基于GPU通用計算的編程模型和計算體系。該架構不需要借助圖像學API,直接使用類C語言即可完成并行計算,使得使用GPU處理圖像中的復雜計算成為可能。
1 CUDA編程模型
CUDA將CPU串行處理和GPU并行處理完美的結合起來。一個完整的CUDA程序是由主機(CPU)程序和設備(GPU)程序共同組成,主機程序主要是為設備程序的運行做前期準備工作,主要包括數據初始化、數據拷貝、內核函數間數據交換等。而設備程序主要就是完成并行計算的任務。CUDA編程模型分為兩個主要部分:CUDA軟件架構和CUDA硬件架構。其中CUDA軟件架構又包括了軟件棧、通用編程模型和存儲模型三個方面。下面將從上述內容對CUDA的編程模型進行介紹。
1.1 軟件模型
根據NVIDIA的官方文檔,CUDA的軟件體系共分3個方面:CUDA設備驅動程序、CUDA運行時庫和編程接口、CUDA官方函數庫。其中,設備驅動器是直接作用于GPU上的,開發者可以通過CUDA運行時庫和CUDA函數庫中的函數調用來使用設備。CUDA編程模型可以根據不同的需求提供不同的API,開發者可根據對GPU的控制程度來使用。并且為了很好的利用CUDA架構,CUDA還提供了一系列的輔助開發、調試的工具。
1.2 硬件模型
軟件程序的運行是建立在硬件的基礎上的,而GPU之所以能夠比CPU處理數據更加有效,在于GPU中有更多的晶體結構可用于計算。而在CUDA的硬件架構中,流處理器陣列是由多個線程處理器簇組成,而每個TPC又是由多個流處理器組成的。每個流處理器擁有一套完整的邏輯處理單元,就有一系列的功能,如取值、編碼、譯碼等。每個流處理器是由8個流處理單元和2組超級函數單元構成。
2 線程模型
在CUDA編程模型中是通過大量的并行線程來實現計算的,因此CUDA架構下最小的執行單元線程(thread)。每個線程塊中是由多個可以通信的線程組成,每個線程和線程塊都有唯一的標示ID,則可以通過索引確切定位到每個線程。線程的索引和線程的ID是與線程塊的維度所確定的,一維線程索引和ID是相同的,二維維度為(m,n)的線程塊,線程索引(x,y)所對應的線程ID為x+y*m;三維維度為(m,n,k)的線程塊,線程索引(x,y,z)所對應的線程ID為x+y*m+z*m*n。CUDA線程的開辟是根據所需解決問題的數據大小來確定的,而每個線程塊內的線程數由于其共享一個核心處理器的存儲器資源,則塊內線程數量是有限制的,這個可以通過NVIDIA給出的資料查詢。一般為了使每個線程塊的調度達到最優值,每個塊內的線程數一般設為16的倍數,但不能超過限定值。
3 存儲器模型
CUDA內部存儲器的結構是由寄存器、全局存儲器、共享內存、本地寄存器、常量內存和紋理內存組成。下面是對這6個存儲器的介紹:
寄存器位于GPU晶體片中,在各種CUDA存儲結構中,它的訪問速度快,因為它是線程所私有的,不允許其他線程訪問和使用。但由于GPU硬件的限制,寄存器不是無限的,每個線程塊中的寄存器是事先分配好的。但如果內核函數中分配的寄存器數量超過了寄存器的總數,編譯器會默認的將數據轉入設備端的本地內存中,這樣就會大大降低程序數據訪問的效率。
全局寄存器也稱之為線性寄存器,占設備內存的DRAM的大部分空間,在內核函數運行時,所有的線程都可以讀寫其中的數據。正因如此,它的訪問速度較慢,耗時較多,線程訪問全局寄存器一般都要花費幾百個時間周期。全局寄存器一般在CPU中完成數據空間的開辟、數據的拷貝和傳輸、數據的釋放等操作。
常量存儲器位于顯存中,空間大小一般為64K,是一段只讀的地址空間,由于其具有緩存并且無訪問沖突的優勢,常常用于常數的訪問。
本地存儲器是位于編譯器分配的全局存儲中,是歸每個線程所私有的數據空間,與全局存儲器相同,其在程序運行過程中不會緩存,所以其訪問速度也較慢。本地存儲器一般用來存放內核函數所聲明的變量。
共享存儲器是可以被同一塊中的所有線程訪問的可讀寫存儲器,它的生存期就是塊的生命期。在沒有沖突的情況下,訪問共享存儲器幾乎與訪問寄存器一樣快,是實現線程間通信的最好方法。在同一個塊內,所有的線程都能夠讀共享存儲器中的數據,相比于AMD的顯卡來說,共享存儲器是NVIDIA顯卡的一項特色。其和寄存器一樣位于GPU的晶體芯片中,所以其訪問速度較之全局內存和本地內存來說,其效率較高,并且可以減少線程塊中的線程通信的時間,一般只有2個時間周期。但由于其空間較小,一般每個SM有一個16K大小的共享寄存器,并且其數據只能在一個線程塊中共享。這就容易導致各線程塊中的數據不同步,容易引起數據混亂,為保證數據在程序執行中的同步性,CUDA中使用syncthreads()函數來實現線程塊的同步。
紋理存儲器是GPU中專門用來渲染紋理的圖像處理單元,它是一塊只讀空間。在內核函數運行的過程中,使用紋理寄存器首先需將數據與紋理綁定。紋理存儲器與常數存儲器一樣具有緩存機制。紋理存儲器相較于其它存儲器有兩大優勢:一是紋理存儲器中的數據可以反復使用,避免了數據的重復讀取,提高了效率;二是可以拾取坐標對應位置附近領域內的像元數據,該優勢在對圖像進行處理中,可以提高局部性數據讀取效率。
4 結語
21世紀人類面臨的眾多重要科技課題,這些課題沒有萬億次以上的計算能力是無法解決的。GPU與生俱來就有強大的計算能力,NVIDIA公司推出了cuDA架構使開發的難度大大降低,程序員可以很容易地利用GPU這個計算工具進行并行程序的開發。現在GPU在非圖形領域得到了廣泛的應用,基于GPU的通用計算研究也逐漸深入。