简述
利用GPU显卡硬件,进行cuda C++编程,加速C++程序,适合高度并行计算的情况
环境配置
1.安装显卡驱动
2.VS2019设置
右击工程——>生成依赖项——>生成自定义 ,将对话框中CUDA前面的勾打上
添加CUDA程序文件,后缀名为.cu
右击cu文件——>属性,在 常规——>项类型 里面选择CUDA C/C++
内容
1.常用概念
将CPU的内存称为主机,Host
将GPU的显示内存称为设备,Device
通过GPU的一个核进行处理
由多个线程组成线程块,各block是并行执行的,block间无法通信,无执行顺序
由多个线程块组成的线程网格
是在GPU上执行的函数,核函数用__global__符号声明,每个线程都会执行核函数
用__shared__关键字表示,同一个线程块内的所有线程共享该内存区域,使用__syncthreads()控制线程同步
2.运行方式
执行<<< >>>配置指定线程运行方式,第一个参数是线程网格维度(线程块的数目),第二个参数是块维度(每个块中线程的数目);
线程分布以列为主序(从上往下)
dim3是三维数据结构,对应x(列数),y(行数),z(z默认为1),可使用亍一维、二维或三维的索引来标识线程,构成一维、二维或三维线程块;
threadIdx,是获取线程thread的ID索引;如果线程是一维的那么就取threadIdx.x,二维的还可以多取到一个值threadIdx.y,以此类推到三维threadIdx.z;
blockIdx,线程块的ID索引;同样有blockIdx.x,blockIdx.y,blockIdx.z
blockDim,线程块的维度,同样有blockDim.x,blockDim.y,blockDim.z
gridDim,线程格的维度,同样有gridDim.x,gridDim.y,gridDim.z
3.cu文件调用
C++不能直接调用核函数,C语言可直接调用CUDA核函数;用extern "C"可让C++函数调用
4.CUDA编程案例指引
(1)内存初始化:开辟GPU(设备Device)内存空间;
GPUCAL::GPUCAL(int imgArrayrow, int imgArraycol)
{
cublasStatus_t status = cublasCreate(&cuHandle);
if (status != CUBLAS_STATUS_SUCCESS)
{
if (status == CUBLAS_STATUS_NOT_INITIALIZED) {
std::cout << "CUBLAS 对象实例化出错" << std::endl;
}
return;
}
imgArrayRow = imgArrayrow;
imgArrayCol = imgArraycol;
result = (int*)malloc(RESULTSIZE * sizeof(int));
cudaMalloc((void**)&dimgArray, imgArrayRow * imgArrayCol * sizeof(double));
cudaMalloc((void**)&dresult, RESULTSIZE * sizeof(int));
}
(2)拷贝数据:拷贝主机(Host)内存到设备(Device)内存;
cudaMemcpy(dimgArray, imgArray, imgArrayRow * imgArrayCol * sizeof(double), cudaMemcpyHostToDevice);
(3)多线程运算:调用cu文件的核函数进行多线程处理
void GPUCAL::MatCal(double* imgArray, int* result, double upper, double lower)
{
cudaMemcpy(dimgArray, imgArray, imgArrayRow * imgArrayCol * sizeof(double), cudaMemcpyHostToDevice);
auto starttime = system_clock::now();
SearchDefectFunc(dimgArray, imgArrayRow, imgArrayCol, upper, lower, dresult);
cudaMemcpy(result, dresult, RESULTSIZE * sizeof(int), cudaMemcpyDeviceToHost);
duration<double> dif = system_clock::now() - starttime;
std::cout << "GPU运算并取回所耗时间为:" << dif.count() << "s" << std::endl;
//for (int i = 0; i < 10; i++) {
// std::cout << result[i] << " ";
// std::cout << "dresult" << std::endl;
//}
}
(4)内存释放:回收释放开辟的设备(Device)空间和主机(Host)空间
GPUCAL::~GPUCAL(void)
{
free(result);
result = NULL;
cudaFree(dresult);
std::cout << "free GPU memory" << std::endl;
}