CUDA C編程入門-編程模型

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   strong   io   資料   

  這章節介紹CUDA編程模型的主要的概念。

2.1.kernels(核函數)

  CUDA C擴充了C語言,允許程式員定義C函數,稱為kernels(核函數)。並行地在N個CUDA線程中執行N次。

  使用__global__說明符聲明一個核函數,調用使用<<<...>>>,並且指定執行的CUDA線程數目。執行的每個線程都有一個獨一的ID,在核函數中可以通過變數threadIdx擷取。

  例子,兩個向量的加,A加B,並把結果存入C,A、B和C的長度為N。

__global__ void addKernel(int *c, const int *a, const int *b){    int i = threadIdx.x;    c[i] = a[i] + b[i];}int main(){  ...  // Launch a kernel on the GPU with one thread for each element.    addKernel<<<1, N>>>(c, a, b);  ...      }

 

  其中,每一個線程都會在數組中的每個元素上執行addKernel這個核函數。

2.2.線程層次

  threadIdx是一個3元組,因此線程可以被一維、二維和三維的threadIdx標識,形成一維、二維和三維的線程塊。

  線程的索引和ID之間的關係:對於一維的線程塊,索引和ID是相同的;對於大小為(Dx,Dy)的二維的線程塊,索引為(x,y),而ID為x+y*Dx;對於大小為(Dx,Dy,Dz)的三維線程塊,索引為(x,y,z),ID為(x+y*Dx+z*Dx*Dy)。

  例子,二維矩陣加,N*N大小的A和B相加,結果存入C。

  

// Kernel definition__global__ void MatAdd(float A[N][N], float B[N][N],float C[N][N]){    int i = threadIdx.x;    int j = threadIdx.y;    C[i][j] = A[i][j] + B[i][j];}int main(){    ...    // Kernel invocation with one block of N * N * 1 threads    int numBlocks = 1;    dim3 threadsPerBlock(N, N);    MatAdd<<<numBlocks, threadsPerBlock>>>(A, B, C);    ...}

  其中,因為一個block的線程一般會在同一個處理核心中,並且共用有限的記憶體,所以一個塊的線程的個數是有限制的。在當前的GPU,塊中的線程數目最大為1024。

  然而,一個核函數可以在多個相同大小的線程塊中執行,所以總的線程數等於線程塊的個數乘以每個線程塊中線程的個數。

  線程塊被組織進一維、二維或者三維的grid中,6所示。

圖6 擁有多個線程塊的grid

  調用核函數的時候,可以通過<<<...>>>指定每個線程塊中線程的個數以及每個grid中線程塊的個數,<<<...>>>的類型可以為int何dim3。核函數中可以通過內建的變數blockIdx得到grid中的每個線程塊的索引。同時可以通過blockDim獲得每個線程塊的維數。

  例子,擴充先前的矩陣加的例子為多個線程塊的。

// Kernel definition__global__ void MatAdd(float A[N][N], float B[N][N],float C[N][N]){    int i = blockIdx.x * blockDim.x + threadIdx.x;    int j = blockIdx.y * blockDim.y + threadIdx.y;    if (i < N && j < N)    C[i][j] = A[i][j] + B[i][j];}int main(){    ...    // Kernel invocation    dim3 threadsPerBlock(16, 16);    dim3 numBlocks(N / threadsPerBlock.x, N / threadsPerBlock.y);    MatAdd<<<numBlocks, threadsPerBlock>>>(A, B, C);    ...}

  其中,線程塊的大小為16*16,總共有256個線程。在同一個線程塊中線程可以通過shared memory(共用記憶體)共用資料。可以使用__syncthreads()函數同步線程對共用記憶體的資料訪問。

2.3.記憶體層次

  執行時,核函數可以擷取多個記憶體空間中的資料,7所示。每個線程有自己的局部記憶體。每個線程塊擁有共用記憶體空間,塊中的每個線程都可以訪問。還有執行核函數的每個線程都可以訪問的全域記憶體空間。

  另外,還有兩個額外的唯讀記憶體空間:常量和紋理記憶體空間。全域、常量和紋理記憶體空間為不同的記憶體用法做了最佳的最佳化。紋理模型提供多種的定址方式。

 

圖7 記憶體層次

2.4.異構編程

  8所示,CUDA編程模型假設CUDA線程執行在一個與主機的C程式分離的裝置上。核函數在GPU上執行,而其他的在CPU上執行。CUDA編程模型同時假設主機和裝置獨立操作它們在DRAM中的記憶體空間。因此,程式調用CUDA運行時(在編程介面這一章描述)管理全域、常量和紋理記憶體空間對核函數的訪問性,運行時包括記憶體配置和回收、主機和裝置之間的記憶體資料的拷貝等。

在主機上執行串列的代碼,而GPU執行並行的核函數

圖8 異構編程

2.5.計算能力

  裝置的計算能力定義為一個主要版本號和一個次的修訂編號。

  相同的主要版本號的GPU擁有相同的核心架構。主版號為5的是Maxwell架構,3為Kepler架構,2為Fermi架構,1為Tesla架構。

  次修訂編號相當於核的不斷改進和新的特性。

  支援CUDA的GPU這一章節列出支援CUDA的所有GPU的計算能力。計算能力這一章節給出每個計算能力的詳細技術規格。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.