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

时间:2015-06-18 19:42:47

标签: c++ cuda gpu multi-gpu

背景

我编写了一个CUDA程序,对一系列符号进行处理。该程序并行处理所有符号序列,并规定所有序列具有相同的长度。我将我的数据分组成组,每组完全由相同长度的序列组成。该计划一次处理1个小组。

问题:

我在具有4个GPU的Linux机器上运行我的代码,并希望通过运行我的程序的4个实例(每个GPU 1个)来利用所有4个GPU。是否可以让程序选择另一个CUDA应用程序无法运行的GPU?当程序在具有更多或更少GPU的不同硬件上运行时,我不想硬编码会导致问题的任何事情。

2 个答案:

答案 0 :(得分:5)

environment variable 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 一样。 / p>

这意味着您不必对此方法的应用程序进行任何更改,假设您的应用使用默认的GPU或GPU 0。

您还可以对此进行扩展以使多个GPU可用,例如:

export CUDA_VISIBLE_DEVICES="2,4"

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

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

  1. 我们需要“使用中”的定义
  2. 在特定时刻使用的GPU可能不会在此之后立即使用
  3. 最重要的是,没有“正在使用”的GPU可能会异步“使用”,这意味着您将面临竞争条件。
  4. 所以最好的建议(IMO)是明确管理GPU。否则,您需要某种形式的作业调度程序(在此问题的范围之外,IMO)才能查询未使用的GPU并在另一个应用程序尝试之前“保留”一个,以有序的方式。

答案 1 :(得分: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数据等。