2

我最近尝试将我的 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
     }

问题是有时当我运行这段代码时,一切都很顺利,但有时它会停止并且不会打印出“并行结束”语句。这种情况是随机发生的,谁能告诉我这可能是什么原因?

4

2 回答 2

2

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

在并行区域中想象一下,当执行前两行时,活动线程与另一行切换,

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

然后另一个线程将调用设置设备函数并更改所选设备。

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

每个流具有多个内核的 CUDA 并发内核执行

于 2012-09-17T19:45:35.937 回答
0

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

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

另一种可能性是重新设计你的内核。一个内核可以完成相同的工作并返回数组作为结果。

于 2012-09-18T12:15:40.083 回答