您的示例内核是完全串行的,无论如何都不是循环展开的有用的现实世界用例,但是让我们将自己限制在编译器将执行多少循环展开的问题上。
这是您的内核的可编译版本,带有一些模板装饰:
template<int LIMIT>
__global__ void
test_kernel( const float* B, const float* C, float* A_out, int array_size)
{
int j = threadIdx.x + blockIdx.x * blockDim.x;
if (j < array_size) {
#pragma unroll
for (int i = 0; i < LIMIT; i++) {
A_out[i] = B[i] + C[i];
}
}
}
template __global__ void test_kernel<4>(const float*, const float*, float*, int);
template __global__ void test_kernel<64>(const float*, const float*, float*, int);
template __global__ void test_kernel<256>(const float*, const float*, float*, int);
template __global__ void test_kernel<1024>(const float*, const float*, float*, int);
template __global__ void test_kernel<4096>(const float*, const float*, float*, int);
template __global__ void test_kernel<8192>(const float*, const float*, float*, int);
您可以将其编译为 PTX 并亲自查看(至少使用 CUDA 7 版本编译器和默认的计算能力 2.0 目标架构),内核LIMIT=4096
完全展开。案件LIMIT=8192
没有展开。如果您比我更有耐心,您可能可以使用模板来找到此代码的确切编译器限制,尽管我怀疑这对了解特别有指导意义。
您还可以通过编译器亲自看到所有大量展开的版本都使用相同数量的寄存器(因为内核的琐碎性质)。