本篇博文僅實現hello world,先看到效果,具體細節將在后續博文解釋。
准備
如果你是第一次使用CUDA,在Linux下可以使用下面的命令來檢查CUDA編譯器是否安裝正確:
$ which nvcc
一般,該指令輸出為:
/usr/local/cuda/bin/nvcc
另外,你可能還需要檢查下你機器上的GPU型號,可以使用給下面的命令查詢:
$ ls -l /dev/nv*
可能的輸出為:
crw-rw-rw- 1 root root 195, 0 Jul 3 13:44 /dev/nvidia0
crw-rw-rw- 1 root root 195, 1 Jul 3 13:44 /dev/nvidia1
crw-rw-rw- 1 root root 195, 255 Jul 3 13:44 /dev/nvidiactl
crw-rw---- 1 root root 10, 144 Jul 3 13:39 /dev/nvram
以上輸出顯示這里有兩個GPU顯卡安裝在機器上。
寫一段CUDA程序的基本過程為:
- 創建源文件,以”.cu”為后綴。
- 用nvcc編譯程序。
- 命令行運行。
代碼
首先,為了對比,先寫一段簡單的C程序輸出hello world:
#include <stdio.h> iint main(void){ printf(“helllo world!\n”); }
然后是我們所謂的kernel function(即CUDA代碼):
__global__ void helloFromGpu(void){ printf(“hello world form GPU!\\n”); }
限定符__global__告訴編譯器這個function將由CPU調用在GPU上執行,其調用形式為:
helloFromGPU<<<1,10>>>();
一個kernel是由一組線程執行,所有線程執行相同的代碼。上面一行三對尖括號中的1和10 表明了該function將有10個線程,具體含義之后博文中會詳述。下面是完整代碼:
#include <stdio.h>
__global__ void helloFromGPU (void) { printf(“Hello World from GPU!\n”); } int main(void) { // hello from cpu printf(“Hello World from CPU!\n”); helloFromGPU <<<1, 10>>>(); cudaDeviceReset(); return 0; }
這里順便提及下,我們將CPU端稱為host,GPU端稱為device。
cudaDeviceReset()用來顯式的摧毀清理CUDA程序占用的資源。現在用下面的命令編譯:
$nvcc –arch sm_20 hello.cu –o hello
-arch sm_20是用來指定編譯器使用Fermi架構產生device代碼。編譯成功后執行$ ./hello:
Hello World from CPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
一個典型的CUDA程序結構包含五個主要步驟:
- 分配GPU空間。
- 將數據從CPU端復制到GPU端。
- 調用CUDA kernel來執行計算。
- 計算完成后將數據從GPU拷貝回CPU。
- 清理GPU內存空間。
參考書:《professional cuda c programming》
NVIDIA CUDA板塊:https://developer.nvidia.com/cuda-zone