一直在找cuda的檔案組織圖文章,但是,適合自己業務開發的感覺描述不清晰,下面是對自己的cuda工程的一個小結。語言群組織架構是工程的一個良好結構,一個適合本業務開發的語言群組織架構,對開發人員理解和閱讀程式有著良好的協助。瞭解到cuda是c的一個子集,用的是nvcc編譯環境,針對某領域對cuda的應用,規範自己的程式架構。
開發環境:vs2008+cuda5.0
工程流程如下:
1 建立cuda項目
2 建立main.cpp作為程式入口,用的是c++編譯器。
3 建立業務層級.h和.cpp,業務封裝在.h檔案的class中。
比如:
class A{
public:
fun();
}
4 建立計算層級的.h或.cuh和.cu,其實這裡標頭檔可以不建立,而直接在.cu檔案中定義,然後聲明成extern,但是為了統一函式宣告,都用了標頭檔。
比如:
////////////////calc.cuh
#ifndef _CU_H_
#define _CU_H_
calcfun();
#endif
////////////////calc.cu
#include "calc.cuh"
__device__ kernelsubcalc(){}
__global__ kernelcalc(){kernelsubcalc();}
calcfun()
{
kernelcalc<<<,>>>();
}
注意一個原則:與裝置有關的關鍵字比如global和<<<>>>符號必須只能出現在.cu檔案中。
5 封裝裝置操作函數
cuda的裝置操作很多,為了編程的方便,通常封裝自己常用的操作。
比如我封裝的一個裝置記憶體操作函數:
#ifndef _GUPMEM_
#define _GUPMEM_
#include "common.h"
// 分配裝置記憶體
template
int GPUMalloc(T **t, size_t n)
{
HANDLE_ERROR( cudaMalloc( (void**)&*t, n * sizeof(T) ) );
printf("gpu malloc right!\n");
return 0;
}
// 釋放裝置記憶體
template
class GPUGuard
{
public:
GPUGuard(T *t):m_t(t){}
~GPUGuard(){
cudaFree(m_t);
printf("cuda mem free\n");
}
private:
T *m_t;
};
// 記憶體在裝置與主機之間的拷貝
enum CopyModel{
HOST2DEV, // 主機->裝置
DEV2HOST // 裝置->主機
};
template
int MemCopy(T **dev_t, T **host_t, size_t n, CopyModel model)
{
if(model == HOST2DEV)
{
printf("host to dev\n");
HANDLE_ERROR( cudaMemcpy( *dev_t, *host_t, n * sizeof(T), cudaMemcpyHostToDevice ) );
}
else if (model == DEV2HOST)
{
printf("dev to host\n");
HANDLE_ERROR( cudaMemcpy( *host_t, *dev_t, n * sizeof(T), cudaMemcpyDeviceToHost ) );
}
else
{
printf("copy model error!\n");
return -1;
}
return 0;
};
#endif
裝置操作函數的使用就很簡單:
int *dev_a;
GPUGuardg1(dev_a);
if(GPUMalloc(&dev_a, N) < 0)
return -1;
if(MemCopy(&dev_a, &a, N, HOST2DEV) < 0)
return -1;
總結:
我需要的cuda工程檔案有.cpp .h .cu,並行計算放在cu中,其他業務放在.cpp中。