CUDA编程结构、存储管理、线程管理杂谈
CUDA编程结构
一个异构环境,通常有多个CPU多个GPU,他们都通过PCIe总线相互通信,也是通过PCIe总线分隔开的。所以要区分一下两种设备的内存:
1)主机:CPU及其内存
2)设备:GPU及其内存
这两个内存从硬件到软件都是隔离的(CUDA6.0 以后支持统一寻址),目前先不研究统一寻址,现在还是用内存来回拷贝的方法来编写调试程序,以巩固大家对两个内存隔离这个事实的理解。
一个完整的CUDA应用可能的执行顺序,如图10-9所示。
图10-9 一个完整的CUDA应用可能的执行顺序
从host的串行到调用核函数(核函数被调用后控制马上归还主机线程,也就是在第一个并行代码执行时,很有可能第二段host代码已经开始同步执行了)。
接下来的研究层次是:
1)内存
2)线程
3)核函数
①启动核函数
②编写核函数
③验证核函数
4)错误处理
内存管理
内存管理在传统串行程序是非常常见的,寄存器空间,栈空间内的内存由机器自己管理,堆空间由用户控制分配和释放,CUDA程序同样,只是CUDA提供的API可以分配管理设备上的内存,当然也可以用CDUA管理主机上的内存,主机上的传统标准库也能完成主机内存管理。
一些主机API和CUDA C的API的对比,见表10-1。
表10-1 一些主机API和CUDA C的API的对比
标准C函数 |
CUDA C 函数 |
说明 |
malloc |
cudaMalloc |
内存分配 |
memcpy |
cudaMemcpy |
内存复制 |
memset |
cudaMemset |
内存设置 |
free |
cudaFree |
释放内存 |
依靠下面两个内置结构体确定线程标号: 1)blockIdx(线程块在线程网格内的位置索引) 2)threadIdx(线程在线程块内的位置索引) 这里的Idx是index的缩写(之前一直以为是identity x的缩写),这两个内置结构体基于 uint3 定义,包含三个无符号整数的结构,通过三个字段来指定: 1)blockIdx.x 2)blockIdx.y 3)blockIdx.z 4)threadIdx.x 5)threadIdx.y 6)threadIdx.z 上面这两个是坐标,当然要有同样对应的两个结构体来保存其范围,也就是blockIdx中三个字段的范围threadIdx中三个字段的范围: 1)blockDim 2)gridDim 他们是dim3类型(基于uint3定义的数据结构)的变量,也包含三个字段x,y,z. 1)blockDim.x 2)blockDim.y 3)blockDim.z 网格和块的维度一般是二维和三维的,也就是说一个网格通常被分成二维的块,而每个块常被分成三维的线程。
注意:dim3是手工定义的,主机端可见。uint3是设备端在执行的时候可见的,不可以在核函数运行时修改,初始化完成后uint3值就不变了。他们是有区别的!这一点必须要注意。 下面有一段代码,块的索引和维度: /* *1_check_dimension */ #include <cuda_runtime.h> #include <stdio.h> __global__ void checkIndex(void) { printf("threadIdx:(%d,%d,%d) blockIdx:(%d,%d,%d) blockDim:(%d,%d,%d)\ gridDim(%d,%d,%d)\n",threadIdx.x,threadIdx.y,threadIdx.z, blockIdx.x,blockIdx.y,blockIdx.z,blockDim.x,blockDim.y,blockDim.z, gridDim.x,gridDim.y,gridDim.z); } int main(int argc,char **argv) { int nElem=6; dim3 block(3); dim3 grid((nElem+block.x-1)/block.x); printf("grid.x %d grid.y %d grid.z %d\n",grid.x,grid.y,grid.z); printf("block.x %d block.y %d block.z %d\n",block.x,block.y,block.z); checkIndex<<<grid,block>>>(); cudaDeviceReset(); return 0; } 接下来这段代码是检查网格和块的大小的: /* *2_grid_block */ #include <cuda_runtime.h> #include <stdio.h> int main(int argc,char ** argv) { int nElem=1024; dim3 block(1024); dim3 grid((nElem-1)/block.x+1); printf("grid.x %d block.x %d\n",grid.x,block.x); block.x=512; grid.x=(nElem-1)/block.x+1; printf("grid.x %d block.x %d\n",grid.x,block.x); block.x=256; grid.x=(nElem-1)/block.x+1; printf("grid.x %d block.x %d\n",grid.x,block.x); block.x=128; grid.x=(nElem-1)/block.x+1; printf("grid.x %d block.x %d\n",grid.x,block.x); cudaDeviceReset(); return 0; } 标签:存储管理,res,grid,CUDA,线程,block,内存 From: https://www.cnblogs.com/wujianming-110117/p/18386441