CUDA编译器如何知道warp的分歧行为?

时间:2012-04-12 08:10:54

标签: cuda nvcc

CUDA编程指南(v4.1)在第5.4.2节中描述了谓词指令

  

编译器用谓词替换分支指令   指令仅在指令数量受控制时   分支条件小于或等于某个阈值:如果是   编译器确定条件可能产生很多   发散扭曲,此阈值为7,否则为4。

  1. 条件如何产生许多不同的扭曲?给定的条件可以 只将经线分成两部分。 很多在这里意味着什么?
  2. 即使上面有意义,编译器如何知道运行时 经线的分歧行为?

1 个答案:

答案 0 :(得分:2)

变形永远不会“分裂”。它们要么需要“条件执行”(所以执行非参与线程被屏蔽)来服务条件不同的代码路径,要么它们不需要。

至于条件如何产生多个不同的扭曲,请考虑以下设计的例子:

if (threadIdx.x < 128) {
   // Only first four warps process here
   int modthirtytwo = threadIdx.x % 32;

   if (modthirtytwo == 0) {
      // Action A only first thread in the warp
   } else {
      // Action B for the other threads in the warp
   }
}

这里,代码可以产生多个不同的warp,编译器应该能够在编译时对行为进行建模。如果为内核的编译器指定了启动边界,那就更好了。将此情况与仅使用一个warp的共享内存减少进行比较。

if (threadIdx.x < 32) {
   if (threadIdx.x < 16)  shm[threadIdx.x] += shm[threadIdx.x+16];
   if (threadIdx.x < 8)   shm[threadIdx.x] += shm[threadIdx.x+8];
   if (threadIdx.x < 4)   shm[threadIdx.x] += shm[threadIdx.x+4];
   if (threadIdx.x < 2)   shm[threadIdx.x] += shm[threadIdx.x+2];
   if (threadIdx.x == 0)  shm[0] += shm[1];
}

这里的差异仅限于每个块的单个扭曲。所有这些文字都说是两种情况下的编译器行为可能不同。

似乎“新”编译器(它已经用于OpenCL几年)具有heurisitics,用于在分支变得更经济之前它应该使用多少谓词指令。并且似乎指令管道中的许多分支对性能不利,因此当编译器可以计算出代码将产生更高的“分支密度”时,它将更喜欢更多的谓词指令而不是分支。