如果在条件分支内无法调用__syncthreads,如何减少CUDA?

时间:2016-09-13 06:39:29

标签: c++ parallel-processing cuda synchronization reduce

缩减方法suggested by NVIDIA在条件分支中使用__syncthreads(),例如:

if (blockSize >= 512) { if (tid < 256) { sdata[tid] += sdata[tid + 256]; } __syncthreads(); }

for (unsigned int s=blockDim.x/2; s>32; s>>=1)
{
    if (tid < s)
        sdata[tid] += sdata[tid + s];
    __syncthreads();
}

在第二个示例中,__syncthreads()位于for循环体内,也是一个条件分支。

然而,关于SO的一些问题引起了条件分支中__syncthreads()的问题(例如Can I use __syncthreads() after having dropped threads?conditional syncthreads & deadlock (or not)),并且答案说条件中的__syncthreads()分支机构可能导致僵局。因此,NVIDIA建议的缩减方法可能会陷入僵局(如果相信答案所依据的文档)。

此外,如果_syncthreads()无法在条件分支中使用,那么我担心许多基本操作都会被阻止,缩减只是一个例子。

那么如何在条件分支中不使用__syncthreads()来减少CUDA?或者它是文档中的错误?

1 个答案:

答案 0 :(得分:5)

限制不是

  

__syncthreads不能用于条件分支

限制是

  

__syncthreads不能在所有线程不会同时遍历的分支中使用

请注意,在两者您提供的示例中,__syncthreads不包含在依赖于线程ID(或某些每线程数据)的条件中。在第一种情况下,blockSize是一个模板参数,它不依赖于线程ID。在第二种情况下,它同样在if之后。

是的,for循环的s > 32是一个条件,但它是一个条件,其真值不以任何方式依赖于线程或其数据。 blockdim.x对于所有线程都是相同的。并且所有线程将执行与s完全相同的修改。这意味着所有线程将在其控制流的完全相同的点上到达__syncthreads。哪个完全没问题。

另一种情况,即你不能使用__syncthreads,这种情况对某些线程可能是真的而对其他线程则是假的。在这种情况下,您必须关闭所有条件才能使用__syncthreads。所以不要这样:

if (threadIdx.x < SOME_CONSTANT)
{
  operation1();
  __syncthreads();
  operation2();
}

你必须这样做:

if (threadIdx.x < SOME_CONSTANT)
{
  operation1();
}
__syncthreads();
if (threadIdx.x < SOME_CONSTANT)
{
  operation2();
}

您给出的两个示例都证明了这一点:在调用__syncthreads之前关闭了与线程ID相关的条件。