cuda控制分歧

时间:2010-11-05 03:47:23

标签: cuda

说我有3个共享内存阵列:a b c。我不确定跟随线程安排是否会导致控制分歧,

if (threadIdx < 64)
{
    if (threadIdx == 1)
        for (int i = 0; i < N; i++)
            c += a[threadIdx]*a[threadIdx];
    else
        for (int i = 0; i < N; i++)
            c += a[threadIdx]*b[threadIdx];
}

如果确实如此,它对性能的影响有多大?有没有有效的方法来处理这个问题?感谢

2 个答案:

答案 0 :(得分:10)

根据块的尺寸,第一个条件threadIdx.x < 64(注意.x)可能不会导致任何分歧。例如,如果您有一个维度为(128,1,1)的块,则前两个warp(以锁定步骤执行的32个线程组)将进入if块,而最后两个将绕过它。由于整个 warp以某种方式运行,因此没有分歧。

threadIdx.x == 1这样的条件会引起分歧,但成本会非常适中。实际上,在许多情况下,CUDA将能够使用单个指令实现条件表达式。例如,minmaxabs等操作通常会使用单个指令实现,并且绝对不会产生分歧。您可以在PTX Manual

中阅读有关此类说明的信息

一般情况下,您不应过分关注如上所述的适度控制流量偏差。在像

这样的情况下,分歧会让你陷入困境
if (threadIdx.x % 4 == 0)
  // do expensive operation
else if (threadIdx.x % 4 == 1)
  // do expensive operation
else if (threadIdx.x % 4 == 2)
  // do expensive operation
else
  // do expensive operation

其中“昂贵的操作”是需要10或100条指令的操作。在这种情况下,由if语句引起的分歧会使效率降低75%。

请记住,线程分歧比(1)高级算法选择和(2)内存局部性/合并更少关注。很少有CUDA程序员应该关注你的例子中的那种分歧。

答案 1 :(得分:8)

如果每个块有多个线程,我会期望每个块的一个warp中的分歧(无论哪个块保存线程1)。

但是,两个循环之间的区别仅在于访问哪个内存,而不是在指令中。所以,我会这样做......

if (threadIdx.x < 64)
{
    //this conditional might diverge
    if (threadIdx.x == 1)
        ptr = a;
    else
        ptr = b;

    //but obviously this part will not
    for (int i = 0; i < N; i++)
        c += a[threadIdx]*ptr[threadIdx];
}