Как выбрать, на какой 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
случайным при каждом запуске гостевой системы.