我有一个CUDA内核,首先将全局计数器设置为零,进行一些计算,递增共享计数器,然后将不同块的共享计数器添加到全局计数器。现在我想确保初始化发生在全局计数器的任何增量之前。这是我的内核的简化示例:
__global__ void counter_function(int32_t* global_count, int32_t* other_data)
{
__shared__ int32_t block_count;
bool condition = false;
// first thread of first block initializes global counter
if (thread.Idx == 0 && block.Idx == 0) {
*global_count = 0;
}
// do some calculation on other_data and possibliy set
// condition = true;
// increment counter if condition is true
if (condition) {
atomicAdd(&block_count, 1);
}
__synchthreads();
// first thread of each block adds its count to the global count
if (thread.Idx == 0) {
atomicAdd(&global_count, block_count);
}
}
我已经阅读了CUDA C编程指南的Memory Fence Functions和Synchronization Functions,但找不到解决方案,因为__syncthreads()
仅同步每个块的线程并且仅__threadfence()
据我所知,在线程内处理全局读/写操作的顺序。并且由于除了初始化全局计数的线程之外的所有线程只有一个全局写操作,因此在我的情况下似乎没有任何用处。我理解__threadfence()
功能吗?
一种方法似乎是将内核拆分为两个内核,因此基本上有一个单独的内核只将计数器设置为零。但是有更好的方法吗?
有任何建议如何解决这个问题?或者我错过了什么?
答案 0 :(得分:0)
在CUDA中,没有允许您在块之间“同步”的功能。另外,正如@Robert Crovella已经提到的,线程执行顺序是未指定的。您应该编写2个单独的内核并在执行前者后调用cudaDeviceSynchronize以确保已执行所请求的操作。
此外,您的代码中的atomicAdd似乎是不必要的。最好有一个int向量,每个线程可以更新一个单独的元素,然后对整个向量执行Reduce操作。