【问题标题】:Is it possible to execute multiple instances of a CUDA program on a multi-GPU machine?是否可以在多 GPU 机器上执行多个 CUDA 程序实例?
【发布时间】:2015-06-18 19:42:47
【问题描述】:

背景:

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

问题:

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

【问题讨论】:

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

标签: c++ cuda gpu multi-gpu


【解决方案1】:

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

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

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

export CUDA_VISIBLE_DEVICES="2,4"

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

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

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

因此,最好的建议 (IMO) 是明确管理 GPU。否则,您需要某种形式的作业调度程序(在此问题的范围之外,IMO)能够查询未使用的 GPU 并在另一个应用程序尝试这样做之前以有序的方式“保留”一个。

【讨论】:

  • 有趣——你知道 OCL 是否支持类似的功能吗?
  • 看来AMD has something similar。不知道OpenCL设备有没有通用的方法。
  • 我在 NVIDIA GPU 上测试了一个 OpenCL 程序,我能够使用 CUDA_VISIBLE_DEVICES 选择程序将在其上运行的 GPU,所以这个环境变量似乎也适用于 OpenCL(在 NVIDIA GPU),但我不知道这是在任何地方指定的。这只是我的观察。
【解决方案2】:

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

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

其他想法是:启动一个 MPI 应用程序,每个 rank 的进程数与 GPU 的数量相同,并使用与本地 rank 号相同的设备号。这也有助于像您这样具有不同数据集要分发的应用程序。所以你可以例如有 MPI rank 0 进程 length1-data 和 MPI rank 1 进程 length2-data 等。

【讨论】:

    猜你喜欢
    • 2011-05-19
    • 2014-02-22
    • 2012-10-01
    • 2015-10-17
    • 1970-01-01
    • 2011-10-22
    • 2018-12-05
    • 2021-08-21
    • 2022-08-17
    相关资源
    最近更新 更多