我在互联网上看到了许多关于分支分歧以及如何避免它的问题。然而,即使在阅读了数十篇关于 CUDA 如何工作的文章之后,我似乎也看不出在大多数情况下避免分支分歧有什么帮助。在有人伸出爪子扑向我之前,请允许我描述一下我认为“大多数情况”的情况。
在我看来,大多数分支分歧实例都涉及许多真正不同的代码块。例如,我们有以下场景:
if (A):
foo(A)
else:
bar(B)
如果我们有两个线程遇到这种分歧,线程 1 将首先执行,走路径 A。随后,线程 2 将走路径 B。为了消除分歧,我们可以将上面的代码块改为如下所示:
foo(A)
bar(B)
foo(A)
假设在线程 2 和线程 1 上调用是安全的bar(B)
,人们可能会期望性能会有所提高。但是,这是我的看法:
在第一种情况下,线程 1 和 2 串行执行。称之为两个时钟周期。
在第二种情况下,线程 1 和 2foo(A)
并行执行,然后bar(B)
并行执行。在我看来,这仍然像两个时钟周期,不同之处在于,在前一种情况下,如果foo(A)
涉及从内存读取,我想线程 2 可以在该延迟期间开始执行,从而导致延迟隐藏。如果是这种情况,分支发散代码会更快。