如何在我的CUDA内核中编写由单个线程执行的语句。例如,如果我有以下内核:
__global__ void Kernel(bool *d_over, bool *d_update_flag_threads, int no_nodes)
{
int tid = blockIdx.x*blockDim.x + threadIdx.x;
if( tid<no_nodes && d_update_flag_threads[tid])
{
...
*d_over=true; // writing a single memory location, only 1 thread should do?
...
}
}
在上面的内核中,“d_over”是一个布尔标志,而“d_update_flag_threads”是一个布尔数组。
我之前通常使用的是线程块中的第一个线程,例如:
if(threadIdx.x==0)
但它在这种情况下无法工作,因为我在这里有一个标志数组,只有带有assosiated标志“true”的线程才会执行if语句。该标志数组由之前调用的另一个CUDA内核设置,我事先并不了解它。
简而言之,我需要在OpenMP中使用类似于“Single”构造的东西。
答案 0 :(得分:3)
可能的方法是使用原子操作。如果每个块只需要一个线程来进行更新,则可以在共享内存中执行原子操作(对于计算能力&gt; = 1.2),这通常比在全局内存中执行它快得多。
说,这个想法如下:
int tid = blockIdx.x*blockDim.x + threadIdx.x;
__shared__ int sFlag;
// initialize flag
if (threadIdx.x == 0) sFlag = 0;
__syncthreads();
if( tid<no_nodes && d_update_flag_threads[tid])
{
// safely update the flag
int singleFlag = atomicAdd(&sFlag, 1);
// custom single operation
if ( singleFlag == 0)
*d_over=true; // writing a single memory location, only 1 thread will do it
...
}
这只是一个想法。我没有对它进行过测试,但它接近于由单个线程执行的操作,而不是该块的第一个线程。
答案 1 :(得分:0)
您可以使用atomicCAS(d_over,0,1)声明d_over或者类型转换为int *。 这将确保只有第一个看到d_over值为0(false)的线程才会更新它而没有其他人会这样做。