GPU程式設計自學3 CUDA程式初探

2021-08-04 21:57:23 字數 3276 閱讀 8919

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 架構由主機 ...