1. 程式人生 > >CUDA從入門到精通到精通_筆記5:GPU入門綜述博文

CUDA從入門到精通到精通_筆記5:GPU入門綜述博文

  PS:這篇部落格出自我的一個同學的手中,寫的很好,是CUDA入門的好部落格,因此才從他的部落格中複製過來(複製改版也是個力氣活~),大家也可以檢視他部落格中其它的文章,涉獵很廣,從語言到開源包。此外,他是做推薦系統的,如果有關於推薦系統的問題也可以在部落格給他留言~!
——————————————————正文——————————————————————
         鑑於自己的畢設需要使用GPU CUDA這項技術,想找一本入門的教材,選擇了Jason Sanders等所著的書《CUDA By Example an Introduction to General Purpose GPU Programming》。這本書作為入門教材,寫的很不錯。自己覺得從理解與記憶的角度的出發,書中很多內容都可以被省略掉,於是就有了這篇博文。此博文記錄與總結此書的筆記和理解。注意本文並沒有按照書中章節的順序來寫。書中第8章影象互操作性和第11章多GPU系統上的CUDA C,這兩章沒有看。等有時間了再看吧,趕緊碼字。

CUDA是什麼
        CUDA,Compute Unified Device Architecture的簡稱,是由NVIDIA公司創立的基於他們公司生產的圖形處理器GPUs(Graphics Processing Units,可以通俗的理解為顯示卡)的一個平行計算平臺和程式設計模型。
        通過CUDA,GPUs可以很方便地被用來進行通用計算(有點像在CPU中進行的數值計算等等)。在沒有CUDA之前,GPUs一般只用來進行圖形渲染(如通過OpenGL,DirectX)。
        開發人員可以通過呼叫CUDA的API,來進行並行程式設計,達到高效能運算目的。NVIDIA公司為了吸引更多的開發人員,對CUDA進行了程式語言擴充套件,如CUDA C/C++,CUDA Fortran語言。注意CUDA C/C++可以看作一個新的程式語言,因為NVIDIA配置了相應的編譯器nvcc,CUDA Fortran一樣。更多資訊可以參考文獻。

64位Ubuntu12.04安裝CUDA5.5
        具體步驟請點選此處http://bookc.github.io/2014/05/08/my-summery-the-book-cuda-by-example-an-introduction-to-general-purpose-gpu-programming/
[b]對CUDA C的個人懵懂感覺[/b]
        如果粗暴的認為C語言工作的物件是CPU和記憶體條(接下來,稱為主機記憶體),那麼CUDA C工作的的物件就是GPU及GPU上的記憶體(接下來,稱為裝置記憶體),且充分利用了GPU多核的優勢及降低了並行程式設計的難度。一般通過C語言把資料從外界讀入,再分配資料,給CUDA C,以便在GPU上計算,然後再把計算結果返回給C語言,以便進一步工作,如進一步處理及顯示,或重複此過程。

 主要概念與名稱
主機
        將CPU及系統的記憶體(記憶體條)稱為主機。
裝置
        將GPU及GPU本身的顯示記憶體稱為裝置。
執行緒(Thread)
        一般通過GPU的一個核進行處理。(可以表示成一維,二維,三維,具體下面再細說)。
執行緒塊(Block)
        1. 由多個執行緒組成(可以表示成一維,二維,三維,具體下面再細說)。
        2. 各block是並行執行的,block間無法通訊,也沒有執行順序。
        3. 注意執行緒塊的數量限制為不超過65535(硬體限制)。
執行緒格(Grid)
        由多個執行緒塊組成(可以表示成一維,二維,三維,具體下面再細說)。

執行緒束
        在CUDA架構中,執行緒束是指一個包含32個執行緒的集合,這個執行緒集合被“編織在一起”並且“步調一致”的形式執行。在程式中的每一行,執行緒束中的每個執行緒都將在不同資料上執行相同的命令。
核函式(Kernel)
        1. 在GPU上執行的函式通常稱為核函式。
        2. 一般通過識別符號__global__修飾,呼叫通過<<<引數1,引數2>>>,用於說明核心函式中的執行緒數量,以及執行緒是如何組織的。
        3. 以執行緒格(Grid)的形式組織,每個執行緒格由若干個執行緒塊(block)組成,而每個執行緒塊又由若干個執行緒(thread)組成。
        4. 是以block為單位執行的。
        5. 叧能在主機端程式碼中呼叫。
        6. 呼叫時必須宣告核心函式的執行引數。
        7. 在程式設計時,必須先為kernel函式中用到的陣列或變數分配好足夠的空間,再呼叫kernel函式,否則在GPU計算時會發生錯誤,例如越界或報錯,甚至導致藍屏和宕機。
C/C++ code ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /* * @file_name HelloWorld.cu  字尾名稱.cu */ #include <stdio.h> #include <cuda_runtime.h>  //標頭檔案 //核函式宣告,前面的關鍵字__global__ __global__ void kernel( void ) { } int main( void ) { //核函式的呼叫,注意<<<1,1>>>,第一個1,代表執行緒格里只有一個執行緒塊;第二個1,代表一個執行緒塊裡只有一個執行緒。 kernel<<<1,1>>>(); printf"Hello, World!\n" ); return 0; }

dim3結構型別
        1. dim3是基亍uint3定義的向量型別,相當亍由3個unsigned int型組成的結構體。uint3型別有三個資料成員unsigned int x; unsigned int y; unsigned int z;
        2. 可使用亍一維、二維或三維的索引來標識執行緒,構成一維、二維或三維執行緒塊。
        3. dim3結構型別變數用在核函式呼叫的<<<,>>>中。
        4. 相關的幾個內建變數
        4.1. threadIdx,顧名思義獲取執行緒thread的ID索引;如果執行緒是一維的那麼就取threadIdx.x,二維的還可以多取到一個值threadIdx.y,以此類推到三維threadIdx.z。
        4.2. blockIdx,執行緒塊的ID索引;同樣有blockIdx.x,blockIdx.y,blockIdx.z。
        4.3. blockDim,執行緒塊的維度,同樣有blockDim.x,blockDim.y,blockDim.z。
        4.4. gridDim,執行緒格的維度,同樣有gridDim.x,gridDim.y,gridDim.z。
        5. 對於一維的block,執行緒的threadID=threadIdx.x。
        6. 對於大小為(blockDim.x, blockDim.y)的 二維 block,執行緒的threadID=threadIdx.x+threadIdx.y*blockDim.x。
        7. 對於大小為(blockDim.x, blockDim.y, blockDim.z)的 三維 block,執行緒的threadID=threadIdx.x+threadIdx.y*blockDim.x+threadIdx.z*blockDim.x*blockDim.y。
        8. 對於計算執行緒索引偏移增量為已啟動執行緒的總數。如stride = blockDim.x * gridDim.x; threadId += stride。
函式修飾符