Cuda 如何收集块中线程的单个结果?

Cuda 如何收集块中线程的单个结果?,cuda,Cuda,在我的内核中,线程正在处理全局内存中数组的一小部分。 处理后,我还想设置一个标志,指示块内所有线程的计算结果为零: __global__ void kernel( int *a, bool *blockIsNull) { int tid = blockIdx.x * blockDim.x + threadIdx.x; int result = 0; // {...} Here calculate result a[tid] = result; // some code h

在我的内核中,线程正在处理全局内存中数组的一小部分。 处理后,我还想设置一个标志,指示块内所有线程的计算结果为零:

__global__ void kernel( int *a, bool *blockIsNull) { 
  int tid = blockIdx.x * blockDim.x + threadIdx.x;
  int result = 0;
  // {...} Here calculate result
  a[tid] = result;

  // some code here, but I don't know, that's my question...
  if (condition)
    blockIsNull[blockIdx.x] = true; // if all threads have returned result==0
}
每个线程都拥有这些信息。但是我没有找到一个有效的方法来收集它

例如,我可以在共享内存中有一个计数器,当
result==0
时,该计数器由每个线程自动递增。因此,当计数器到达
blockDim.x
时,意味着所有线程都返回了零。尽管未经测试,但我担心此解决方案会对性能产生负面影响(原子功能很慢)

零结果并不经常出现,因此一个块中的所有线程都不太可能有零。我希望找到一个在一般情况下对性能影响不大的解决方案


你有什么建议

听起来您想在块上对条件值执行块级缩减。几乎所有CUDA硬件都支持一组非常有用的扭曲投票原语。您可以使用
\uuu all()
扭曲投票来确定每个扭曲的线程是否满足该条件,然后再次使用
\uu all()
来检查所有扭曲是否满足该条件。在代码中,它可能如下所示:

__global__ void kernel( int *a, bool *blockIsNull) { 

    // assume that threads per block is <= 1024
    __shared__ volatile int blockcondition[32];
    int laneid = threadIdx.x % 32;
    int warpid = threadIdx.x / 32;

    // Set each condition value to non zero to begin
    if (warpid == 0) {
        blockcondition[threadIdx.x] = 1;
    }
    __syncthreads();

    //
    // your code goes here
    //

    // warpcondition holds the vote from each warp
    int warpcondition = __all(condition);

    // First thread in each warp loads the warp vote to shared memory
    if (laneid == 0) {
        blockcondition[warpid] = warpcondition;
    }
    __syncthreads();

    // First warp reduces all the votes in shared memory
    if (warpid == 0) {
        int result = __all(blockcondition[threadIdx.x] != 0);

        // first thread stores the block result to global memory
        if (laneid == 0) {
             blockIsNull[blockIdx.x] = (result !=0);     
        }
    }
}
\uuuu全局\uuuu无效内核(int*a,bool*blockIsNull){

//假设每个块的线程数为,我不知道warp level
\uu all()
投票函数,但它似乎是合适的答案。我将在将来测试它。谢谢!