CUDA Hello World 程式
阿新 • • 發佈:2018-12-26
CUDA(Compute Unified Device Architecture)是NVIDIA(英偉達)公司基於其生產的圖形處理器GPU(Graphics Processing Unit)開發的一個平行計算平臺和程式設計模型。
基於CPU程式設計,程式都是執行在CPU上的;基於GPU編寫的程式,程式執行在GPU上。在原有CPU平臺上新增GPU裝置後,通過增加額外的計算單元,可以有效的提高程式的執行效率。
一般將CPU端叫做Host, 將GPU端叫做Device. 如何寫一個執行在GPU端的Hello world程式呢?
簡單的看了Manual後,可能會這麼寫:
#include <stdio.h> __global__ void hello() { printf("Hello world from device"); } int main() { hello<<<1, 1>>>(); printf("Hello world from host"); return 0; }
將上面檔案命名為helloWorld.cu,用nvcc編譯:
nvcc -o helloWorld helloWorld.cu
執行./helloWorld,發現只會打印出"hello world from host"。
檢視NVIDIA的開發文件,device端的printf其實和裝置端的printf函式是不同的實現,那為什麼include一個標準庫的標頭檔案就可以使用device端的printf函式?其實這是源於cuda實現的一些技術細節,標準庫的標頭檔案只是給出了一個函式原型的提示,當在不同架構的計算機上編譯時,通過函式過載,會呼叫不同的函式,這裡有人給出了詳細解釋)。而device端的輸出其實是輸出到device端的一個環形buffer(超出size後會覆寫之前的內容),要flush到host端,需要採用下面任一操作:
- Kernel launch via <<<>>> or cuLaunchKernel()
- Synchronization via cudaDeviceSynchronize(), cuCtxSynchronize(), cudaStreamSynchronize(), cuStreamSynchronize(),
cudaEventSynchronize(), or cuEventSynchronize(), - Memory copies via any blocking version of cudaMemcpy*() or cuMemcpy*(),
- Module loading/unloading via cuModuleLoad() or cuModuleUnload(),
- Context destruction via cudaDeviceReset() or cuCtxDestroy().
- Prior to executing a stream callback added by cudaStreamAddCallback or cuStreamAddCallback.
這裡,新增cudaDeviceSynchronize(),發現就可以正常輸出了:
#include <stdio.h>
__global__ void hello() {
printf("Hello world from device");
}
int main() {
hello<<<1, 1>>>();
printf("Hello world from host");
cudaDeviceSynchronize();
return 0;
}