virtio-nvgpu: открытый проект даёт гостевым KVM почти нативный доступ к GPU Nvidia

virtio-nvgpu, открытый проект, который пробрасывает ioctl-вызовы ядерного драйвера Nvidia между гостевой Linux-системой в KVM и хостом на уровне ABI драйвера (вызовы к /dev/nvidia*), а не на уровне графического API. Благодаря этому гость запускает собственные немодифицированные пользовательские драйверы Nvidia, те же библиотеки Vulkan, OpenGL, CUDA и NVENC, что работают с той же картой напрямую, а физическая видеокарта при этом остаётся на хосте. Цель проекта, headless-стриминг: композитор внутри виртуальной машины рендерит, компонует и кодирует кадры прямо на GPU, а наружу уходит только сжатое видео; монитора у такой VM нет.
Проект протестирован на RTX 3060 (драйвер 595.99.02): при кадрах длиннее примерно 2 мс (это охватывает практически любой игровой кадр) гость показывает производительность в пределах 2% от того же хоста без виртуализации. Гостевой Wayland-клиент с захватом через NVENC произвёл 618 кадров H.264, которые ffmpeg декодировал без единой ошибки. По накладным расходам на CPU: за прогон с ненормированной нагрузкой около 100 кадров/с в течение 12 секунд и в сумме 813 691 кадр бэкенд обработал 13 792 сообщения, то есть одно обращение к хосту примерно на каждые 59 кадров, и почти все они приходятся на первоначальную настройку устройства, а не на сам цикл рендеринга.
Проверили и многопользовательский сценарий: четыре одновременных гостя на одной RTX 3060 при одинаковой нагрузке показали 25,84, 26,49, 25,57 и 25,79 кадра/с (в сумме 103,7 кадра/с, против 102,9 у одного гостя), с почти идентичными медианными временами кадра (39,164, 39,168 мс) и стабильным кодированием NVENC у каждого ровно на 60 Гц без превышения лимита сессий кодирования. Авторы подчёркивают, что четыре гостя, это просто то, что протестировали, а не найденный предел: восемь гостей не пробовали, как и нагрузку тяжелее vkcube в разрешении 720p.
Поддерживаются конкретные диапазоны версий драйвера Nvidia (профили ABI 535.129.03, 580.178.04, 595.71.05, подбор идёт по диапазону версий); всё старше 535.129.03 отклоняется, а не обрабатывается вслепую, чтобы не пробросить ioctl с незнакомой структурой. Карта RTX A2000 с драйвером 615.71.09 рендерит корректно, но не была включена в замеры производительности. CUDA пробрасывается, но протестирован только на уровне перечисления устройств, без реальной нагрузки.
Авторы сравнивают подход с virtio-gpu поверх Venus, где каждый вызов Vulkan/OpenGL сериализуется в гостевой системе, передаётся через virtio и воспроизводится на хосте: при 1000, 5000 вызовов отрисовки на кадр (типично для игр) и бюджете кадра 16,6 мс при 60 кадрах/с сериализация съедает 6, 18% этого бюджета ещё до начала работы GPU, а кодирование на стороне гостя вообще не работает, поскольку буферы принадлежат хосту. По оценке проекта, при Venus на кадр приходится около 2000 пересечений границы виртуальной машины (по одному на вызов API), тогда как у virtio-nvgpu, порядка 5, 20 (отправки очередей и выделения памяти), поскольку сами команды GPU собираются в гостевой системе компилятором самой Nvidia, а не пересобираются на хосте после сериализации.
Проект состоит из четырёх компонентов под тремя лицензиями: гостевой драйвер обязан быть под GPL, чтобы обращаться к символам ядра; часть на стороне хоста, под пермиссивной лицензией (Apache-2.0), чтобы её могли использовать другие разработчики; общие для обеих сторон определения написаны так, чтобы подключаться из кода под любой из лицензий. Структура репозитория повторяет проект chromeos/virtio-media. Отдельный «изолятор», песочница, которая должна запускать по одному непривилегированному вспомогательному процессу на гостя и держать реальные файловые дескрипторы устройств, пока не реализован: сегодня дескрипторы держит сам бэкенд внутри процесса гипервизора (VMM).
Авторы прямо оговаривают: измерения сделаны на одной карте с одной синтетической нагрузкой и не позволяют сравнивать проект с производительностью какого-либо другого гипервизора, поскольку ни один другой не тестировался.
Ключевые факты
- virtio-nvgpu пробрасывает ioctl-вызовы драйвера Nvidia между гостевой KVM-системой и хостом на уровне ABI драйвера, а не графического API, гость использует немодифицированные драйверы Nvidia для Vulkan, OpenGL, CUDA и NVENC
- На RTX 3060 гость показывает производительность в пределах 2% от «голого железа» при кадрах длиннее ~2 мс; 618 закодированных кадров H.264 декодировались без ошибок
- Четыре одновременных гостя на одной RTX 3060 дали в сумме 103,7 кадра/с против 102,9 у одного гостя, с равномерным распределением нагрузки и стабильным кодированием NVENC у каждого на 60 Гц
- Поддерживаются только явно перечисленные диапазоны версий драйвера Nvidia (535.129.03, 580.178.04, 595.71.05); более старые версии отклоняются, чтобы не пробрасывать ioctl с незнакомой структурой
- CUDA проброшен, но не протестирован за пределами перечисления устройств; песочница-изолятор для безопасной работы пока не реализована, а сравнения с другими гипервизорами авторы прямо называют неподкреплёнными измерениями
Почему это важно
Для видеокарт Nvidia в KVM до сих пор был выбор из двух крайностей: либо virtio-gpu с трансляцией Vulkan/OpenGL на уровне API (Venus), которая съедает 6, 18% бюджета кадра на сериализацию и не позволяет кодировать видео на стороне гостя, либо VFIO passthrough, отдающий всю карту целиком одной виртуальной машине. У Intel и AMD есть промежуточный вариант, нативный DRM-контекст, где гость строит команды локально, а у Nvidia такого решения не было. virtio-nvgpu предлагает третий путь именно для карт Nvidia: пробрасывать вызовы на уровне драйвера ядра, оставляя реальные драйверы Nvidia и работу с командными буферами внутри гостя.
Кому это важно
В первую очередь тем, кто строит инфраструктуру headless-стриминга игр или приложений на GPU Nvidia, облачный гейминг, удалённый рендеринг, мультитенантные GPU-сервисы на KVM, где нужно делить одну карту между несколькими виртуальными машинами без потери производительности рендеринга и кодирования.
Как это применить
Проект открытый, исходники на GitHub. Лицензирование раздельное: гостевой драйвер, под GPL (обязательное требование для работы с символами ядра), часть на стороне хоста, под пермиссивной Apache-2.0, чтобы её могли использовать сторонние разработчики. Работает только с явно перечисленными диапазонами версий драйвера Nvidia (535.129.03, 580.178.04, 595.71.05); более старые версии драйвера отклоняются. Проверено пока на RTX 3060 (полностью, с бенчмарками) и RTX A2000 (только рендеринг, без замеров).
Можно ли доверять
Источник, собственная документация проекта (README и файл с бенчмарками), а не независимый обзор. Авторы сами оговаривают границы измерений: тесты проведены на одной карте с одной синтетической нагрузкой и прямо не поддерживают сравнение с производительностью какого-либо другого гипервизора, потому что ни один другой не тестировался. Это добросовестная методологическая оговорка, но не замена независимой проверки.
Риски и подводные камни
CUDA пробрасывается, но проверен только на уровне перечисления устройств, без реальной вычислительной нагрузки. Ключевой компонент безопасности, «изолятор», отдельный непривилегированный процесс-песочница на каждого гостя, пока не написан: сегодня дескрипторы реальных устройств держит сам бэкенд внутри процесса гипервизора. Протестировано максимум четыре одновременных гостя с нагрузкой не тяжелее vkcube в 720p; восемь гостей и более тяжёлые сценарии не пробовали. ABI ядерного драйвера Nvidia нестабилен между релизами, поэтому список поддерживаемых версий узкий и явно ограниченный.
«Гость использует собственные пользовательские драйверы Nvidia без изменений, те же библиотеки, тот же Vulkan и NVENC, работающие с той же картой.»
— документация проекта virtio-nvgpu