如果知道warp中所有线程的条件相同,如何避免在CUDA程序中执行条件的两个分支?

Posted

技术标签:

【中文标题】如果知道warp中所有线程的条件相同,如何避免在CUDA程序中执行条件的两个分支?【英文标题】:How to avoid executing both branches of conditional in CUDA program if it is known that the condition is the same for all threads in a warp? 【发布时间】:2020-12-20 01:08:53 【问题描述】:

据我了解,如果我有以下形式的 CUDA 代码:

if (condition) 
    // do x

else 
    //do y

然后由于线程在扭曲中的 SIMT 执行,条件的执行将被序列化,并且所有线程都需要运行代码的 x 和 y 部分。例外情况是如果分支很大,在这种情况下编译器会使用__any 插入检查以避免不必要地运行代码。

但是,如果我提前知道一个 warp 中的所有线程都将具有相同的 condition 值,那么这个 __any 操作就没有必要了,只会降低我的代码速度。

我想知道是否有任何方法可以指示编译器不包含此投票操作,而是假设条件的评估对于 warp 中的所有线程都是相同的,并且只运行相应的块代码?

【问题讨论】:

我对编译器插入 __any 的说法持怀疑态度。我在条件的两边都写了复杂的代码,我在 SASS 中看不到它。我知道你可以找到info on the web that seems to substantiate this,但我认为这是过时的信息,以及可能不再正确的实现细节。在任何情况下都没有这样的documented instruction to the compiler,并且warp vote 是一个成本相对较低的指令。 相反,NVIDIA materials(幻灯片 49)建议如果决策边界在扭曲之外,则可以避免分歧的成本(对于该扭曲)。我的理解是,只有当 warp 中的一个或多个线程实际选择了该路径时,warp 执行引擎才会遵循不同的路径。如果 warp 中的 0 个线程选择了特定的发散路径,则 warp 执行引擎足够聪明,不会调度该路径(所有线程都被屏蔽)。 【参考方案1】:

然后由于线程在 warp 中的 SIMT 执行,条件的执行将被序列化,并且所有线程都需要运行代码的 x 和 y 部分

只有当条件在扭曲中的评估不一致时才会发生

如果分支很大,则例外情况,在这种情况下,编译器将使用__any 插入检查以避免不必要地运行代码。

这是完全错误的。该编译器不这样做,并且从字面上反汇编任何版本的 CUDA 编译器所发出的任何代码都是微不足道的 NVIDIA 曾经发布过以确认这一点。有predicated execution,但这与你描述的有很大不同。

但是,如果我已经提前知道 warp 中的所有线程都将具有相同的条件值,那么这个 __any 操作是不必要的,只是为了减慢我的代码速度。

这不仅没有必要,而且根本不存在。

我想知道是否有任何方法可以指示编译器不包含此投票操作,而是假设条件的评估对于 warp 中的所有线程都是相同的,并且只运行相应的块代码?

不,因为你想要的是默认行为。

【讨论】:

以上是关于如果知道warp中所有线程的条件相同,如何避免在CUDA程序中执行条件的两个分支?的主要内容,如果未能解决你的问题,请参考以下文章

cuda基础---cuda通信机制

两个块可以在同一个warp中执行吗?

如何避免死锁

在 GPU 架构中,所有非活动扭曲的数据存储在哪里?

如何避免死锁

如何使翘曲导致另一个翘曲处于空闲状态?