1

TL;DR 版本: “使用 Python/PyCUDA 循环内核调用多个 GPU 以使 CPU 和 GPU 工作可以并行发生的最佳方式是什么?” 一边说“我不可能是第一个问这个的人;有什么我应该读的吗?”

完整版本:

我想知道在具有多个 GPU 的系统上使用 CUDA 的应用程序中设计上下文等处理的最佳方法。我一直在尝试查找有关何时适合上下文重用与娱乐的指南的文献,但到目前为止还没有找到任何概述最佳实践、经验法则等的内容。

我们需要做的总体概述是:

  • 请求进入一个中央流程。
  • 该进程分叉处理单个请求。
  • 数据从数据库加载(相对昂贵)。

以下内容根据请求重复任意次数(数十次):

  • 一些快速内核调用来计算后续内核所需的数据。
  • 一个缓慢的内核调用(10 秒)。

最后:

  • 内核调用的结果在 CPU 上收集和处理,然后存储。

目前,每个内核调用都会创建然后销毁一个上下文,这似乎很浪费。每个上下文和内核负载的设置大约需要 0.1 秒,虽然这不是很大,但它阻止了我们将其他更快的任务转移到 GPU。

我正在尝试找出管理上下文等的最佳方法,以便我们可以有效地使用机器。我认为在单gpu的情况下,它相对简单:

  • 在开始任何 GPU 工作之前创建一个上下文。
  • 启动第一组数据的内核。
  • 记录系列中最后一次内核调用之后的事件。
  • 在 CPU 上准备第二组数据,而第一组数据在 GPU 上进行计算。
  • 启动第二组,重复。
  • 确保每个事件在收集结果并存储它们之前得到同步。

假设正确使用重叠的内存副本,这似乎应该可以解决问题。

但是,我不确定当想要循环处理数十个项目中的每一个以在多个 GPU 上处理时我应该做什么。

宿主程序是 Python 2.7,使用 PyCUDA 访问 GPU。目前它不是多线程的,虽然我宁愿保持这种方式(“现在你有两个问题”等),如果答案意味着线程,它意味着线程。同样,当需要阻塞数据时,能够在主线程中调用 event.synchronize() 会很好,但是对于我们的需要,有效地使用硬件更为重要。由于我们可能会同时处理多个请求,因此让其他进程在该进程不使用 GPU 时使用它很重要。

我认为我们没有任何明确的理由使用独占计算模式(即,我们不会用一个工作项来填充卡的内存),所以我不认为涉及长期上下文的解决方案不在桌子上。

请注意,以指向涵盖我的问题的其他内容的链接形式的答案是完全可以接受的(甚至是鼓励的),只要它们对原因有足够的详细信息,而不仅仅是 API。谢谢阅读!

4

1 回答 1

1

警告:我还不是 PyCUDA 用户。

使用 CUDA 4.0+,您甚至不需要每个 GPU 的显式上下文。您可以在执行每个设备的操作(、、启动内核等)之前调用(或cudaSetDevicePyCUDA 等效项)。cudaMalloccudaMemcpy

如果您需要在 GPU 之间进行同步,则可能需要创建流和/或事件并使用cudaEventSynchronize (或 PyCUDA 等价物)。您甚至可以让一个流等待插入到另一个流中的事件来执行复杂的依赖关系。

所以我怀疑今天的答案比 talonmies 的优秀pre-CUDA-4.0 答案要简单得多。

您可能还会发现此答案很有用。

(重新)由 OP 编辑​​:据我了解,PyCUDA 支持 4.0 之前的 CUDA 版本,因此仍使用旧的 API/语义(驱动程序 API?),因此 talonmies 的答案仍然相关。

于 2012-03-09T06:18:08.457 回答