1

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

例如,

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

肯定会展开(达到相当大的行程计数,请参阅此答案)。关于什么:

#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,在这种情况下,我将部分回答这个问题。但我更喜欢更权威和基于更广泛经验的东西。

4

1 回答 1

2

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

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

所有这些都在文档的相关部分中进行了非常清楚的讨论。

于 2017-03-01T07:12:36.517 回答