#pragma unroll 究竟是做什么的?它会影响线程数吗?

46

我是CUDA的新手,不理解循环展开。我写了一段代码来学习这个技术。

__global__ void kernel(float *b, int size)
{
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
 #pragma unroll
    for(int i=0;i<size;i++)
        b[i]=i;
}

上面是我的内核函数。在 main 中我像下面这样调用它。
int main()
{
    float * a; //host array
    float * b; //device array
    int size=100;

    a=(float*)malloc(size*sizeof(float));
    cudaMalloc((float**)&b,size);
    cudaMemcpy(b, a, size, cudaMemcpyHostToDevice);

    kernel<<<1,size>>>(b,size); //size=100

    cudaMemcpy(a, b, size, cudaMemcpyDeviceToHost);

    for(int i=0;i<size;i++)
        cout<<a[i]<<"\t";

    _getch();

    return 0;
}

这是否意味着我有size*size=10000个线程正在运行程序?当循环展开时,其中的100个是被创建出来的吗?


4
不。这意味着您使用了一个块,并且该块有100个活动线程,从函数参数中传递size到您的CUDA核函数。在您的核函数中,每个这100个线程都会执行for循环100次。我建议您从基础开始逐步学习CUDA,而不是跳到更高级或不太重要的内容,比如循环展开。 - Farzad
@Farsad,谢谢你,你能解释一下#pragma unroll是什么吗? 我认为我可以不使用pragma来执行for循环? - Magzhan Abdibayev
1个回答

59

不是这样的。它意味着您使用一个块调用了CUDA内核,并且该块有100个活动线程。您将大小作为第二个函数参数传递到内核中。在您的内核中,每个这100个线程都会执行for循环100次。

#pragma unroll是一种编译器优化,例如,可以替换像下面这样的代码段:

for ( int i = 0; i < 5; i++ )
    b[i] = i;

随着

b[0] = 0;
b[1] = 1;
b[2] = 2;
b[3] = 3;
b[4] = 4;
通过在循环之前放置#pragma unroll指令。展开循环版本的好处是它对处理器的处理负荷较少。对于for循环版本,在将每个i分配给b[i]之外,还涉及到初始化i,6次评估i<5和5次递增i。而在第二种情况下,它只涉及填充b数组内容(如果稍后使用i,可能还有int i=5;)。展开循环的另一个好处是提高指令级并行性(ILP)。在展开的版本中,处理器可能会有更多的操作推入处理管道而无需担心每次迭代中的for循环条件。
这样的帖子解释了CUDA无法运行时展开循环。在您的情况下,CUDA编译器没有任何提示,表明size将为100,因此不会发生编译时循环展开,因此,如果您强制展开循环,则可能会影响性能。
如果您确定所有执行中的size都为100,则可以像下面这样展开循环:
#pragma unroll
for(int i=0;i<SIZE;i++)  //or simply for(int i=0;i<100;i++)
    b[i]=i;

其中SIZE在编译时已知,使用#define SIZE 100定义。

我建议您在代码中进行适当的CUDA错误检查(解释在此处)。


12
#pragma unroll 也在 编程指南 中有介绍。 - Robert Crovella
1
这主要是因为它会降低您的并行计算性能。当存在分支条件时,线程束不是并行的,这会导致块中的任何线程偏离不同的指令路径,并且会使SIMT架构无效,即所有线程在同一时间和同一位置执行1个指令(寄存器?)。 - yan bellavance
@RobertCrovella 为什么我们需要显式添加这个编译指示?编译器不能自己识别这样的循环吗? - z0lupka
我并没有说过你必须明确添加这个编译指示。我只是链接到文档中的相关部分,以便其他人可以参考文档。如果你点击那个链接并阅读第一句话,你就会得到你问题的答案。 - Robert Crovella

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接