如何适当地将OpenMP与CUDA结合起来

时间:2012-09-15 03:23:36

标签: cuda openmp

我最近尝试将我的CUDA代码与OpenMP结合使用,但是出现了一些问题。我的CUDA-OpenMP代码写成

    int main (void)
    {
       cudaGetDeviceCount(&gpuNum);

       //declare variables
       float *data_h; *data_d[gpuNum];
       data_h = (float*)malloc(Mem);
       ....
       ....
       omp_set_num_threads(gpuNum); 
       #pragma omp parallel
       {
         int cpuid = omp_get_thread_num();
         cudaSetDevice(cpuid);

         cudaMalloc((void**)&data_d[cpuid], Mem );

         cudaMemcpy( data_d[cpuid], data_h, Mem, cudaMemcpyHostToDevice);
         kernel<<< gpu_block, gpu_thread >>>();
         cudaMemcpy( data_h, data_d[cpuid], Mem, cudaMemcpyDeviceToHost);
       }
       printf("end of parallel\n");
       //post process
     }

问题在于,有时当我运行此代码时,一切进展顺利,但有时它会停止并且“并行结束”句子将不会打印出来。这种情况是随机发生的,任何人都可以告诉我这可能是什么原因?

2 个答案:

答案 0 :(得分:2)

我想提供一些失败的可能性:

在并行区域中,假设当执行前两行时,活动线程将被另一行切换,

#pragma omp parallel{
  int cpuid = omp_get_thread_num();
  cudaSetDevice(cpuid);
  ...
}

然后另一个线程将调用设备设备功能,所选设备将被更改。

虽然memcopy操作阻塞,但内核调用却没有。因此,如果在内核调用之后切换线程,则在一次内核调用未完成时,将发出另一个内核调用。要执行并发内核,您需要使用“ streams ”。看看

CUDA concurrent kernel execution with multiple kernels per stream

答案 1 :(得分:0)

如果您想获得最佳性能,我建议您不要使用OpenMP来运行CUDA。我从我的经验中知道,OpenMP创建的thred并不是无成本的,而且需要一些时间。在创建线程期间,您将能够在许多设备上运行更多的gpu内核。

如上所述@phoad,如果您的数据集是独立的,则可以使用流。你可以在网上找到很多例子。

另一种可能性是重新设计你的内核。一个内核可以做同样的工作并返回数组。