3.1 主機與裝置
通常將cpu及其記憶體稱之為主機,gpu及其記憶體稱之為裝置。
如下圖所示,新建乙個nvidia cuda工程,並命名為 「1-helloworld」
之後發現專案裡多了乙個「kernel.cu」的檔案,該檔案內容是乙個經典的向量相加的gpu程式。
可以暫時全部注釋該**,並嘗試編譯執行下面的我們經常見到的程式設計入門示例:
#include
int main()
這看起來和普通的c++程式並沒什麼區別。 這個示例只是為了說明cuda c程式設計和我們熟悉的標準c在很大程度上是沒有區別的。 同時,這段程式直接執行在主機上。
接下來,我們看看如何使用gpu來執行**。如下:
#include
__global__ void mkernel(void){}
int main()
與之前的**相比, 這裡主要增加了
_global_為cuda c為標準c增加的修飾符,表示該函式將會交給編譯裝置**的編譯器(nvcc)並最終在裝置上執行。 而main函式則依舊交給系統編譯器(vs2013)。
其實,cuda就是通過直接提供api介面或者在語言層面整合一些新的東西來實現在主機**中呼叫裝置**。
3.2 第乙個gpu程式: 向量相加
下面主要通過**解讀的形式來進行我們的第乙個gpu程式。
程式遵循以下流程:
主機端準備資料 -> 資料複製到gpu記憶體中 -> gpu執行核函式 -> 資料由gpu取回到主機
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include
// 介面函式: 主機**呼叫gpu裝置實現向量加法 c = a + b
cudaerror_t addwithcuda(int *c, const
int *a, const
int *b, unsigned
int size);
// 核函式:每個執行緒負責乙個分量的加法
__global__ void addkernel(int *c, const
int *a, const
int *b)
int main()
; const
int b[arraysize] = ;
int c[arraysize] = ;
// 並行向量相加
cudaerror_t cudastatus = addwithcuda(c, a, b, arraysize);
if (cudastatus != cudasuccess)
printf(" + = \n",
c[0], c[1], c[2], c[3], c[4]);
// cuda裝置重置,以便其它效能檢測和跟蹤工具的執行,如nsight and visual profiler to show complete traces.traces.
cudastatus = cudadevicereset();
if (cudastatus != cudasuccess)
return0;}
// 介面函式實現: 主機**呼叫gpu裝置實現向量加法 c = a + b
cudaerror_t addwithcuda(int *c, const
int *a, const
int *b, unsigned
int size)
// 依次為 c = a + b三個向量在gpu上開闢記憶體 .
cudastatus = cudamalloc((void**)&dev_c, size * sizeof(int));
if (cudastatus != cudasuccess)
cudastatus = cudamalloc((void**)&dev_a, size * sizeof(int));
if (cudastatus != cudasuccess)
cudastatus = cudamalloc((void**)&dev_b, size * sizeof(int));
if (cudastatus != cudasuccess)
// 將向量a和b依次copy進入gpu記憶體中
cudastatus = cudamemcpy(dev_a, a, size * sizeof(int), cudamemcpyhosttodevice);
if (cudastatus != cudasuccess)
cudastatus = cudamemcpy(dev_b, b, size * sizeof(int), cudamemcpyhosttodevice);
if (cudastatus != cudasuccess)
// 執行核函式,執行設定為1個block,每個block中size個執行緒
addkernel<<<1, size>>>(dev_c, dev_a, dev_b);
// 檢查是否出現了錯誤
cudastatus = cudagetlasterror();
if (cudastatus != cudasuccess)
// 停止cpu端線程的執行,直到gpu完成之前cuda的任務,包括kernel函式、資料拷貝等
cudastatus = cudadevicesynchronize();
if (cudastatus != cudasuccess)
// 將計算結果從gpu複製到主機記憶體
cudastatus = cudamemcpy(c, dev_c, size * sizeof(int), cudamemcpydevicetohost);
if (cudastatus != cudasuccess)
error:
cudafree(dev_c);
cudafree(dev_a);
cudafree(dev_b);
return cudastatus;
}
Caffe原始碼學習3 CUDA程式設計
cuda compute unified device architecture 的簡稱,是由nvidia公司創立的基於他們公司生產的圖形處理器gpus graphics processing units,可以通俗的理解為顯示卡 的乙個平行計算平台和程式設計模型。通過cuda,gpus可以很方便地被...
GPU程式設計自學4 CUDA核函式執行引數
在前面的章節中,我們不止一次看到了在呼叫定義的核函式時採用了類似下面的形式 kernel 1,1 param1,param2,中引數的作用是告訴我們該如何啟動核函式 比如如何設定執行緒 下面我們先直接介紹引數概念,然後詳細說明其意義。4.1 核函式執行引數 當我們使用gloabl宣告核函式後 glo...
GPU計算與CUDA程式設計
1.來自nvidia的 cuda 並行程式設計框架是 gpgpu 正規化的一種特定的實現。它提供了gpu程式設計的簡易介面,基於cuda程式設計可以構建基於gpu計算的應用程式。2.cuda 在技術上是一種異構計算環境,也就是說它利用了同時在 cpu 和 gpu 上的協調計算。cuda 架構由主機 ...