- 核函数
kernel<<m,n>>();
其中m表示CUDA运行时需要启动的block,n表示每个block中创建的线程数量,启动的总线程数为m*n;
一个Grid对应一个kernel<<<m,n>>>,通过这种形式可以完成目标线程的索引。 - 修饰符:_global _,含义:告知编译器,函数应该在device 编译,而不在host上。且必须注意—global—函数的返回值必须是void。
cudaMalloc((void**)&dev_c, sizeof(int))
函数,告知CUDA在运行时在device上分配内存。(void**)&dev_c
指针表示指向用于保存新分配内存地址的变量,sizeof(int)
表示内存的大小。cudaFree()
每次程序结束后,需要通过这个函数释放分配的内存。- device与host之间的访问,参数的传递:
cudaMemcpy(dst_a,src_a,sizeof(int),cudaMencpyDeviceToHost)
,最后一个参数代表参数传递的方向。
因此传递的方向可以是:
参数 | 方向 |
---|---|
cudaMencpyHostToDevice | CPU TO GPU |
cudaMencpyDeviceToHost | GPU TO CPU |
cudaMencpyDeviceToDevice | GPU TO GPU |
- 线程协作
对于kernel<<m,n>>();
,参数m和n的大小都有一定的限制(来自硬件的限制)。m即block的数量不超过65535,n即一个block中thread的数量不超过512。因此对于矢量求和时,若矢量长度小于512可以调用int tid = threadIdx.x;
对于长度小于65535的矢量可以调用int tid = blockIdx.x
,但长度位于512–65535,也可以调用int tid = threadIdx.x + blockIdx.x*blockDim.x
进行计算。
上面的blockDim.x
是一个常量,表示block其中一维的线程数量,类似的变量还有gridDim.x
,代表grid每一维的block数量。其中,gridDim.x
是2D的,blockDim.x
是3D的。这种三维索引好像适合计算图像像素之间的运算)
grid 和block通过dim3类定义,dim3可以看成包含3个无符号整数(x, y, z)的结构体变量,在定义是缺省值初始化为1。- 了解硬件架构
通过上述简单概念对GPU和CUDA有一个简单的认识之后,需要了解GPU的硬件架构,如果需要设计一个高性能的并行程序,必然要对GPU的计算过程有一个详细的了解。用图说话
SP是GPU的基本处理单元,kernel启动后,thread即被分配到SP上。负责运行线程上的程序。
SM:多处理器,包含SP以及其他一些硬件结构(如:register, local memory(thread私有的), shared memory(block,global memory(共享,都可访问))等 - 编程模型
SIMD(Single Instruction Multiple Data), 针对GPU—SIMT(Single Instruction Multiple Thread)
编程模式:使用扩展的C语言,多了一些关键词,内置的变量,一些API函数,函数调用形式等
CUDA函数声明:
- 了解硬件架构
执行位置 | 调用位置 | |
---|---|---|
_device_float DeviceFunc() | device | device |
_global_void KernelFunc() | device | host |
_host_float HostFunc() | host | host |