1

我们有一个多 GPU 框架(在 Windows 上),可以在其中指定“作业”(还指定它们应在哪个 GPU 上完成),然后在特定 GPU 上执行。目前,我们的方法是在启动框架时为每个 GPU 创建一个“工作线程”,然后等待作业被处理。具体来说,我们使用来自https://devtalk.nvidia.com/search/more/sitecommentsearch/GPUworker/的“GPUWorker”类

到目前为止它运行良好,但有一些严重的与性能相关的缺点:

  • 在我们的框架中,一个特定的 GPU 在“作业”的整个时间内都被锁定,即使 GPU 实际上仅在 50% 的作业时间内使用。请注意,作业具有非常粗略的粒度,例如“进行光流计算”,这可能需要 50 - 100 毫秒。

  • 不能指定不锁定 GPU 的“异步”作业(例如异步主机设备副本)

所以我现在正在考虑针对该问题的“更好”策略。我的想法如下:对于每个“启动”的新作业,我创建一个新的“临时”CPU 线程。CPU 线程然后设置要在其上完成工作的 GPU 的设备号(通过“cudaSetDevice”)。我想此时也(对我透明地)创建了一个 Cuda 上下文。在看到正确的设备后,作业的“doWork”功能由 CPU 线程执行。取决于作业是同步完成还是异步完成,是否完成了“加入”(等待 CPU 线程完成)。

我现在有几个问题:

  • 这是一个“好”的策略,还是有人知道如何处理这个更好的方法?当然它必须是线程安全的策略。

  • 在我提出的策略中,创建新 CPU 线程和(隐藏)创建 Cuda 上下文的典型开销(以毫秒为单位)是多少?此外,如果 Cuda 上下文的创建很重要,有没有办法(例如使用 cuda 设备 api 和某种“上下文迁移”)来减少这种开销?

4

1 回答 1

2

您的第一种方法听起来比您正在考虑的替代方法更有希望。

创建 CPU 线程和初始化 CUDA 上下文是非常昂贵的,而且你很难使该操作更快。NVIDIA 故意将大量操作预先加载到上下文创建过程中,因此您不会因资源分配失败而出现意外延迟或失败。

你最好的选择是投资异步。如果没有 CPU/GPU 并发,您肯定会将性能留在桌面上,因为您没有隐藏 CUDA 驱动程序中内置的 CPU 开销。

于 2013-10-21T19:42:20.690 回答