我知道具有2.x或更高计算能力的NVIDIA GPU可以同时执行多达16个内核。但是,我的应用程序生成7个“进程”,每个进程启动CUDA内核。
我的第一个问题是这些内核的预期行为是什么。它们会并发执行,还是由于它们由不同的进程启动,它们将按顺序执行?
我感到困惑,因为CUDA C编程指南说:
“来自一个CUDA上下文的内核不能与来自另一个CUDA上下文的内核同时执行。”
这带我来到我的第二个问题,什么是CUDA“上下文”?
谢谢!
CUDA上下文是一个虚拟执行空间,它保存由主机线程或进程拥有的代码和数据。在当前所有硬件中,只能有一个上下文处于活动状态。
因此,为了回答您的第一个问题,如果有七个独立的线程或进程都尝试在同一个GPU上建立上下文并运行,它们将被序列化,并且任何等待访问GPU的进程都将被阻塞,直到正在运行的上下文的所有者放弃。据我所知,没有时间切片,调度启发式算法也未记录,并且(我认为)在不同操作系统之间也不统一。
最好启动一个持有GPU上下文的单个工作线程,并使用其他线程的消息将工作推送到GPU上。另外,CUDA驱动程序API中提供了上下文迁移功能,但它仅适用于来自同一进程的线程,而迁移机制具有延迟和主机CPU开销。
补充一下@talonmies的回答:
在较新的架构中,通过使用MPS,多个进程可以同时启动多个内核。因此,现在肯定是可能的,而以前则不是。要详细了解,请阅读本文。
https://docs.nvidia.com/deploy/pdf/CUDA_Multi_Process_Service_Overview.pdf
此外,您还可以查看不同GPU支持的每个CUDA计算能力类型允许的最大并发内核数量。这是一个链接:https://en.wikipedia.org/wiki/CUDA#Version_features_and_specifications
例如,具有7.5的CUDA计算能力的GPU最多可以启动128个CUDA内核。你真的需要单独的线程和上下文吗? 我相信最佳实践是每个GPU使用一个上下文,因为在单个GPU上使用多个上下文会带来足够大的开销。
为了同时执行许多内核,您应该在一个CUDA上下文中创建几个CUDA流,并将每个内核排队到自己的流中-这样它们将并发执行,如果有足够的资源。
如果需要使上下文从几个CPU线程可访问-可以使用cuCtxPopCurrent(),cuCtxPushCurrent()进行传递,但任何时间只能有一个线程能够使用上下文。