如何避免在Cuda简单if语句中的分歧分支

时间:2014-10-11 15:39:35

标签: c cuda

我想知道,当线程必须比较和存储来自本地,共享或全局变量的值时,如何避免内核中的分支。例如,以下代码检查共享变量并相应地将bool标志设置为true

if ( shared_variable < local_value ){
    shared_bool_var = true;
}
__syncthreads();

这里的问题是所有线程都访问同一个变量,所有线程都将覆盖为true。 所以我会使用threadId.x检查只允许一个线程访问该变量,但这会导致分支发散。

if ( threadIdx.x == 0 && shared_variable < local_value ){
    shared_bool_var = true;
}
__syncthreads();

这里的问题是我应该做什么?在这两种情况下,似乎都是安全的,因为syncthread将保护 Hazards (在写入之前读取等)。我的偏好是第二种解决方案,但通常代码并不那么简单。

在上述情况下,允许所有线程访问1个共享内存位置是否安全,否则会导致银行冲突或内存访问序列化? 感谢

1 个答案:

答案 0 :(得分:2)

需要注意的一件重要事情:在语义和功能上,两个代码节都不相同:

// set var to true if ANY thread in the block verifies the predicate
if (shared_variable < local_value) {
    shared_bool_var = true;
}

// set var to true if THE FIRST thread in the block verifies the predicate
if (threadIdx.x == 0 && shared_variable < local_value) {
    shared_bool_var = true;
}

但回到你的问题:

  

在上述情况下,允许所有线程访问1个共享内存位置是否安全,否则会导致银行冲突或内存访问序列化?

CUDA programming guide中验证后,似乎存在某种写崩溃机制阻止对同一地址的写访问序列化:相反,只有一个线程写入其值(但是哪个线程未定义) )。

<强> CC 1.x:

  

如果warp执行的非原子指令写入warp的多个线程的共享内存中的相同位置,则每个half-warp只执行一个线程执行写操作,哪个线程执行最终写操作是未定义。

<强> CC 2.x and above:

  

warp的共享内存请求不会在访问同一个32位字内任何地址的两个线程之间产生存储体冲突(即使这两个地址属于同一个存储区):在这种情况下,[.. 。]对于写访问,每个地址只由一个线程写入(哪个线程执行写操作未定义)。

此外:

  

所以我会使用threadId.x检查只允许一个线程访问该变量,但这会导致分支发散。

这不比第一个代码“更加分散”。只要整个warp没有相同地评估谓词,第一节就会表现出分歧。第二节仅在每个区块的第一个经线中表现出分歧。在这两种情况下,这些分支都不会对性能产生影响:没有else主体,if主体只有一条指令。