今天学习了CUDA编程中关于线程的知识,这里做下笔记并分享给大家。
CUDA并行执行具有分层结构。每次内核启动时可被切分成多个并行执行的块,每个块又可以进一步被切分成多个线程,这也就是我们常说的内核函数配置参数:块数以及每个块的线程数。
并行执行的方式有多种,可以启动多个并行的块,每个块启动1个线程;也可以启动1个块,这个块启动多个线程;一般用的最多的内核参数配置是启动多个并行的块,每个块也启动多个线程,但是设备中每个块可以启动的线程数量是有上限的(1024个线程),这点要尤其注意。
当启动多个并行块,每个块也启动多个线程时,在内核函数中线程索引计算公式:
线 程 索 引 = 当 前 块 线 程 索 引 ( t h r e a d I d x . x ) + 当 前 块 索 引 ( b l o c k I d x . x ) ∗ 每 块 线 程 数 ( b l o c k D i m . x ) 线程索引 = 当前块线程索引(threadIdx.x) + 当前块索引(blockIdx.x)* 每块线程数(blockDim.x) 线程索引=当前块线程索引(threadIdx.x)+当前块索引(blockIdx.x)∗每块线程数(blockDim.x)
#include
#include
#include
#include
#include
#define N 10000
/*
Block0: thread0 thread1 thread2
Block1: thread0 thread1 thread2
Block2: thread0 thread1 thread2
*/
__global__ void GpuAdd(int* d_a, int* d_b, int* d_c)
{
//线程ID = 当前线程ID + 当前块ID*每块线程数
int tid = threadIdx.x + blockIdx.x * blockDim.x;
// 当N远大于设备线程总数时,通过while循环,步长为所有块的线程总数,这样一个线程就可以执行多个操作,最终达到总数N
while (tid < N)
{
d_c[tid] = d_a[tid] + d_b[tid];
// 循环步长: 每个块的线程数 * 块数
tid += blockDim.x * gridDim.x;
}
}
int main()
{
//定义主机(CPU, h_)变量和设备(GPU, d_)变量
int h_a[N], h_b[N], h_c[N];
int *d_a, *d_b, *d_c;
//在GPU设备上分配全局内存
cudaMalloc(&d_a, N * sizeof(int));
cudaMalloc(&d_b, N * sizeof(int));
cudaMalloc(&d_c, N * sizeof(int));
//初始化主机数组
for (int i = 0; i < N; i++)
{
h_a[i] = 2 * i;
h_b[i] = i;
}
//将主机内存数据拷贝到设备内存中
cudaMemcpy(d_a, h_a, N * sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(d_b, h_b, N * sizeof(int), cudaMemcpyHostToDevice);
//启动核函数
GpuAdd << <512, 512 >> > (d_a, d_b, d_c);
cudaMemcpy(h_c, d_c, N * sizeof(int), cudaMemcpyDeviceToHost);
//保证所有内核线程都执行完成
cudaDeviceSynchronize();
int correct = 1;
printf("Vector addition on GPU \n");
for (int i = 0; i < N; i++)
{
if (h_a[i] + h_b[i] != h_c[i])
{
correct = 0;
break;
}
}
if (correct == 1)
{
printf("GPU has computed Sum Correctly!\n");
}
else
{
printf("There is an Error in GPU Computation\n");
}
//释放设备内存
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
return 0;
}
CUDA并行执行的线程知识介绍就到这里了,内容很少,但是很精,希望对大家有启发!
《基于GPU加速的计算机视觉编程》