一个设备使用多个CUDA上下文有意义吗?

11

我原以为自己已经掌握了这个技术,但事实上并不是这样:)我需要使用NVENC从不符合编码器要求的帧中执行并行H.264流编码,因此我有以下代码流程:

  • 调用通知新帧已到达的回调函数
  • 将帧复制到CUDA内存并执行所需的颜色空间转换(只有第一个“cuMemcpy”是同步的,因此可以从回调函数返回,所有待处理操作都被推送到专用流中)
  • 在流中推送事件,并有另一个线程等待它,一旦设置,我就会获取正确颜色空间中带有帧的CUDA内存指针并将其提供给解码器

由于某种原因,我认为如果在并行线程中执行此管道,则需要为每个线程使用专用上下文。代码很慢,在阅读一些文章之后,我了解到上下文切换实际上是昂贵的,然后我确实得出结论,这是没有意义的,因为一个上下文拥有整个GPU,因此我锁定了其他转码器线程的任何并行处理。

问题1:在这种情况下,我是否可以使用单个上下文和在该上下文上创建的显式流来执行所述管道的每个线程?

问题2:有人可以让我了解CUDA设备上下文的唯一目的是什么吗?我认为在多GPU情况下,这是有意义的,但是否有任何情况需要为一个GPU创建多个上下文?


什么是NVCENC?我听说过NVENC和NVCUVENC。 - Robert Crovella
@RobertCrovella,我的错,NVENC 拼错了。 - Rudolfs Bundulis
2个回答

17

问题1:在这种情况下,我使用一个单一的上下文和为每个执行所述流水线的线程创建的显式流是否可行?

你可以使用单一的上下文。

问题2:有人能告诉我CUDA设备上下文的唯一目的是什么吗?我假设在多GPU场景中使用它会很有意义,但是否存在需要为一个GPU创建多个上下文的情况?

CUDA设备上下文在编程指南中有介绍。它表示与特定进程(即与该特定进程使用GPU相关联)关联的所有状态(内存映射、分配、内核定义和其他状态相关信息)。通常,不同进程将具有不同的上下文(以及不同的设备),因为这些进程具有独立的GPU使用和独立的内存映射。

如果你在一个GPU上有多进程使用,通常会在该GPU上创建多个上下文。正如你已经发现的那样,可以从单个进程创建多个上下文,但通常并不需要。

当你有多个上下文时,这些上下文中启动的内核需要进行上下文切换,以便从一个上下文中的一个内核切换到另一个上下文中的另一个内核。这些内核无法并发运行。

CUDA运行时API使用会为你管理上下文。当使用运行时API时,通常不需要明确与CUDA上下文交互。然而,在驱动程序API使用中,上下文是显式创建和管理的。


当您说多个上下文不能同时运行时,这是否仅限于内核启动,还是也包括内存传输?我一直在考虑在同一GPU上使用IPC API从进程到进程传输缓冲区的多进程设计。这是否意味着实际上只有一个进程可以同时独占整个GPU(而不仅仅是特定的SM)?这对我的设计来说并不致命,但确实令人失望。就调度而言,这如何与每个进程中异步排队的内核/流复制相互作用? - Jason R
关于你的第一个问题,我认为我的回答中倒数第二段已经很清楚地表明了我在谈论并发内核,但我进行了轻微的编辑以消除疑虑。至于剩下的部分,我建议你提出一个新的问题。在评论区讨论这些话题是不切实际的。 - Robert Crovella
@RobertCrovella鉴于最终需要在线程之间同步的单个cuda上下文(cuvidCtxLock),这是否意味着我们永远无法使用NVENC API实现真正的并发执行?如果我在单个线程中循环多个流的帧进行编码,那么速度会更快吗? - nano

2
显然,已经过去了几年,但是自2019年9月左右的视频编解码器SDK 9.1版本以来,NVENC / NVDEC现在似乎具有CUstream支持:https://developer.nvidia.com/nvidia-video-codec-sdk/download

新功能9.1-编码:NVENC中的CUStream支持,可增强CUDA预处理和NVENC编码之间的并行性

我对CUDA非常陌生,但是我的基本理解是,CUcontexts允许多个进程使用GPU(通过进行上下文交换来打断彼此的工作),而CUstreams则允许在单个进程内协调共享GPU资源。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接