我如何 select 在哪个 GPU 上 运行 作业?

How do I select which GPU to run a job on?

在多 GPU 计算机中,如何指定 CUDA 作业应该 运行 在哪个 GPU 上?

例如,在安装 CUDA 时,我选择安装 NVIDIA_CUDA-<#.#>_Samples 然后 运行 多个 nbody 模拟实例,但它们都 运行 在一个显卡 0; GPU 1 完全空闲(使用 watch -n 1 nvidia-dmi 进行监控)。使用

检查 CUDA_VISIBLE_DEVICES
echo $CUDA_VISIBLE_DEVICES

我发现这没有设置。我尝试使用

设置它
CUDA_VISIBLE_DEVICES=1

然后 运行再次 nbody 但它也转到了 GPU 0。

我查看了相关问题,how to choose designated GPU to run CUDA program?,但是deviceQuery命令不在CUDA 8.0 bin目录中。除了$CUDA_VISIBLE_DEVICES$,我看到其他帖子提到了环境变量$CUDA_DEVICES,但这些都没有设置,我也没有找到关于如何使用它的信息。

虽然与我的问题没有直接关系,但使用 nbody -device=1 我能够在 GPU 1 上获得应用程序 运行 但使用 nbody -numdevices=2 没有 运行 GPU 0 和 1。

我正在使用 bash shell 在 CentOS 6.8 上使用 CUDA 8.0、2 GTX 1080 GPU 和 NVIDIA 驱动程序 367.44 在 运行ning 系统上进行测试。

我知道在使用 CUDA 编写代码时,您可以管理和控制使用哪些 CUDA 资源,但是当 运行编译编译的 CUDA 可执行文件时,我如何从命令行管理它?

问题是由于未正确设置 shell 中的 CUDA_VISIBLE_DEVICES 变量引起的。

例如,要指定 CUDA 设备 1,您可以使用

设置 CUDA_VISIBLE_DEVICES
export CUDA_VISIBLE_DEVICES=1

CUDA_VISIBLE_DEVICES=1 ./cuda_executable

前者为当前 shell 的生命周期设置变量,后者仅为该特定可执行文件调用的生命周期设置变量。

如果要指定多个设备,请使用

export CUDA_VISIBLE_DEVICES=0,1

CUDA_VISIBLE_DEVICES=0,1 ./cuda_executable

设置以下两个环境变量:

NVIDIA_VISIBLE_DEVICES=$gpu_id
CUDA_VISIBLE_DEVICES=0

其中 gpu_id 是您选择的 GPU 的 ID,如主机系统的 nvidia-smi(从 0 开始的整数)中所示,它将提供给来宾系统(例如, Docker容器环境)。

您可以通过在访客系统的终端中检查 nvidia-smi 运行 中的 Bus-Id 参数来验证为 gpu_id 的每个值选择了不同的卡) .

更多信息

这种基于NVIDIA_VISIBLE_DEVICES的方法只向系统暴露了一张卡(本地ID为零),因此我们也将另一个变量CUDA_VISIBLE_DEVICES硬编码为0(主要是为了防止它从默认为表示没有 GPU 的空字符串。

请注意,环境变量应在客户系统启动之前设置(因此没有机会在 Jupyter Notebook 的终端中设置),例如在 Kubernetes 中使用 docker run -e NVIDIA_VISIBLE_DEVICES=0env 或Openshift.

如果您想要 GPU 负载平衡,请在每个来宾系统启动时使 gpu_id 随机。

如果使用 python 进行设置,请确保所有环境变量都是 using strings,包括数字变量。

您可以通过检查 nvidia-smi 的 Bus-Id 参数(在访客系统的终端 运行 中)来验证是否为 gpu_id 的每个值选择了不同的卡.

仅基于 CUDA_VISIBLE_DEVICES 的公认解决方案不会隐藏其他卡(与固定卡不同),因此如果您尝试在启用 GPU 的 python 中使用它们会导致访问错误包裹。使用此解决方案,其他卡对访客系统不可见,但其他用户仍然可以访问它们并在平等的基础上共享他们的计算能力,就像 CPU 的(已验证)。

这也优于使用 Kubernetes / Openshift 控制器 (resources.limits.nvidia.com/gpu) 的解决方案,后者会对分配的卡施加锁定,将其从可用资源池中移除(因此具有 GPU 的容器数量访问不能超过物理卡的数量)。

这已经在 docker 容器 运行ning Ubuntu 18.04 或 20.04 中的 CUDA 8.0、9.0、10.1 和 11.2 下进行了测试,并由 Openshift 3.11 编排。

如果其他人在 Python 中执行此操作并且它不起作用,请尝试在 之前设置它 执行 pycuda 和 tensorflow 的导入。

即:

import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
...
import pycuda.autoinit
import tensorflow as tf
...

here.

您还可以在命令行中设置 GPU,这样您就不需要将设备硬编码到脚本中(这在没有多个 GPU 的系统上可能会失败)。假设您想在 5 号 GPU 上 运行 您的脚本,您可以在命令行中键入以下内容,它将在 GPU#5 上 运行 您的脚本一次:

CUDA_VISIBLE_DEVICES=5, python test_script.py

对于随机 GPU,您可以这样做:

export CUDA_VISIBLE_DEVICES=$((( RANDOM % 8 )))

选择利用率最低的 GPU

使 xml2json 在您的路径中可用后,您可以 select 利用率最低的 N 个 GPU:

export CUDA_VISIBLE_DEVICES=$(nvidia-smi -x -q | xml2json | jq '.' | python -c 'import json;import sys;print(",".join([str(gpu[0]) for gpu in sorted([(int(gpu["minor_number"]), float(gpu["utilization"]["gpu_util"].split(" ")[0])) for gpu in json.load(sys.stdin)["nvidia_smi_log"]["gpu"]], key=lambda x: x[1])[:2]]))')

如果您需要单个 GPU 或根据可用 GPU 的最大数量的任意数量,只需将 [:2] 替换为 [:1]