Как выбрать графический процессор для выполнения задания?

Как на компьютере с несколькими графическими процессорами определить, на каком графическом процессоре должно выполняться задание CUDA?

Например, при установке 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.

Я посмотрел на связанный вопрос, как выбрать назначенный графический процессор для запуска программы CUDA?, но deviceQuery Команда не находится в каталоге bin CUDA 8.0. В дополнение к $CUDA_VISIBLE_DEVICES$Я видел другие посты ссылающиеся на переменную окружения $CUDA_DEVICES но они не были установлены, и я не нашел информации о том, как его использовать.

Хотя не имеет прямого отношения к моему вопросу, используя nbody -device=1 Я смог заставить приложение работать на GPU 1, но с помощью nbody -numdevices=2 не работал на обоих GPU 0 и 1.

Я тестирую это в системе, работающей с использованием оболочки bash, на CentOS 6.8, с CUDA 8.0, 2 графическими процессорами GTX 1080 и драйвером NVIDIA 367.44.

Я знаю, что при написании с использованием CUDA вы можете управлять и контролировать, какие ресурсы CUDA использовать, но как бы я управлял этим из командной строки при запуске скомпилированного исполняемого файла CUDA?

8 ответов

Решение

Проблема была вызвана не установкой 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

В случае, если кто-то другой делает это на 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
...

Как увидел здесь.

Вы также можете установить графический процессор в командной строке, чтобы вам не нужно было жестко закодировать устройство в свой скрипт (что может привести к сбою в системах без нескольких графических процессоров). Предположим, вы хотите запустить свой скрипт на GPU №5, вы можете ввести в командной строке следующее, и он запустит ваш скрипт только один раз на GPU №5:

CUDA_VISIBLE_DEVICES=5, python test_script.py

Установите следующие две переменные среды:

NVIDIA_VISIBLE_DEVICES=$gpu_id
CUDA_VISIBLE_DEVICES=0

где gpu_id это идентификатор выбранного вами графического процессора, как показано в хост-системе nvidia-smi (целое число, отсчитываемое от 0), которое будет доступно для гостевой системы (например, для среды контейнера D ocker).

Вы можете убедиться, что для каждого значения gpu_id выбрана другая карта, проверив Bus-Id параметр в nvidia-smi запустить в терминале в гостевой системе).

Больше информации

Этот метод основан на NVIDIA_VISIBLE_DEVICES предоставляет системе только одну карту (с нулевым локальным идентификатором), поэтому мы также жестко кодируем другую переменную, CUDA_VISIBLE_DEVICES до 0 (в основном, чтобы не допустить, чтобы по умолчанию была пустая строка, указывающая на отсутствие графического процессора).

Обратите внимание, что переменная среды должна быть установлена ​​до запуска гостевой системы (поэтому нет шансов сделать это в терминале Jupyter Notebook), например, используя docker run -e NVIDIA_VISIBLE_DEVICES=0 или env в Kubernetes или Openshift.

Если вам нужна балансировка нагрузки на GPU, сделайте gpu_id случайным образом при каждом запуске гостевой системы.

Если вы устанавливаете это с помощью python, убедитесь, что вы используете строки для всех переменных среды, включая числовые.

Вы можете убедиться, что для каждого значения gpu_id путем проверки nvidia-smiПараметр Bus-Id (в терминале, запущенном в гостевой системе).

Принятое решение на основе CUDA_VISIBLE_DEVICESсам по себе не скрывает другие карты (отличные от закрепленной) и, таким образом, вызывает ошибки доступа, если вы пытаетесь использовать их в пакетах python с поддержкой GPU. С помощью этого решения другие карты не видны гостевой системе, но другие пользователи по-прежнему могут получить к ним доступ и поделиться своей вычислительной мощностью на равной основе, как и с CPU (проверено).

Это также предпочтительнее решений с использованием контроллеров Kubernetes / Openshift (resources.limits.nvidia.com/gpu), что наложило бы блокировку на выделенную карту, удалив ее из пула доступных ресурсов (чтобы количество контейнеров с доступом к GPU не могло превышать количество физических карт).

Это было протестировано под CUDA 8.0, 9.0 и 10.1 в контейнерах докеров под управлением Ubuntu 18.04 под управлением Openshift 3.11.

Выберите GPU с наименьшей загрузкой

После того, как вы сделаете xml2json доступным на вашем пути, вы можете выбрать N графических процессоров с наименьшей загрузкой:

      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]]))')

Просто замените [:2]по [:1]если вам нужен один графический процессор или любое количество в соответствии с максимальным количеством доступных графических процессоров.

Для случайного графического процессора вы можете сделать это:

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

NVIDIA_CUDA-<#.#>_ Легкий телефон

Могу ли я установить несколько графических процессоров в коде Python следующим образом:

      os.environ["CUDA_VISIBLE_DEVICES"] = "1,2"
Другие вопросы по тегам