多个GPU上的CUDA上下文、流和事件

多个GPU上的CUDA上下文、流和事件,cuda,pycuda,Cuda,Pycuda,TL;DR version:“使用Python/PyCUDA对多个GPU进行循环内核调用,从而使CPU和GPU并行工作的最佳方式是什么?”带有“我不可能是第一个问这个问题的人;有什么我应该读的吗?” 完整版本: 我想知道在具有多个GPU的系统上使用CUDA的应用程序中设计上下文等处理的最佳方法。我一直在努力寻找文献,其中讨论了上下文重用与娱乐何时合适的指导原则,但到目前为止还没有找到任何概述最佳实践、经验法则等的内容 我们需要做的总体概述如下: 请求进入一个中心进程 该过程分叉处理单个请求 数

TL;DR version:“使用Python/PyCUDA对多个GPU进行循环内核调用,从而使CPU和GPU并行工作的最佳方式是什么?”带有“我不可能是第一个问这个问题的人;有什么我应该读的吗?”

完整版本:

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

我们需要做的总体概述如下:

  • 请求进入一个中心进程
  • 该过程分叉处理单个请求
  • 数据从数据库加载(相对昂贵)
根据请求,以下操作会重复任意次数(数十次):

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

  • 内核调用的结果在CPU上收集和处理,然后存储
目前,每个内核调用都会创建并销毁一个上下文,这似乎是浪费。安装程序在每个上下文和内核负载上花费了大约0.1秒,虽然这并不是很大,但它阻止了我们将其他更快的任务转移到GPU上

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

  • 在开始任何GPU工作之前创建上下文
  • 为第一组数据启动内核
  • 在系列中的最后一个内核调用之后为录制事件
  • 当第一组数据在GPU上计算时,在CPU上准备第二组数据
  • 启动第二组,重复
  • 在收集和存储结果之前,确保每个事件都已同步
假设正确使用重叠的内存拷贝,这似乎应该可以做到

然而,当我想在多个GPU上循环处理几十个项目中的每一个项目时,我不确定应该怎么做

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

我不认为我们有任何明确的理由使用独占计算模式(即,我们没有用一个工作项填充卡的内存),因此我不认为涉及长期上下文的解决方案是不可能的


请注意,以链接的形式回答我的问题的其他内容是完全可以接受的(甚至是鼓励的),前提是这些内容足够详细地说明了为什么,而不仅仅是API。谢谢你的阅读

警告:我还不是PyCUDA用户

使用CUDA 4.0+时,每个GPU甚至不需要显式上下文。您只需调用
cudaSetDevice
(或PyCUDA等效程序),然后再进行每设备操作(
cudamaloc
cudaMemcpy
、启动内核等)

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

所以我怀疑今天的答案比泰龙的优秀答案要简单得多

你可能也会发现这很有用


(Re)按OP编辑:据我所知,PyCUDA支持4.0之前的CUDA版本,因此仍然使用旧的API/语义(驱动程序API?),因此Talonmes的答案仍然相关。

警告:我不是PyCUDA用户(目前)

使用CUDA 4.0+时,每个GPU甚至不需要显式上下文。您只需调用
cudaSetDevice
(或PyCUDA等效程序),然后再进行每设备操作(
cudamaloc
cudaMemcpy
、启动内核等)

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

所以我怀疑今天的答案比泰龙的优秀答案要简单得多

你可能也会发现这很有用


(Re)按OP编辑:据我所知,PyCUDA支持4.0之前的CUDA版本,因此仍然使用旧的API/语义(驱动程序API?),因此Talonmes的答案仍然是相关的。

Uhrm,“用Python/PyCUDA循环多个GPU的内核调用以使CPU和GPU并行工作的最佳方式是什么?”“我不可能是第一个问这个问题的人;有什么我应该读的吗?“与之类似,但它早于CUDA 4.0版本,该版本对多gpu进行了很多更改。我希望避免每个内核调用上下文,但这可能是不现实的。您不需要每个内核调用上下文,您需要每个gpu上下文。理想的持久性。这曾经意味着每个设备一个线程。从CUDA 4.0开始,它就没有了。你可以用一根线。我经常使用pycuda,但通常使用mpi4py,因为我主要使用集群。我还没有用CUDA4.Uhrm尝试过CUDA4.0风格的多GPU,“对多个GPU进行循环内核调用的最佳方法是什么