#pragma unroll 指令到底做了什麼事情

參考原廠手冊的說法我還是不太清楚這個指令做了什麼事情

#pragma unroll 2
for(int i=0;i<6;i++)
sum += array[i] ;

我一直以為加了#pragma unroll 2會自動變成嗎

for(int i=0;i<3;i++)
{
sum1 += array[i] ;
}

for(int i=3;i<6;i++)
{
sum2 += array[i] ;
}
sum = sum1 +sum2;


如果是#pragma unroll 6

sum =  array[0] + array[1] + array[2] +  array[3] + array[4] + array[5];

我自己有試過手動指令層級的展開

for(int i=0;i<3;i++)
{
sum1 += array[i] ;
sum2 += array[i+1] ;
}
sum = sum1 +sum2;

效果似乎會比#pragma unroll N還要好很多,因此我就不太清楚他做了什麼

上面只是舉例而已。

我的經驗是當for i = 1 : N 時做 #pragma unroll N 不見得會比#pragma unroll N/k 還要好 (mod(N,k)=0)

反而是自己先手動做k次的展開後再加上#pragma unroll N/k 效果會最好

我想請問一下再使用#pragma unroll N 時有沒有一個比較確切的依據或準則可以參考?

又或者我有兩層for迴圈那要哪一層去做#pragma unroll N ?

LZ您好:

1:#pragma unroll n指的是指的是展开n次循环,若原来的循环次数为n*k次,那么unroll n之后,每次循环将计算之前循环n次的内容,总的循环次数变成k次。因为每次循环有固定的指令开销,所以这样减少了循环判断次数,增加了实际计算的比例。对于循环体很小的循环而言有利于提升性能。

2:因为1:,所以您上文中对unroll 2的考虑是不正确的,你那样还是两个循环,你那个写法有些像CPU上的规约做法,两个线程各维护一个循环,计算一个自己的相加结果,而不是展开循环。

3:如果您的例子中的unroll 6,那么相当于直接将6个数据相加起来,但是具体计算的格式可能编译器还有一定的自己的安排。

另外,编译器对于预编译指令,仅作为参考,会综合多个因素给出最后的编译结果。以及您还可以将编译好的exe文件中的汇编码dump出来,以观察编译器究竟采取了何种选择。

大致如此,供您参考。

祝您编码顺利~

後來我有在CUDA C BEST PRACTICES GUIDE找到一些資料,也感謝版主的說明

不客气的,欢迎您常来论坛讨论问题。

祝您编码顺利~