如何选择运行作业的GPU?

Ste*_*ell 41 cuda nvidia

在多GPU计算机中,如何指定应运行CUDA作业的GPU?

作为一个例子,在安装CUDA时,我选择安装NVIDIA_CUDA-<#.#>_Samples然后运行几个nbody模拟实例,但它们都在一个GPU 0上运行; GPU 1完全空闲(使用监控watch -n 1 nvidia-dmi).检查CUDA_VISIBLE_DEVICES使用

echo $CUDA_VISIBLE_DEVICES
Run Code Online (Sandbox Code Playgroud)

我发现这没有设定.我尝试使用它

CUDA_VISIBLE_DEVICES=1
Run Code Online (Sandbox Code Playgroud)

然后nbody再次运行但它也进入了GPU 0.

我看了相关的问题,如何选择指定的GPU来运行CUDA程序?,但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.

我知道在使用CUDA编写时,您可以管理和控制要使用的CUDA资源,但在运行已编译的CUDA可执行文件时,如何从命令行管理?

Ste*_*ell 76

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

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

export CUDA_VISIBLE_DEVICES=1
Run Code Online (Sandbox Code Playgroud)

要么

CUDA_VISIBLE_DEVICES=1 ./cuda_executable
Run Code Online (Sandbox Code Playgroud)

前者为当前shell的生命周期设置变量,后者仅针对特定可执行调用的生命周期.

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

export CUDA_VISIBLE_DEVICES=0,1
Run Code Online (Sandbox Code Playgroud)

要么

CUDA_VISIBLE_DEVICES=0,1 ./cuda_executable
Run Code Online (Sandbox Code Playgroud)

  • 如何设置多个设备?`export CUDA_VISIBLE_DEVICES = 0,1`? (3认同)
  • @KurianBenoy 设置 `CUDA_VISIBLE_DEVICE=0` 将选择 GPU 0 来执行任何 CUDA 任务。我认为这是默认行为,因为在我设置变量之前,我所有的 GPU 任务都将转到 GPU 0,因此可能没有必要实际设置它,具体取决于您的用例。 (2认同)
  • @KurianBenoy CUDA_VISIBLE_DEVICES="" 表示 CPU (2认同)

Luc*_*cas 22

如果其他人在 Python 中执行此操作并且无法正常工作,请尝试在导入 pycuda 和 tensorflow之前对其进行设置。

IE:

import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
...
import pycuda.autoinit
import tensorflow as tf
...
Run Code Online (Sandbox Code Playgroud)

这里所见。


mir*_*phd 13

设置以下两个环境变量:

NVIDIA_VISIBLE_DEVICES=$gpu_id
CUDA_VISIBLE_DEVICES=0
Run Code Online (Sandbox Code Playgroud)

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

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

更多信息

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

请注意,环境变量应该在来宾系统启动之前设置(因此没有机会在您的 Jupyter Notebook 的终端中执行此操作),例如使用docker run -e NVIDIA_VISIBLE_DEVICES=0env在 Kubernetes 或 Openshift 中。

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

如果使用 python 设置它,请确保对所有环境变量使用字符串,包括数字变量。

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

接受的基于CUDA_VISIBLE_DEVICES单独的解决方案不会隐藏其他卡(与固定卡不同),因此如果您尝试在支持 GPU 的 Python 包中使用它们,则会导致访问错误。使用此解决方案,访客系统看不到其他卡,但其他用户仍然可以访问它们并在平等的基础上共享他们的计算能力,就像使用 CPU 一样(已验证)。

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

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


Jan*_*Jan 11

更新

下面的评论中有一个由 lukaszzenko 修改的解决方案,它使用相同的想法并产生相同的输出。考虑使用它来代替,因为它更简洁:

export CUDA_VISIBLE_DEVICES=$(nvidia-smi --query-gpu=memory.free,index --format=csv,nounits,noheader | sort -nr | head -1 | awk '{ print $NF }')
Run Code Online (Sandbox Code Playgroud)

选择利用率最低的GPU(原方案)

在路径中提供xml2json后,您可以选择利用率最低的 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]]))')
Run Code Online (Sandbox Code Playgroud)

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

  • 更简单的方法是 `export CUDA_VISIBLE_DEVICES=$(nvidia-smi --query-gpu=memory.free,index --format=csv,nounits,noheader | sort -nr | head -1 | awk '{ print $ NF }'`) (12认同)

Edu*_*era 9

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

CUDA_VISIBLE_DEVICES=5, python test_script.py
Run Code Online (Sandbox Code Playgroud)