Шпаргалка о том, как внутри контейнера 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.