cuda,利用GPU来实现高速计算。对程序中一些函数含义的记录
cudaSetDevice(0);
//一个设备必须在任何__global__函数或者所有来自附录D 的任何函数调用之前选择;
//否则,device 0 自动地被选择,并且所有随后的设备选择将是无效的。
//0表示能搜索到的第一个设备号,如果有多个设备,则编号为0,1,2...
cudaDeviceSynchronize()
//该方法将停止CPU端线程的执行,直到GPU端完成之前CUDA的任务;
//主机和设备之间传递数据
//注意:该函数是同步执行函数,
//在未完成数据的转移操作之前会锁死井一直占有CPU进程的控制权,
//所以不用再添加cudaDeviceSynchronize()函数
cudaMemcpy(d_A,h_A,nBytes,cudaMemcpyHostToDevice) //主机到设备
cudaMemcpy(h_A,d_A,nBytes,cudaMemcpyDeviceToHost) //设备到主机
cuda里的打印输出
- cuda里不能用c++的cout;
- 使用printf,打印某个线程下的输出信息
#include <cstdio> //printf函数所需头文件
const int tid = blockIdx.x*blockDim.x+ threadIdx.x;// 计算当前执行的线程id
if (tid == 99)
{
printf("curctpos: %f %f %f\n", curPos.x, curPos.y, curPos.z);
}
GPU的线程管理
参考:谭升的博客(face2ai.com/CUDA-F-2-0-…)
一个核函数只能有一个grid,一个grid可以有很多个块(block),每个块可以有很多的线程(thread),这种分层的组织结构使得并行过程更加自如灵活。
线程编号
- blockIdx(线程块在线程网格内的位置索引,即当前 block 在 grid 中的坐标,可能从1维到3维)
- blockIdx.x
- blockIdx.y
- blockIdx.z
- threadIdx(线程在线程块内的位置索引,当前 thread 在 block 中的坐标,可能从1维到3维)
- threadIdx.x
- threadIdx.y
- threadIdx.z
- blockDim(范围,即每个block中有多少thread)
- blockDim.x
- blockDim.y
- blockDim.z
- gridDim(范围,即每个grid有多少block)
线程的id计算:
- 1 grid, 1 block
-blockSize = blockDim.x
- blockId = blockIdx.x
- threadId = threadIdx.x
核函数
kernel_name<<<grid,block>>>(argument list);
kernel_name<<<4,8>>>(argument list)指令的线程布局为:blockIdx.x 0,1,2,3;threadIdx.x,0,1,2,3,4,5,6,7
当主机启动了核函数,控制权马上回到主机,而不是主机等待设备完成核函数的运行
想要主机等待设备端执行可以用下面这个指令:
cudaDeviceSynchronize(void);