c++ - 使用 cudaSetDeviceFlags 的正确位置?

标签 c++ multithreading cuda

Win10 x64、CUDA 8.0、VS2015、6 核 CPU(12 个逻辑核心)、2 个 GTX580 GPU。

一般来说,我正在开发一个多线程应用程序,该应用程序启动与 2 个可用 GPU 关联的 2 个线程,这些线程存储在线程池中。

每个线程在启动时都会执行以下初始化过程(即,这只在每个线程的运行时期间完成):

::cudaSetDevice(0 or 1, as we have only two GPUs);
::cudaDeviceSetCacheConfig(cudaFuncCachePreferL1);
::cudaSetDeviceFlags(cudaDeviceMapHost | cudaDeviceScheduleBlockingSync);

然后,从其他工作线程(另外 12 个根本不接触 GPU 的线程),我开始向这 2 个与 GPU 相关的工作线程提供数据,只要启动的 GPU 线程数量相等,它就可以完美工作可用物理 GPU 的数量。

现在我想启动 4 个 GPU 线程(即每个 GPU 2 个线程)并让每个线程通过单独的 CUDA 流工作。我知道正确使用 CUDA 流所必需的要求,我满足所有这些要求。我失败的是上面提到的初始化过程。

一旦尝试从不同的 GPU 线程但对于同一 GPU 执行此过程两次,::cudaSetDeviceFlags(...) 就会开始失败,并显示“在此过程中设备处于事件状态时无法设置” 错误消息。

我查看了手册,似乎我明白了发生这种情况的原因,但我无法理解的是如何正确使用::cudaSetDeviceFlags(...) 进行设置。

我可以评论这个::cudaSetDeviceFlags(...) 行,即使每个 GPU 8 个线程,propgram 也能正常工作,但我需要设置 cudaDeviceMapHost 标志才能使用流,固定内存不会否则可用。

编辑需要考虑的额外信息#1:

  1. 如果在::cudaSetDevice 之前调用::cudaSetDeviceFlags 则不会出现错误 发生。
  2. 每个 GPU 线程通过以下方式分配一 block 固定内存 线程启动时的::VirtualAlloc ->::cudaHostRegister 方法 (无论启动多少个 GPU 线程都可以正常工作)并且 在线程终止时释放它(通过::cudaHostUnregister -> ::虚拟免费)。::cudaHostUnregister 失败,并显示“指针不 如果每个 GPU 的线程数大于 1,则“对应于一半线程的注册内存区域”。

最佳答案

好吧,高度复杂的尝试这个-尝试那个-看看会发生什么-再尝试的方法终于像往常一样成功了。

以下是::cudaSetDeviceFlags() 文档的摘录:

Records flags as the flags to use when initializing the current device. If no device has been made current to the calling thread, then flags will be applied to the initialization of any device initialized by the calling host thread, unless that device has had its initialization flags set explicitly by this or any host thread.

因此,在 GPU 工作线程中,有必要在 之前调用::cudaSetDeviceFlags()。

我在 GPU 线程初始化代码中实现了类似的东西,以确保在设备集实际正确应用之前设置设备标志:

bse__throw_CUDAHOST_FAILED(::cudaSetDeviceFlags(nFlagsOfDesire));
bse__throw_CUDAHOST_FAILED(::cudaSetDevice(nDevice));

unsigned int nDeviceFlagsActual = 0;
bse__throw_CUDAHOST_FAILED(::cudaGetDeviceFlags(&nDeviceFlagsActual));
bse__throw_IF(nFlagsOfDesire != nDeviceFlagsActual);

此外,talonmies 的评论还展示了解决::cudaHostUnregister 错误的方法。

关于c++ - 使用 cudaSetDeviceFlags 的正确位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47175958/

相关文章:

c++ - 避免 C++11 原始字符串文字中的第一个换行符?

c++ - 如何以及在注册表中写入什么以在 Windows 启动时自动重启程序

Java线程: synchronized reading and writing of value on the same object

python - 多数组计算中cupy执行错误

c++ - 使用 CUDA 转置 : Inquiry on program in Blog

c++ - 构建一个使用 boost 的 .cu 文件

c++ - 以某种方式用质数填充 vector

c++ - 如何在 for_each 期间添加元素

multithreading - boost::线程和模板函数

c++ - C++ 中分离线程的资源释放