您的示例内核完全串行化,无法在实际应用中使用循环展开,但让我们局限于编译器将执行多少循环展开的问题。
以下是添加了一些模板修饰符的可编译版本的内核:
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
情况未展开。如果你比我更有耐心,可以尝试使用模板来查找此代码的确切编译器限制,但我认为了解这一点并不特别有教育意义。
通过编译器,你还可以自己看到所有重复展开版本使用相同数量的寄存器(因为内核的基本性质)。
A
、B
和C
是什么,它们存储在哪里?为什么循环完全串行?您希望从展开完全串行的循环(看起来像线程本地变量)中获得什么优势? - talonmiestest_kernel<<<1, 1>>>(d_idata_B, d_idataC, d_odataA);
的方式进行调用。 - Blizzard