以下是我对CUDA线程执行模式的理解。如果特定线程满足条件,它将执行内核。通常,每个线程的索引和访问都是使用其线程和块ID完成的。但是,当我遇到下面这段代码时,我跌跌撞撞。至于正确性,这段代码给出了完全正确的结果。
__global__ void kernel0(int *a)
{
int b0 = blockIdx.x;
int t0 = threadIdx.x;
__shared__ int shared_a[32][33];
for (int g5 = 0; g5 <= 96; g5 += 32) {
for (int c0 = 0; c0 <= min(31, -32 * b0 + 99); c0 += 1)
for (int c1 = t0; c1 <= min(32, -g5 + 99); c1 += 32)
shared_a[c0][c1] = a[(32 * b0 + c0) * 100 + (g5 + c1)];
__syncthreads();
if (32 * b0 + t0 <= 99)
for (int c2 = 0; c2 <= min(31, -g5 + 98); c2 += 1)
shared_a[t0][c2 + 1] = (shared_a[t0][c2] + 5);
__syncthreads();
if (((t0 + 31) % 32) + g5 <= 98)
for (int c0 = 0; c0 <= min(31, -32 * b0 + 99); c0 += 1)
a[(32 * b0 + c0) * 100 + (((t0 + 31) % 32) + g5 + 1)] = shared_a[c0][((t0 + 31) % 32) + 1];
__syncthreads();
}
}
我的问题是32块的块大小中的哪个thread-id执行前3个for-loop&#39; s?
答案 0 :(得分:1)
简短回答
每个线程都会执行for循环,但只有索引在[0,min(31,-32 * b0 + 99)] [t0,c1&lt; = min(32,-g5 + 99) ]在内部陈述中做一些工作,即
shared_a[c0][c1] = a[(32 * b0 + c0) * 100 + (g5 + c1)]
关于映射机制
您必须为每个线程分配其对应工作的方式是索引。例如,以下语句将仅由每个块的线程0执行:
if( threadIdx.x == 0){
// some code
}
虽然这个只由线程执行,而索引0是一维网格:
if( threadIdx.x + blockIdx.x*blockDim.x == 0){
// some code
}
此代码(来自简单的数组缩减)也可用于说明此类行为:
for( unsigned int s = 1; s < blockDim.x; s *= 2){
int index = 2*s*tid;
if( index < blockDim.x){
sdata[index] += sdata[index + s];
}
__syncthreads();
}
块中的所有线程都执行for循环,并且所有线程都有自己的索引变量值。然后,if语句阻止某些线程执行添加。最后,添加仅由具有线程号“index”的线程执行。
如您所见,这使得一些线程处于空闲状态而其他线程可能需要做很多工作(负载不平衡),因此需要在整个网格中实现均匀的工作负载以最大限度地提高性能。
学习资料。
起初这可能有些令人困惑,所以我建议您阅读CUDA工具包中包含的CUDA C编程指南。使用矩阵 - 矩阵乘法,向量加法和向量约简。
一本非常全面的指南是David B. Kirk和Wen-mei W. Hwu撰写的“大规模并行处理程序编程”一书。