在if语句中的CUDA分歧,没有其他分支?

时间:2016-02-13 21:18:46

标签: cuda opencl gpgpu

在CUDA设备代码中,以下if-else语句将导致warp线程之间出现分歧,导致SIMD硬件两次通过。假设Vs是共享内存中的一个位置。

if (threadIdx.x % 2) {
  Vs[threadIdx.x] = 0;
} else {
  Vs[threadIdx.x] = 1;
}

我相信当我们有一个if语句时,会两次传递 no else分支。为什么会这样?

if (threadIdx.x % 2) {
  Vs[threadIdx.x] = 0;
}

以下if声明是否会在3次通过中完成?

if        (threadIdx.x < 10) {
  Vs[threadIdx.x] = 0;
} else if (threadIdx.x < 20) {
  Vs[threadIdx.x] = 1;
} else {
  Vs[threadIdx.x] = 2;
}

1 个答案:

答案 0 :(得分:1)

在GPU上,很可能只有一个带有if-else语句的传递 - 一个谓词传递。该条件将在“then”块中为半个线程打开“不执行任何操作”位,并为“else”块关闭另一半的“不执行任何操作”位。

正如@njuffa指出的那样,这取决于诸如目标架构等参数。

有关详细信息,请参阅:

Branch predication on GPU

对于if主体的第一个具体示例,编译器甚至可能不需要谓词传递,因为它可以被重写为

Vs[threadIdx.x] = (threadIdx.x % 2 ? 0 : 1);

这样你的经线就完全一致了。对于你的最后一个例子 - 它真的取决于,但理论上它也可以由编译器优化为单个不可预测的传递,并且也可能是你将拥有一个预测的单一路径,在三者中的每一个都有不同的预测作用域。