CUDA内核仅由单个线程执行语句

时间:2012-06-05 11:41:15

标签: cuda gpgpu gpu-programming

如何在我的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”构造的东西。

2 个答案:

答案 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)的线程才会更新它而没有其他人会这样做。