我们对nvcc的#pragma展开的“力量”了解多少?

时间:2017-02-28 23:37:37

标签: cuda compiler-optimization pragma nvcc loop-unrolling

在遇到#pragma unroll指令时,我们对nvcc的展开功能了解多少?它有多复杂?有没有人尝试过越来越复杂的循环结构来看看它放弃了什么?

例如,

#pragma unroll
for(int i = 0; i < constexpr_value; i++) { foo(i); }

肯定会展开(最多相当大的旅行次数,请参阅this answer)。怎么样:

#pragma unroll
for(int i = 0;  i < runtime_variable_value and i < constexpr_value; i++) {
    foo(i); 
}

此处不知道循环行程计数,但它具有恒定的上限,并且可以执行循环的完全展开,并进行一些条件跳转。

然后,怎么样:

template <typename T>
constexpr T simple_min(const T& x, const T& y) { return x < y ? x : y; }

#pragma unroll
for(int i = 0;  i < simple_min(runtime_variable_value, constexpr_value); i++) {      
    foo(i); 
}

哪个应该编译成与上面相同的东西?

注意:如果您打算回答“进行自己的实验”,那么 - 我打算这样做,至少在我的例子中,如果没有人知道一般的答案,请查看PTX在这种情况下,我将部分回答这个问题。但我更喜欢一些更具权威性并且基于更广泛经验的东西。

1 个答案:

答案 0 :(得分:2)

展开的规则非常简单 - 如果编译器不能将循环行程计数推导为整数常量值,它将不会自动展开循环。在这种情况下,它还会发出警告通知您。

如果您的代码具有非常量循环行程计数,您仍然可以通过在展开编译指示之后添加一个值大于1的整数常量表达式来强制编译器展开(即#pragma unroll 8

所有这一切都在documentation的相关部分中进行了非常清楚的讨论。