【问题标题】:CUDA divergence at an if statement, with no else branch?if 语句中的 CUDA 分歧,没有 else 分支?
【发布时间】:2016-05-24 22:49:32
【问题描述】:

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

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

我相信当我们有一个if 语句时会有两次通过,没有 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;
}

【问题讨论】:

  • @user2023370:然后查看我的编辑。

标签: cuda opencl gpgpu


【解决方案1】:

在 GPU 上,很可能只有一个带有 if-else 语句的遍 - 一个谓词遍。该条件只会在“then”块期间为一半线程打开“什么都不做”位,并为“else”块关闭另一半的“什么也不做”位。

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

更多详情见:

Branch predication on GPU


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

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

这在你的经线上完全一致。对于您的最后一个示例-它确实取决于,但理论上它可以再次由编译器优化为单个非谓词传递,并且您也可能会有一个谓词单路径,在三个中的每一个中都有不同的谓词范围。

【讨论】:

  • 条件执行的代码块可能有谓词,也可能有分支围绕它,也可能有统一分支加谓词。除了预测的可能性随着块大小的减小而增加之外,不可能预先说明编译器将做出的选择。除此之外,这取决于目标架构、优化级别等。使用cuobjdump --dump-sass 检查机器代码将知道编译器做出了哪个选择。
  • 你确定吗?您提供的参考非常简短,甚至与 if-else 相关(需要 40+50 (90) 个周期);而不是我要问的单个 if 声明。
  • @user2023370:嗯,我不确定确定,但至少对于第一个例子来说——如果不是一次性发生,nvcc 是非常糟糕的。不过,说真的,只需使用传递给 nvcc 的--ptx 编译你的内核,你就会(有点)看到实际发生了什么。不用担心,PTX 的具体细节你不用知道,你会搞清楚的。
猜你喜欢
  • 2020-03-20
  • 1970-01-01
  • 2016-05-27
  • 2012-12-20
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 2020-10-10
  • 2013-12-02
相关资源
最近更新 更多