如何选择要在哪个GPU上运行作业?


71

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

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

echo $CUDA_VISIBLE_DEVICES

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

CUDA_VISIBLE_DEVICES=1

然后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和GPU 1上运行。

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

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


nbody应用程序具有一个命令行选项来选择要在其上运行的GPU-您可能需要研究该代码。对于更一般的情况,CUDA_VISIBLE_DEVICES应该起作用。如果不正确,则可能是您未正确使用它,您可能应该给出一个完整示例说明您尝试了什么。您还应该指出您正在使用的操作系统以及Linux,以及什么shell(例如bash,csh等)。 deviceQuery不需要任何这些,它只是一个示例应用程序来演示的行为CUDA_VISIBLE_DEVICES。正确的环境变量名称中没有$
罗伯特·克罗维拉

6
您将需要了解有关正在使用的bash shell的更多信息。这:CUDA_VISIBLE_DEVICES=1 不会永久设置环境变量(实际上,如果您只在命令行中放了它,那么它实际上没有任何用处。)。这:export CUDA_VISIBLE_DEVICES=1将为该会话的剩余时间永久设置它。您可能想研究环境变量如何在bash中工作,各种命令如何影响它们,以及持续多长时间。
罗伯特·克罗维拉

2
deviceQuery随CUDA 8一起提供,但是您必须对其进行构建。如果您阅读用于Linux的CUDA 8安装指南,它将说明如何进行构建deviceQuery
Robert Crovella

在/ usr / local / cuda / bin中,有一个cuda-install-samples- <version> .sh脚本,如果未安装示例,则可以使用该脚本。然后,在NVIDIA_Samples安装目录的1_Utilities文件夹中,找到deviceQuery。只需在该文件夹中调用make即可为您编译。如果我没记错的话,它将二进制文件复制到同一文件夹中。
Mircea

1
应该是watch -n 1 nvidia-smi...
oliversm '18

Answers:


113

该问题是由于未CUDA_VISIBLE_DEVICES在外壳程序内正确设置变量引起的。

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

export CUDA_VISIBLE_DEVICES=1

要么

CUDA_VISIBLE_DEVICES=1 ./cuda_executable

前者为当前外壳程序的生存期设置变量,后者仅为特定可执行调用的生存期设置变量。

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

export CUDA_VISIBLE_DEVICES=0,1

要么

CUDA_VISIBLE_DEVICES=0,1 ./cuda_executable

那么,如果会发生CUDA_VISIBLE_DEVICE=0什么呢?
Kurian Benoy

1
@KurianBenoy设置CUDA_VISIBLE_DEVICE=0将选择GPU 0以执行任何CUDA任务。我认为这是默认行为,因为在设置变量之前,我所有的GPU任务都将移至GPU 0,因此根据您的使用情况,可能不一定需要进行实际设置。
史蒂文·霍维尔

@ StevenC.Howell我在想CUDA_VISIBLE_DEVICE = 0意味着一个CPU系统。感谢clarrifying
库里安贝诺

1
@KurianBenoy CUDA_VISIBLE_DEVICES =“”表示CPU
runDOSrun

11

设置以下两个环境变量:

NVIDIA_VISIBLE_DEVICES=$gpu_id
CUDA_VISIBLE_DEVICES=0

在哪里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下在由Openshift 3.11编排的运行Ubuntu 18.04的Docker容器中进行了测试。


10

如果有人在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
...

如所见 这里


这很棒!我在终端而不是python中使用它,export CUDA_DEVICE_ORDER=PCI_BUS_ID然后 export CUDA_VISIBLE_DEVICES=<GPU_NUMBER>
曼恩

4

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

CUDA_VISIBLE_DEVICES=5, python test_script.py
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.