缩减方法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?或者它是文档中的错误?
答案 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相关的条件。