在多GPU的机器上,是否可以执行多个CUDA程序的实例?

3

背景:

我编写了一个CUDA程序,用于处理一系列符号。该程序并行处理所有符号序列,但要求所有序列的长度相同。我将数据分类为具有相同长度的序列组。程序每次处理1个组。

问题:

我在拥有4个GPU的Linux机器上运行代码,并希望通过运行4个程序实例(每个GPU运行1个)来利用所有4个GPU。是否可能让程序选择一个未被另一个CUDA应用程序使用的GPU来运行?我不想硬编码任何内容,以免在将程序运行在具有更多或更少GPU的不同硬件上时出现问题。


http://www.nvidia.com/docs/IO/116711/sc11-multi-gpu.pdf 是你的问题在谷歌上的热门搜索结果。它解决了你的问题吗? - Yakk - Adam Nevraumont
不是很对,那个解决方案是关于在一个CUDA应用程序中利用多个GPU,我问的是如何在多个GPU上同时运行多个CUDA程序(但每个实例仍然只有一个GPU)。这需要对我的代码进行重大改写才能处理同一实例中的多个批次。 - aseal
你正在进行异步调用,对吧?将组分成 N 个子组(其中 N 是 GPU 数量),将每个子组发送到不同的 GPU 上,然后再将它们收集起来? - Yakk - Adam Nevraumont
每个组通常不包含足够的并行序列,甚至无法充分利用1个GPU,因此将1个组分布在多个GPU上是毫无意义的。这些组不能合并和拆分,因为每个序列对应一个2D矩阵,从中生成一个3D矩阵,用于计算另一个2D矩阵。容纳不同长度的序列需要完全重写我针对这些矩阵的内存索引方案。 - aseal
2个回答

5

环境变量 CUDA_VISIBLE_DEVICES 是您的好帮手。

我假设您打开了与GPU数量相同的终端。 假设您的应用程序名为myexe

然后在一个终端中,您可以执行:

CUDA_VISIBLE_DEVICES="0" ./myexe

在下一个终端中:
CUDA_VISIBLE_DEVICES="1" ./myexe

等等。

然后,第一个实例将在CUDA枚举的第一个GPU上运行。第二个实例将仅在第二个GPU上运行,依此类推。

假设使用bash,并针对给定的终端会话,您可以通过导出变量来使其“永久”:

export CUDA_VISIBLE_DEVICES="2"

随后,在该会话中运行的所有CUDA应用程序将仅观察到第三个枚举GPU(枚举从0开始),并且它们将在其会话中将该GPU视为设备0。

这意味着您无需对应用进行任何更改,假设您的应用使用默认GPU或GPU 0。

您还可以将其扩展以使多个GPU可用,例如:

export CUDA_VISIBLE_DEVICES="2,4"

意思是通常会枚举为2和4的GPU现在将成为该会话中唯一“可见”的GPU,并且它们将枚举为0和1。

在我看来,上述方法是最简单的。选择一个“未使用”的GPU存在问题,因为:

  1. 我们需要对“使用中”进行定义
  2. 在特定时刻正在使用的GPU可能在那之后立即不再使用
  3. 最重要的是,一个未“使用”的GPU可能会异步地变为“使用中”,这意味着您会面临竞争条件。

因此,最好的建议(在我看来)是明确管理GPU。否则,您需要某种形式的作业调度程序(超出本问题的范围,在我看来)才能查询未使用的GPU并在有序方式中“预留”一个,然后再另一个应用程序尝试这样做之前。


有趣的——你是否知道OCL支持类似的功能吗? - Brian Cain
似乎AMD有类似的东西。我不知道是否有适用于OpenCL设备的通用方法。 - Robert Crovella
1
我在NVIDIA GPU上测试了一个OpenCL程序,并且使用CUDA_VISIBLE_DEVICES选择了程序要运行的GPU,因此似乎这个环境变量对于OpenCL也有效(在NVIDIA GPU上),但我不知道是否有任何规定。这只是我的观察。 - Robert Crovella

0

有一种更好(更自动化)的方法,我们在运行于巨大(且不同)集群上的PIConGPU中使用。 请在此处查看实现:https://github.com/ComputationalRadiationPhysics/picongpu/blob/909b55ee24a7dcfae8824a22b25c5aef6bd098de/src/libPMacc/include/Environment.hpp#L169

基本上:调用cudaGetDeviceCount以获取GPU数量,对它们进行迭代,并调用cudaSetDevice将其设置为当前设备并检查是否有效。这个检查可能涉及到由于CUDA中的某些错误而需要测试创建流,这使得setDevice成功,但所有后续调用都失败了,因为设备实际上正在使用中。 注意:您可能需要将GPU设置为独占模式,以便一个GPU只能被一个进程使用。如果您没有足够的一批数据,您可能希望相反:多个进程向一个GPU提交工作。因此,请根据您的需求进行调整。

其他的想法是:启动一个MPI应用程序,每个进程的排名都与GPU数量相同,并使用本地排名号码相同的设备号。这也将有助于像您这样具有不同数据集分发的应用程序。因此,您可以例如让MPI排名0处理长度为1的数据,而MPI排名1处理长度为2的数据等。

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