Как выбрать, на какой GPU запускать работу?

На компьютере с несколькими GPU, как мне определить, на каком графическом процессоре должно работать CUDA-задание?

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

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

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

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

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

Ответ 1

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

Ответ 2

export NVIDIA_VISIBLE_DEVICES=gpu_id export CUDA_VISIBLE_DEVICES=0

где gpu_id - это идентификатор на основе 0 графического процессора, сделанный доступным для гостевой системы (например, для среды контейнера Docker).

  • Подробнее

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

Принятое решение, основанное только на CUDA_VISIBLE_DEVICES, не скрывает (см., Например, в nvidia-smi) все другие недоступные карты (отличные от прикрепленных) и, таким образом, вызывает ошибки вычислений, если вы пытаетесь использовать их в своих алгоритмах моделирования. При таком решении другие карты просто не видны гостевой системе, но другие пользователи по-прежнему могут получать к ним доступ и распределять свои вычислительные мощности на равной основе, как и в случае ЦП (проверено).

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

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