对应《GPU高性能编程CUDA实战中文版》第1-3章笔记。
CUDA开发环境配置
CUDA全称是Compute Unified Device Architecture。
CUDA开发环境配置十分简单,只需要去官网(点击进入)下载对应安装包,解压、安装即可。安装完成后即可使用。
基础概念
我们将CPU以及系统的内存称为主机
,将GPU及其内存称为设备
。在GPU设备上执行的函数通常叫做核函数(Kernel)
。一个简单的例子:
__global__ void kernel(void)
{
//Your code here...
}
int main(void)
{
kernel<<<1,1>>>();
printf("Hello world!\n");
return 0;
}
与我们熟悉的C语言相比,多了两样东西:
- 一个空的函数
kernel()
,并且带有修饰符__global__
(注意是两个下划线,不是一个) - 在
main()
函数中对这个函数的调用,并且带有修饰符«<1,1»>
CUDA C为标准C增加了__global__
这个修饰符,它将告诉编译器,函数
应该编译为在设备而不是主机上运行。在这段代码中,函数kernel()
将被交给编译设备代码的编译器,而main()
函数将被交给主机编译器。
给核函数传递参数
__global__ void add(int a, int b, int *c)
{
*c = a + b;
}
int main()
{
int c;
int * dev_c;
cudaMalloc((void **)&dev_c, sizeof(int));
add <<<1, 1 >>>(2, 7, dev_c);
cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost);
printf("2+7=%d\n", c);
cudaFree(dev_c);
return 0;
}
在本段代码中,定义了一个add()
的核函数,a、b为值传递,c为引用传递。
调用核函数的过程为定义一个指针,为该指针在GPU内存上分配空间,
调用GPU进行计算,将结果由GPU内存拷贝至主机内存,最后释放掉GPU对应的内存。
需要注意的是,不能使用标准的C的free()
函数来释放cudaMalloc()
分配的内存。
要释放cudaMalloc()
分配的内存,需要调用cudaFree()
。
查询设备
可以使用cudaGetDeviceCount()
查询CUDA设备的数量,返回int。调用方式如下:
int count;
cudaGetDeviceCount(&count);
printf("%d\n",count);
在获得设备数后,可对每个设备进行迭代,获取各自的相关信息。
可以利用cudaGetDeviceProperties()
函数获取,返回为cudaDeviceDrop()
类型的数据。
其中包含各种信息。下面代码可以实现对每个设备信息的迭代:
cudaDeviceProp prop;
int count;
cudaGetDeviceCount(&count);
for(int i=0;i<count;i++)
{
cudaGetDeviceProperties(&prop,i);
printf("%s\n",prop.name);
//......Your code......
}
部分设备属性如下:
name
:char,标识设备的ASC字符串,如“GeForce GTX 1080”
totalGlobalMem
:size_t,设备上全局内存的总量,单位为字节
totalConstMem
:size_t,常量内存的总量
major
:int,设备计算功能集(Compute Capability)的主版本号
minor
:int,设备计算功能集的次版本号
deviceOverlap
:boolean,一个布尔类型值,表示设备是否可以同时执行一个
cudaMemory()
调用和一个核函数调用
multiProcessorCount
:int,设备上多处理器的数量
总结
从本质上来说CUDA C只是对标准C进行了语言级的扩展,通过增加
一些修饰符使我们可以指定哪些代码在设备上运行,哪些代码在
主机上运行。在函数前添加关键字_global_
将告诉编译器把
该函数放在GPU上运行。与C类似,CUDA C中依然有cudaMalloc()
、
cudaMemcpy()
、cudaFree()
,分别实现分配设备内存,在设备
和主机之间复制数据,以及释放内存等操作。
本文作者原创,未经许可不得转载,谢谢配合