1. 程式人生 > >cpp檔案呼叫CUDA .cu檔案實現顯示卡加速相關程式設計

cpp檔案呼叫CUDA .cu檔案實現顯示卡加速相關程式設計

入門cuda遇到的不錯點撥文,故轉載如下:

本篇文章談的是cpp檔案如何呼叫CUDA的.cu檔案實現顯示卡加速的相關程式設計。當然,這是在預設已經配置好CUDA的情況下進行的,如果對於如何配置CUDA還有疑問可以看之前寫的這一篇文章。另外,現在CUDA已經放出了支援VS2013的6.5版本,所以還是建議用最新的,畢竟VS2013好用太多,配置起來也沒什麼區別。關於那篇配置文章,並沒有解決CUDA相關函式偶有錯誤提示的問題,雖然對於編譯沒有影響,但是對於有強迫症的人來說還是比較糾結的,本人研究過後會更新,望周知。

    關於如何通過cpp檔案呼叫CUDA的.cu檔案實現顯示卡加速相關程式設計的問題,有兩種方法。本篇先談的是根據VS2013模板建立CUDA工程(安裝6.5版本CUDA後可看到)然後再加入cpp檔案的這一種方法。至於另外的在MFC或者win32工程等新增.cu檔案再進行呼叫這種其實本質上是差不多的,會比較麻煩,本人後面有時間再更新。

    在主題開始之前,先說下如何呼叫CUDA進行顯示卡加速,其實大的方向是十分簡單的。流程大致如下:

    初始化顯示卡記憶體->將主機待處理的記憶體資料拷貝到顯示卡記憶體中->利用顯示卡處理相關的資料->將處理完成的顯示卡記憶體資料拷回主機記憶體

    OK,下面進入主題

    首先建立CUDA工程,工程建立完成之後會有一個.cu檔案,將檔案的內容替換成如下內容
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "main.h"

 inline void checkCudaErrors(cudaError err)//錯誤處理函式
 {
	   if (cudaSuccess != err)
		{
		    fprintf(stderr, "CUDA Runtime API error: %s.\n", cudaGetErrorString(err));
		    return;
		}
 }

__global__ void add(int *a,int *b,int *c)//處理核函式
{
	int tid = blockIdx.x*blockDim.x+threadIdx.x;
	for (size_t k = 0; k < 50000; k++)
	{
		c[tid] = a[tid] + b[tid];
	}
}

extern "C" int runtest(int *host_a, int *host_b, int *host_c)
{
	int *dev_a, *dev_b, *dev_c;
	
	checkCudaErrors(cudaMalloc((void**)&dev_a, sizeof(int)* datasize));//分配顯示卡記憶體
	checkCudaErrors(cudaMalloc((void**)&dev_b, sizeof(int)* datasize));
	checkCudaErrors(cudaMalloc((void**)&dev_c, sizeof(int)* datasize));
	
	checkCudaErrors(cudaMemcpy(dev_a, host_a, sizeof(int)* datasize, cudaMemcpyHostToDevice));//將主機待處理資料記憶體塊複製到顯示卡記憶體中
	checkCudaErrors(cudaMemcpy(dev_b, host_b, sizeof(int)* datasize, cudaMemcpyHostToDevice));

	add << <datasize / 100, 100 >> >(dev_a, dev_b, dev_c);//呼叫顯示卡處理資料
	checkCudaErrors(cudaMemcpy(host_c, dev_c, sizeof(int)* datasize, cudaMemcpyDeviceToHost));//將顯示卡處理完資料拷回來

	cudaFree(dev_a);//清理顯示卡記憶體
	cudaFree(dev_b);
	cudaFree(dev_c);
	return 0;
}
    然後在工程中新增main.h檔案,新增如下內容
#include<time.h>//時間相關標頭檔案,可用其中函式計算影象處理速度  
#include <iostream>
#define datasize 50000
    下面新增main的實現檔案cpp,在cpp中實現對於CUDA的.cu檔案的呼叫。內容如下
#include "main.h"
extern "C" int runtest(int *host_a, int *host_b, int *host_c);//顯示卡處理函式

int main()
{
	int a[datasize], b[datasize], c[datasize];
	for (size_t i = 0; i < datasize; i++)
	{
		a[i] = i;
		b[i] = i*i;
	}

	long now1 = clock();//儲存影象處理開始時間  
	runtest(a,b,c);//呼叫顯示卡加速
	printf("GPU執行時間為:%dms\n", int(((double)(clock() - now1)) / CLOCKS_PER_SEC * 1000));//輸出GPU處理時間

	long now2 = clock();//儲存影象處理開始時間  
	for (size_t i = 0; i < datasize; i++)
	{
		for (size_t k = 0; k < 50000; k++)
		{
			c[i] = (a[i] + b[i]);
		}
	}
	printf("CPU執行時間為:%dms\n", int(((double)(clock() - now2)) / CLOCKS_PER_SEC * 1000));//輸出GPU處理時間


	/*for (size_t i = 0; i < 100; i++)//檢視計算結果
	{
		printf("%d+%d=%d\n", a[i], b[i], c[i]);
	}*/

	getchar();
	return 0;
}
    需要注意的是,在用來被呼叫的CUDA函式中要加上extern "C" 的宣告,並在cpp檔案中進行宣告(extern "C" int runtest(int *host_a, int *host_b, int *host_c);)後再呼叫。

    到此本篇的第一大部分就做完了,編譯執行可以看到GPU在處理複雜平行計算的時候的確比CPU快的多。關於前面提到的另外一種方法下次再談吧,假期要結束了,額。。。

    好吧,距上面文章完成已經半年之久,來填坑了,另一種方法的部落格地址在這裡