是否可以在三角形区域上展开循环,例如:
for (int i = 0; i < ROW_LENGTH; i++)
{
for (int j = 0; j < i; j++)
{
// Some array operation here
}
}
其中ROW_LENGTH是在编译时定义的常量?现在看来,我不认为这是可能的,因为我在程序执行时正在改变(更重要的是,它在编译时不是常量)。我想你可以将2D数组视为一维数组,从0迭代到(ROW_LENGTH ^ 2)/ 2,然后尝试几个数学技巧来获取索引,但是额外的操作会破坏循环展开的目的。第一名。
答案 0 :(得分:2)
CUDA 7.0编译器将在我的测试中展开它。循环索引在编译时都是已知的,所以没有理由不能这样做。
考虑以下代码,将a的三角形部分设置为1。
#define ROW_LENGTH 4
__global__ void triUnrollTest1(float* a) {
#pragma unroll
for (int i = 0; i < ROW_LENGTH; i++)
{
#pragma unroll
for (int j = 0; j < i; j++)
{
a[i * ROW_LENGTH + j] = 1.f;
}
}
}
仅{4}我们可以自己展开:
ROW_LENGTH
使用CUDA 7.0编译SM 35:
__global__ void triUnrollTest2(float* a) {
a[1 * ROW_LENGTH + 0] = 1.f;
a[2 * ROW_LENGTH + 0] = 1.f;
a[2 * ROW_LENGTH + 1] = 1.f;
a[3 * ROW_LENGTH + 0] = 1.f;
a[3 * ROW_LENGTH + 1] = 1.f;
a[3 * ROW_LENGTH + 2] = 1.f;
}
然后转储SASS汇编程序:
nvcc -arch=sm_35 -c triUnroll.cu
我们得到:
cuobjdump --dump-sass triUnroll.o
显然两者都是相同的并且很好地展开。有趣的是,当我第一次使用6.5编译时,编译器没有展开,所以我想在这种情况下更新是值得的!