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()
投票函数,但它似乎是合适的答案。我将在将来测试它。谢谢!