在CUDA内核中调用推力函数__global ___

时间:2018-02-11 21:51:25

标签: c++ cuda gpu thrust

我已经读过新版本的CUDA支持动态并行性,我可以在thrush::exclusive_scan参数的内核函数中调用像thrust::device这样的推力函数。

__global__ void kernel(int* inarray, int n, int *result) {
  extern __shared__ int s[];
  int t = threadIdx.x;

  s[t] = inarray[t];
  __syncthreads();

  thrust::exclusive_scan(thrust::device, s, n, result);
  __syncthreads();
}

int main() {
  // prep work

  kernel<<<1, n, n * sizeof(int)>>>(inarray, n, result);
}

我感到困惑的是:

  1. 在内核中调用推力函数时,每个线程是否都会调用该函数一次,它们都会对数据进行动态并行处理?
  2. 如果他们这样做,我只需要一个帖子来呼叫thrust,这样我就可以ifthreadIdx;如果没有,那么一个块中的线程如何相互通信已经完成了对推力的调用,并且它们应该忽略它(这似乎有点想象,因为不会有一个系统的方法来确保来自用户&#39 ; s代码)。总结一下,当我在内核中使用thrust::device参数调用推力函数时,究竟发生了什么?

1 个答案:

答案 0 :(得分:3)

  1. 内核中执行推力算法的每个线程都会执行算法的单独副本。内核中的线程在单个算法调用中不合作。

  2. 如果您已满足CUDA动态并行(CDP)调用的所有要求(硬件/软件和编译设置),则遇到推力算法调用的每个线程将启动CDP子内核以执行推力算法(在这种情况下,CDP子内核中的线程执行合作)。如果没有,遇到推力算法调用的每个线程将执行它,就好像您指定了thrust::seq而不是thrust::device

  3. 如果您希望在支持CDP的环境中避免使用CDP活动,则可以指定thrust::seq

  4. 例如,如果您打算只执行推力算法的一个副本,则在内核代码中必须确保只有一个线程调用它,例如:

    if (!threadIdx.x) thrust::exclusive_scan(...  
    

    或类似。

  5. 调用之前/之后的同步问题与普通的CUDA代码没有什么不同。如果您需要块中的所有线程等待推力算法完成,请使用例如__syncthreads(),(以及CDP案例中的cudaDeviceSynchronize())。

  6. 信息here也可能是有意义的。