Трансляция GPU внутрь OpenStack
Перевод с собственной редакцией и дополнениями статьи из блога Jimm Denton
Для решения данной задачи необходима поддержка аппаратной виртуализации (Hardware-assisted virtualization) и виртуализации ввода/вывода (IOMMU virtualization).
Поддержка этих технологий должна быть реализована как на уровне аппаратной платформы, так и на уровне программной реализации (гипервизора).
Суть аппаратной виртуализации заключается в поддержке процессором специальных инструкций, позволяющих организовать эмуляцию всех аппаратных устройств для виртуальной машины.
При этом ВМ не зависит от архитектуры аппаратной платформы хоста, но может использовать напрямую его устройства, а ее производительность сравнима с производительностью хоста.
На основе виртуализации ввода/вывода виртуальной машине с помощью «проброса» (pass-through) можно предоставить прямой доступ к устройствам на шине PCI и PCI-E.
Так можно организовать прямой доступ к видеокарте и USB-контроллерам и другим устройствам хост-машины.
Чтобы передать GPU на виртуальные машины, вам нужно включить расширения VT-d или AMD-Vi (IOMMU) в BIOS.
Для установки видеокарты в сервер может понадобиться переходник (raiser).
Необходимо иметь ввиду, что при использовании гипервизора Xen нельзя «прокинуть» в ВМ видеокарты на чипах Nvidia (кроме Quadro и Grid).
В KVM таких ограничений нет, кроме очень старых моделей видеокарт.
IOMMU
Проверим наличие поддержки IOMMU, выполнив команду:
Затем обновите конфигурацию grub,/etc/default/grub
чтобы включить поддержку IOMMU.
Intel grub
Для Intel добавьте intel_iommu=on
в конец GRUB_CMDLINE_LINUX
строки в файле конфигурации grub /etc/default/grub
AMD grub
iommu=pt
включает маркировку iommu только для устройств, настроенных для сквозного доступа (pci passthrough), позволяя игнорировать ее для локальных устройств хоста.
Пересобираем ядро:
Проверим, что IOMMU драйвер активирован в ядре:
Пример успешного вывода:
[ 1.456466] pci 0000:60:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456519] pci 0000:40:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456545] pci 0000:20:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456565] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456625] pci 0000:e0:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456661] pci 0000:c0:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456696] pci 0000:a0:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.456726] pci 0000:80:00.2: AMD-Vi: IOMMU performance counters supported
[ 1.532953] pci 0000:60:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532962] pci 0000:40:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532968] pci 0000:20:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532974] pci 0000:00:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532980] pci 0000:e0:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532986] pci 0000:c0:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532991] pci 0000:a0:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.532997] pci 0000:80:00.2: AMD-Vi: Found IOMMU cap 0x40
[ 1.547155] perf/amd_iommu: Detected AMD IOMMU #0 (2 banks, 4 counters/bank).
[ 1.547171] perf/amd_iommu: Detected AMD IOMMU #1 (2 banks, 4 counters/bank).
[ 1.547188] perf/amd_iommu: Detected AMD IOMMU #2 (2 banks, 4 counters/bank).
[ 1.547204] perf/amd_iommu: Detected AMD IOMMU #3 (2 banks, 4 counters/bank).
[ 1.547220] perf/amd_iommu: Detected AMD IOMMU #4 (2 banks, 4 counters/bank).
[ 1.547235] perf/amd_iommu: Detected AMD IOMMU #5 (2 banks, 4 counters/bank).
[ 1.547251] perf/amd_iommu: Detected AMD IOMMU #6 (2 banks, 4 counters/bank).
[ 1.547270] perf/amd_iommu: Detected AMD IOMMU #7 (2 banks, 4 counters/bank).
[ 1.670363] AMD-Vi: AMD IOMMUv2 loaded and initialized
AMD-Vi: AMD IOMMUv2 functionality not available on this system - This is not a bug.
,
то необходимо проверить в BIOS, включены-ли два режима:
- IOMMU -> Enabled- DMAr -> Enabled
Для AMD серверов ищите эти настройки в
AMD CBS -> NBIO Common Options
Проверим линк на группу iommu:
*** Важно! *** Если в системе несколько видеокарт, то их IOMMU-группы ни в коем случае не должны пересекаться - иначе, при создании очередного инстанса, в логеnova-compute.log
мы увидим соббщение следующего типа: PCI claim failed
.Если проанализировать лог, то мы увидим странную картину - планировщик запрашивает PCI-слот, который уже занят другой ВМ, в то время как есть еще другие свободные слоты, но
nova scheduler
их почему-то отказывается видеть.Чтобы исправить эту ситуацию, в некоторых случаях помогает смена прошивки BIOS - например, такой случай был на моей практике с сервером Asus.
Проверим, что драйвер vfio-pci разрешен в системе:
Если все хорошо, будет примерно такой вывод:[ 3.243739] VFIO - User Level meta-driver version: 0.3
[ 3.252081] vfio-pci 0000:01:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=io+mem:owns=io+mem
[ 3.276061] vfio_pci: add [10de:1c03[ffffffff:ffffffff]] class 0x000000/00000000
[ 3.296056] vfio_pci: add [10de:10f1[ffffffff:ffffffff]] class 0x000000/00000000
Манипуляции с драйвером
После перезагрузки хоста следующим шагом в подготовке графического процессора к сквозной передаче является проверка правильности настройки драйверов. Вот несколько параметров, которые потребуются по мере прохождения процесса:
- Vendor ID
- Product ID
- PCI Bus ID
Все эти параметры определяем с помощью lspci
:
$ sudo lspci -nn | grep NVIDIA
24:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP106GL [Quadro P2000] [10de:1c30] (rev a1)
24:00.1 Audio device [0403]: NVIDIA Corporation GP106 High Definition Audio Controller [10de:10f1] (rev a1)
В этом примере PCI Bus ID is 24:00.0
, Vendor ID is 10de
и Product ID is 1c30
.
Из листинга видно, что ядро обнаружило GPU и загрузило графический драйвер nouveau (в случае карт NVIDIA).:
$ sudo lspci -s 24:00.0 -k
24:00.0 VGA compatible controller: NVIDIA Corporation GP106GL [Quadro P2000] (rev a1)
Subsystem: Dell GP106GL [Quadro P2000]
Kernel driver in use: nouveau
Kernel modules: nvidiafb, nouveau
Важный момент заключается в том, что пока видеокарта привязана к графическому драйверу на хосте, транзит GPU внутрь ВМ невозможен.
Blacklist
Чтобы предотвратить загрузку драйверов при старте системы, нужно внести их в черный список. Для этого добавляем в файл /etc/modprobe.d/blacklist-nvidia.conf
две строки с драйверами.
Whitelist
Теперь нам надо внести в белый список драйвер vfio-pci , который будет осуществлять привязку видеокарты внутрь гипервизора.
Определим номер шины PCI и идентификаторы прпоизводителя и устройства Vendor-ID:Device-ID графического адаптера, например:
lspci -nn | grep -i nvidia
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] [10de:1c03] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation GP106 High Definition Audio Controller [10de:10f1] (rev a1)
/etc/modprobe.d/vfio.conf
со следующим содержимым:
# create new : for [ids=***], specify [Vendor-ID : Device-ID]
options vfio-pci ids=10de:1c03,10de:10f1
Напомню, что 10de
- это Vendor ID, а 1c30
- Product ID видеокарты, а 10f1
- Product ID аудиокарты графического процессора.
Теперь добавим vfio-pci
драйвер в файл /etc/modules-load.d/modules.conf
для автоматической загрузки при старте системы.
После перезагрузки хоста, проверим, что ядро ОС теперь использует именно драйвер vfio-pci
$ sudo lspci -s 24:00.0 -nnk
24:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP106GL [Quadro P2000] [10de:1c30] (rev a1)
Subsystem: Dell GP106GL [Quadro P2000] [1028:11b3]
Kernel driver in use: vfio-pci
Kernel modules: nvidiafb, nouveau
Подстройка Nova
Службу Nova Compute необходимо настроить в двух местах, чтобы распознать и использовать GPU.
Во-первых, настройте белый список транзитной передачи PCI на вычислительном узле, где находится графический процессор.
Обновите раздел [pci] /etc/nova/nova.conf файла следующим образом:
Убедитесь, что vendor_id и product_id совпадают с полученными ранее.
Белый список может быть ограничен ссылкой на конкретный слот PCI, если это необходимо, но, поскольку в нашем примере установлена только одна видеокарта, в этом нет необходимости.
Перезапустите nova-compute:
Затем настройте псевдоним PCI (PF) в файле /etc/nova/nova.conf на узле, в котором размещается служба Nova API - обычно это контроллер.
Для Nvidia:
[pci]
alias = { "vendor_id":"10de", "product_id":"1c30", "device_type":"type-PCI", "name":"quadro-p2000" }
[pci]
alias = { "vendor_id":"10de", "product_id":"1c30", "device_type":"type-PF", "name":"tesla-t4" }
Перезагружаем Nova API:
Теперь, необходимо указать планировщику Nova, чтобы он применял фильтр PCI Passthrough.
Для этого надо проверить, есть ли фильтр PciPassthroughFilter в параметре enabled_filters
и/или available_filters
в файле /etc/nova/nova.conf.
Если такого фильтра нет, то его необходимо добавить по следущему примеру:
[filter_scheduler]
enabled_filters = RetryFilter, AvailabilityZoneFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, PciPassthroughFilter
available_filters = nova.scheduler.filters.all_filters
Кастомизация flavor
Nova использует метаданные и свойства образа, чтобы определить, какие ресурсы должны быть связаны с экземпляром.
В случае сквозной передачи GPU необходимо настроить вариант со свойством pci_passthrough:alias
.
Создаем новый вариант флавора с 6 виртуальными ядрами, 8 ГБ ОЗУ, диском на 40 ГБ и свойствомpci_passthrough:alias
, которое использует псевдоним нашей видеокарты quadro-p2000
.
openstack flavor create \
--vcpus 6 \
--ram 8192 \
--disk 40 \
--property "pci_passthrough:alias"="quadro-p2000:1" \
6-8-40-gpu
По спецификации nova, флавору может быть сопоставлен только один графический процессор.
Установка Nvidia driver в имидже ОС
Описание установки CUDA на сайте производителя
Ставим на Ubuntu 20
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub
sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ /"
sudo apt-get update
sudo apt-get -y install cuda
Если была попытка установить в другом порядке или после удаления части компонетов cuda при установке выдает ошибки зависимостей, то надо сделать так.
Установка драйвера на Ubuntu 22.04
Приведу просто список команд для установки свободного (без лицензии) драйвера в headless-режиме (без установки X11):
apt purge snapd
apt update
apt upgrade
lspci | grep -i nvidia
ubuntu-drivers devices
apt install -y ubuntu-drivers-common alsa-utils
reboot
apt install -y nvidia-headless-550-open nvidia-utils-550
nvidia-smi
Создание инстанса
Чтобы протестировать новые возможности сквозной передачи графического процессора, разверните экземпляр виртуальной машины:
openstack server create \
--flavor 6-8-40-gpu \
--image ubuntu-bionic \
--network LAN \
--key-name imac-rsa \
--security-group plex \
vm-with-gpu
После создания ВМ, увидим ее в списке.
# openstack server list
+--------------------------------------+-------------------+---------+-------------------+---------------+---------------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+-------------------+---------+-------------------+---------------+---------------+
| 854ba22b-52c0-44a1-ab66-b78eba142bc5 | vm-with-gpu | ACTIVE | LAN=192.168.2.111 | ubuntu-bionic | 6-8-40-gpu |
+--------------------------------------+-------------------+---------+-------------------+---------------+---------------+
Войдите в систему и убедитесь, что GPU присутствует:
ubuntu@vm-with-gpu:~$ lspci | grep NVIDIA
00:06.0 VGA compatible controller: NVIDIA Corporation GP106GL [Quadro P2000] (rev a1)
Для лучшей производительности обновленные драйверы можно установить из исходного репозитория Ubuntu или с веб-сайта NVIDIA. В данном случае установим драйверы из репозитория:
$ sudo apt update
$ sudo apt install ubuntu-drivers-common
$ ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:06.0 ==
modalias : pci:v000010DEd00001C30sv00001028sd000011B3bc03sc00i00
vendor : NVIDIA Corporation
model : GP106GL [Quadro P2000]
driver : nvidia-driver-390 - distro non-free recommended
driver : xserver-xorg-video-nouveau - distro free builtin
Утилита рекомендует nvidia-driver-390
драйвер, но могут быть доступны более новые драйверы.
После перезагрузки экземпляра убедитесь, что новые драйверы были установлены с помощью lspci
и nvidia-smi
:
ubuntu@vm-with-gpu:~$ sudo lspci -nnk -s 00:06.0
00:06.0 VGA compatible controller [0300]: NVIDIA Corporation GP106GL [Quadro P2000] [10de:1c30] (rev a1)
Subsystem: Dell GP106GL [Quadro P2000] [1028:11b3]
Kernel driver in use: nvidia <---
Kernel modules: nvidiafb, nvidia_drm, nvidia
ubuntu@vm-with-gpu:~$ nvidia-smi
Wed May 8 18:08:14 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.116 Driver Version: 390.116 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Quadro P2000 Off | 00000000:00:06.0 Off | N/A |
| 0% 38C P0 19W / 75W | 0MiB / 5059MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
Все хорошо, теперь приступаем к тестированию.
Тестирование
Лучший способ сравнить результаты - запустить транскодер. Запускаем AppleTV 4 (HD), чтобы заставить Plex перекодировать фильм 4K в 1080p. Для этого вам понадобится Plex Pass для включения аппаратного ускорения, но могут быть и альтернативные методы проверки.
Посмотрите на статистику ЦП перед воспроизведением фильма:
Как только фильм начал воспроизводиться, загрузка процессора увеличилась более чем на 85%:
Взгляд на панель инструментов Plex отражает программную транскодировку (обратите внимание на отсутствие «hw»):
Мы видим, что Quadro P2000 просто стоит и не используется:
Wed May 8 19:04:40 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.116 Driver Version: 390.116 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Quadro P2000 Off | 00000000:00:06.0 Off | N/A |
| 0% 38C P0 19W / 75W | 0MiB / 5059MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
Включение аппаратного ускорения в настройках сервера Plex и перезапуск фильма отразили значительное снижение загрузки ЦП:
Падение с 80% до ~50%? Неплохо, но не очень впечатляет. Панель инструментов Plex показывает, что аппаратное перекодирование включено:
Мы видим, что Quadro P2000 работает, но не в полную мощь:
Wed May 8 19:11:03 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.116 Driver Version: 390.116 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Quadro P2000 Off | 00000000:00:06.0 Off | N/A |
| 49% 42C P0 19W / 75W | 161MiB / 5059MiB | 1% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 26847 C /usr/lib/plexmediaserver/Plex Transcoder 151MiB |
+-----------------------------------------------------------------------------+
Оказывается, транскодирование с полной разгрузкой еще не поддерживается в Plex Media Server для Linux. Дальнейшие исследования показалт, что можно значительно больше нагрузить видеокарту, если использовать некоторые флаги FFmpeg.
Чтобы это задействовать, можно использовать скрипт.
Включаем NVDEC
Чтобы улучшить “занятость” видеопроцессора, добавим флаг для включения механизма NVDEC.
#!/bin/bash
marap=$(cut -c 10-14 <<<"$@")
if [ $marap == "mpeg4" ]; then
exec /usr/lib/plexmediaserver/PlexTranscoder "$@"
else
exec /usr/lib/plexmediaserver/PlexTranscoder -hwaccel nvdec "$@"
fi
Перезапустив процесс, мы видим, что загрузка ЦП падает ниже 20%:
nvidia-smi
показывает, что GPU почти не потеет, но работает превосходно:
Wed May 8 19:25:14 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.116 Driver Version: 390.116 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Quadro P2000 Off | 00000000:00:06.0 Off | N/A |
| 49% 41C P0 21W / 75W | 1034MiB / 5059MiB | 11% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 27118 C ...ib/plexmediaserver/Plex Transcoder Orig 1024MiB |
+-----------------------------------------------------------------------------+
20.02.2022 translated by aizaro@mail.ru 18.09.2024 last updated