Ранее (первая и вторая версия) я писал о том, как делал автоматическое управление кулерами корпуса для своего сервера на Machinist X99.
Предыстория
В первое время видеокарты прокидывались "дольками" (использовал vGPU/Grid). Благодаря vGPU карты были видны с хоста и температуры можно было получать прямо через nvidia-smi.
Позже я стал пробрасывать карты целиком (это проще и стабильнее), но потребовало добавить часть, работающую на каждой ВМ (виртуальной машине). При полном пробросе GPU недоступны с хоста. Чтобы хост "видел" температуры проброшенных пришлось вынести функционал внутрь виртуальных машин.
Условная версия 2.0 (box_fan_control_for_cpu_and_gpu начиная с c73c8e8) изначально была компромиссной. Опрос виртуалок происходил последовательно, из-за чего выключенные ВМ замедляли реакцию системы. Температуры всех карт сводились к одной максимальной (независимо от модели и особенностей), настройка требовала ручного редактирования конфигов, да и в логике были проблемы. Улучшение требовало серьезной работы.
В какой-то момент я решил посмотреть температуры VRAM на RTX 3090, чтобы проверить, как они изменились спустя время после обслуживания. Кроме того, волновало, какие у карт температуры под ИИ-нагрузкой. В ВМ на Debian сделать это через привычную nvidia-smi было невозможно. Даже перекинув карты в ВМ на Windows и глядя через GPU-Z, я получал данные только для стресс-тестов, т.к. реальная нагрузка-то была в ВМ на Debian.
Тревожности добавляла восстановленная карта, у которой были заменены родные вентиляторы на простые TF-9215-W. Как там ими управляет родная логика (корректно ли)? Хватает ли охлаждения VRAM? Не успели ли вылезти косяки самостоятельного обслуживания (замены термопасты и термопрокладок)?
В общем, проблемы и хотелки накопились. Представление о цели сложилось, и я начал работу.
Как получить температуры VRAM и Hotspot?
Стандартная утилита nvidia-smi не отдает эти данные для потребительских карт. Попутно с основным проектом пришлось сделать свою библиотеку — ngjvt (NVIDIA GPU Junction/VRAM Temperature Library). Сначала на Си (на основе других проектов, написанных тоже на Си) + обертка на Python. Чуть позже добавил чистую реализацию на Python (чтобы не требовалась компиляция).
Эта библиотека читает температуры через обратный инжиниринг драйвера (работает через /dev/mem). Поэтому для её работы потребуются root-права, отключенный Secure Boot и параметр iomem=relaxed в grub. Поддерживает RTX 20-ю (ограниченно), 30-ю и 40-ю серии (с полным списком предположительно поддерживаемых карт можно ознакомиться в репозитории библиотеки).
В какой-то момент я понял, что засяду надолго, и для ускорения пришлось использовать ИИ. Получилось достаточно быстро и просто. Но признаюсь честно: до символа код не перепроверял, могут быть "грабли". Все, что нашел — убрал, какие-то могли остаться. Поэтому с осторожностью: если найдете — пишите.
Новые фишки (версии 3.0)
- Появился Web-интерфейс. Теперь можно не лезть в текстовые файлы, а настраивать кривые оборотов вентиляторов прямо из браузера. Там же выводятся температуры и мощность.
- Индивидуальный подход к каждому GPU. Теперь для каждой видеокарты свой профиль, привязанный по UUID (можно не бояться, что привязка карты к другой ВМ сбросит или сменит профиль).
- Умная идентификация GPU. Не нужно вручную связывать UUID видеокарты с виртуальной машиной — система сама разбирает конфиги Proxmox и сопоставляет карты на лету.
- Переход на WebSockets. Это решило проблему с задержками. Данные от ВМ приходят асинхронно, и неработающие машины больше не растягивают цикл опроса.
- Расширенный мониторинг. Добавилось чтение температур Hotspot, VRAM и потребляемой мощности для видеокарт, а также интеграция с Netdata через StatsD.
Краткая инструкция по развертыванию
Ниже описан общий порядок установки, скорее образный рисунок процесса. Конкретные команды, пути и скрипты смотрите в репозитории проекта.
- Настройка хоста (Proxmox)
Клонируем репозиторий, создаем Python-venv и устанавливаем зависимости из requirements.txt. Далее регистрируем приложение как systemd-сервис с высоким приоритетом (FIFO), чтобы управление кулерами не зависало при высоких нагрузках на систему. Запускаем. - Настройка ВМ на Linux (Debian/Ubuntu)
Сначала подготавливаем систему для работы библиотеки ngjvt: добавляем iomem=relaxed в параметры ядра, отключаем Secure Boot и перезагружаемся.
Затем копируем файлы клиентской части в ВМ, создаем venv, устанавливаем зависимости (включая библиотеку для работы с NVIDIA и websockets). Клиента также запускаем через systemd. - Настройка ВМ на Windows
Копируем клиентский скрипт и необходимые .dll файлы из проекта LibreHardwareMonitor. Создаем venv и ставим зависимости. Для фонового автозапуска без окон консоли используем встроенный планировщик задач (Task Scheduler). В репозитории есть готовый PowerShell скрипт-установщик, который все сделает сам (запускает от имени SYSTEM с высоким приоритетом).
Результат
После запуска всех частей система сама найдет карты, свяжет их с ВМ по UUID, и Web-интерфейс станет доступен в браузере по адресу http://IP-ВАШЕГО-ХОСТА:17006/. Там же можно будет настроить профили кулеров.
Завершение
Проект остается open-source. Исходный код, скриншоты интерфейса и подробные инструкции доступны ниже.
🔗 GitHub проекта: box_fan_control_for_cpu_and_gpu_v3
🔗 Библиотека для температур: ngjvt
Буду рад любым отзывам и баг-репортам.