Настроив ВМ с Windows для стриминга игр я заметил, что при ее выключении потребление энергии не снижается, а иногда и возрастает, по сравнению с запущенной ВМ в простое. Загуглив проблему, понял, что я не один такой. Но представленные решения выглядели совсем уж костыльными.
У меня Proxmox VE 8.4.0 на следующем железе:
CPU Intel Core i9-13900K
Материнаская плата MSI MAG Z790 TOMAHAWK WIFI
Видеокарта PowerColor AMD Radeon RX 6800 XT Red Devil
ОЗУ 64ГБ DDR5 Kingston FURY Beast Black RGB 6000 МГц
NVMe SSD Samsung 970 EVO Plus 500Gb для хоста Proxmox
Итак, что я заметил. Чистая установка Proxmox, при старте ваттметр показывает 40 Вт. После настройки и запуска ВМ с Windows и пробросом видеокарты потребление в простое составляет 85-90Вт. В играх, понятное дело, потребление зависит от общей нагрузки системы.
Выключаю ВМ и потребление составляет не вышеописанные 40Вт, а 125Вт и видеокарта горячая. Так, естественно, железо долго не проживет, да и платить за электричество простаивающей системы глупо.
При поиске проблемы я наткнулся на пояснение, что до проброса PCI устройства, им управляет хост, что логично. При пробросе им уже управляет сама ВМ. Точнее драйвера, настроенные в ней.
А вот при выключении ВМ, в которую проброшена видеокарта, хост не берет управление обратно на себя. И, соответственно, без активной ВМ видеокарта не может переключиться в энергосберегающие режимы, которые обычно контролируются драйверами операционной системы ВМ. Как итог — высокое потребление в режиме простоя. Это активно обсуждалось на форуме Proxmox.
Но предложенное решение создать для этого фиктивную ВМ с малыми ресурсами, пробросить в нее GPU и настроить скрипт для автоматического запуска этой «фиктивной» ВМ при отключении основной ВМ.. по моему эта идея тоже не очень разумна.
В Proxmox есть возможность использовать hookscripts — специальные скрипты, которые помогают управлять ВМ. И я подумал, раз есть возможность с помощью этих скриптов запускать одну ВМ при остановке другой, то почему бы не использовать скрипт более разумно — передавать управление моей видеокартой обратно хосту при отключении ВМ с Windows? Так и сделаем.
Настройка hookscript
Запускаем хост Proxmox, все ВМ выключены. Теперь посмотрим, у кого сейчас контроль над моим GPU. Как я писал в статье о настройке ВМ для стриминга игр, моя видеокарта на шине 03:00.0
lspci -nnk -s 03:00.0

Здесь видно, что GPU сейчас использует (in use) драйвер amdgpu, который, соответственно, на хосте. Потребление на ваттметре, при этом, 40Вт. Отлично.
Теперь запускаю ВМ Windows c проброшенным GPU и еще раз выполняю lspci -nnk -s 03:00.0
Как видно по ответу, GPU сейчас использует vfio-pci
— видеокартой управляет ВМ. Потребление по ваттметру в простое 85Вт.
Выключаю ВМ и еще раз выполняю lspci -nnk -s 03:00.0 — вывод не поменялся, GPU использует vfio-pci
, а потребление возросло до 125Вт. Бред же, согласитесь. Видеокарта не используется, а жрет в простое как не в себя.
С помощью DeepSeek я написал скрипт, который возвращает контроль над GPU обратно хосту (драйверу amdgpu).
nano /usr/local/bin/gpu_power_control.sh
Код скрипта:
#!/bin/bash
GPU_PCI_ADDR="03:00.0" # Замените на ваш PCI-адрес
GPU_DRIVER="amdgpu" # Родной драйвер (уточните через lspci -nnk)
if [ "$1" = "off" ]; then
echo "Возвращаю GPU под управление хоста..."
# 1. Убеждаемся, что GPU больше не используется vfio-pci
echo 1 > /sys/bus/pci/devices/0000:$GPU_PCI_ADDR/remove
sleep 1
# 2. Возвращаем GPU в систему
echo 1 > /sys/bus/pci/rescan
sleep 1
# 3. Переключаем драйвер с vfio-pci на amdgpu
echo "$GPU_DRIVER" > /sys/bus/pci/devices/0000:$GPU_PCI_ADDR/driver_override
echo "0000:$GPU_PCI_ADDR" > /sys/bus/pci/drivers/$GPU_DRIVER/bind
echo "GPU переключен на $GPU_DRIVER"
elif [ "$1" = "on" ]; then
echo "Подготавливаю GPU для Passthrough..."
# 1. Отключаем GPU от родного драйвера (если он был подключён)
echo "0000:$GPU_PCI_ADDR" > /sys/bus/pci/drivers/$GPU_DRIVER/unbind
sleep 1
# 2. Принудительно назначаем vfio-pci
echo "vfio-pci" > /sys/bus/pci/devices/0000:$GPU_PCI_ADDR/driver_override
echo "0000:$GPU_PCI_ADDR" > /sys/bus/pci/drivers_probe
echo "GPU готов для Passthrough"
fi
Даем права:
chmod +x /usr/local/bin/gpu_power_control.sh
Теперь настроим автоматическое выполнение этого скрипта при старте/остановке ВМ через хуки Proxmox. Для этого зайдем создадим нужный каталог и поместим туда скрипт:
cd /var/lib/vz/
mkdir snippets
cd
nano /var/lib/vz/snippets/gpu-control.sh
Код хук-скрипта:
#!/bin/bash
if [ "$2" == "post-stop" ]; then
/usr/local/bin/gpu_power_control.sh off
elif [ "$2" == "pre-start" ]; then
/usr/local/bin/gpu_power_control.sh on
fi
Даем права:
chmod +x /var/lib/vz/snippets/gpu-control.sh
И привязываем хук к ВМ (моя ВМ 105):
qm set 105 --hookscript local:snippets/gpu-control.sh
И все, при запуске ВМ идет проброс видеокарты в нее, управляение за vfio-pci
. При остановке все возвращается обратно и видеокартой управляет ядрайвер amdgpu на хосте Proxmox. Потребление всей системы по ваттметру все те же 40 Вт. Мне только не ясно, почему по дефолту так не работает, ведь именно так было бы логичней всего.