Nvidia GPU внутри контейнера docker

Шпаргалка о том, как внутри контейнера docker использовать GPU или тензорный ускоритель от Nvidia. Расскажу как установить, настроить и тестировать.

Сначала убеждаемся, что на сервере вообще никогда не было установлено драйверов nvidia. Если были, то удаляем или надеемся на удачу, чтобы не возникло ошибки в процессе установки.

На материнскую систему сервера ставим основное:

apt install build-essential gcc-multilib dkms

Перезапускаем весь сервер. После чего ставим драйвер карты, который скачиваем тут (почему-то на русскоязычном ресурсе nvidia нет драйверов для Tesla и других вычислителей без видео выходов):

https://www.nvidia.com/Download/index.aspx

Запускаем скаченный на сервер установщик от лица рута:

chmod +x NVIDIA-Linux-x86_64-***.run

./NVIDIA-Linux-x86_64-***.run

Начнётся установка, на все вопросы отвечаем положительно. Проверяем результаты, запустив:

nvidia-smi

Если ускоритель определяется верно, то идём на эту страницу:

https://docs.nvidia.com/…/install-guide.html

Там просят сначала установить nvidia-container-tools. Делается это через добавление репозитория, смотрите инструкцию там.

Затем необходимо выполнить несколько команд для настройки docker и containerd:

nvidia-ctk runtime configure —runtime=docker

nvidia-ctk runtime configure —runtime=containerd

На этом вся установка на стороне сервера закончена. Перезапускаем сервер. После чего для проверки правильности работы ускорения внутри докер контейнера стоит запустить проверочный экземпляр командой:

docker run —rm —runtime=nvidia —gpus all ubuntu nvidia-smi

Если всё отработало верно и показалась привычная таблица nvidia-smi с перечисленными ускорителями, то можно начать создавать контейнер и запихивать туда tensorflow/torch и т.п. Но учтите, что при запуске контейнеров в будущем придётся писать ключи «—runtime=nvidia —gpus all», чтобы доступ к GPU был изнутри контейнеров.

Попробуем сделать контейнер со всем нужным ПО. Для этого за основу стоит брать контейнеры nvidia/cuda отсюда:

https://hub.docker.com/r/nvidia/cuda/tags

Внимание! Если предполагается, что в контейнере будет работать tensorflow/torch, то они поддерживают далеко не все версии ПО. Поэтому сначала смотрим условия на версию cuda тут:

https://www.tensorflow.org/install/pip?hl=ru

А только затем выбираем нужный контейнер nvidia/cuda для установки. Я выбрал с пометкой runtime (потому что в описании к ним стоит «cuDNN is available», но стоит проверить верно ли описанное далее для других версий).

На момент написания статьи tensorflow работает только с cuda версии не выше 11.8.0, поэтому скачиваю именно её контейнер:

docker pull nvidia/cuda:11.8.0-runtime-ubuntu22.04

Внутри контейнера первым делом ставим:

apt install cuda-toolkit nvidia-cuda-toolkit libcudnn8

Далее от лица нужного пользователя:

pip install —upgrade pip

pip install nvidia-cudnn-cu11 tensorflow torch tensorrt pycuda

Пакетов будет установлено очень много (несколько гигабайт!). Я ещё добавляю несколько AutoML библиотек (autokeras, tpot, flaml), зависимости от которых на текущий момент не конфликтуют и вполне себе работают вместе:

pip install jupyterlab autokeras numpy scipy scikit-learn pandas joblib tpot ipywidgets flaml

После чего надо настроить переменные окружения. Для этого в конец файла ~/.bashrc добавляем такие строки (тут укажите нужную версию Python вместо 3.10 и версию cuda вместо 11.8, перепроверьте все пути на существование):

export CUDNN_PATH=$HOME/.local/lib/python3.10/site-packages/nvidia/cudnn

export LD_LIBRARY_PATH=$CUDNN_PATH/lib:/usr/local/cuda/lib64:/usr/local/cuda/lib64

export LD_LIBRARY_PATH=$HOME/.local/lib/python3.10/site-packages/tensorrt_libs:$LD_LIBRARY_PATH

export PATH=/usr/local/cuda-11.8/targets/x86_64-linux/include:$PATH

export XLA_FLAGS=—xla_gpu_cuda_data_dir=/usr/lib/cuda

export XLA_FLAGS=—xla_gpu_cuda_data_dir=/usr/local/cuda-11.8

В будущем чтобы TF не отправлял назойливые предупреждения можно добавить ещё и:

export TF_CPP_MIN_LOG_LEVEL=2

После этого перезапускам контейнер:

docker restart id_контейнера

И выполняем внутри контейнера простейшую операцию:

python3 -c «import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))»

Если во время выполнения скрипта не будет показано предупреждений типа «Skipping registering GPU devices…», то всё работает верно. Но лучше убедиться в этом, запуская тяжёлые вычисления и проверяя загрузку карты через nvidia-smi.