LINUX.ORG.RU

Готовим NVIDIA PRIME + Optimus для pre-Turing GPU

 , , ,


4

1

Статья основана на моих оригинальных англоязычных записях тут и тут.

Приветствую, несчастные владельцы ноутбуков с технологией с NVIDIA Optimus, а именно те, кому посчастливилось иметь зелёную GPU до поколения Turing (GTX 1650 и выше). Список поколений микроархитектур NVIDIA можно найти на википедии. Как известно, начиная с версии 435.xx в проприетарном драйвере появилась нормальная поддержка энергосбережения для этих архитектур, так что если у вас NVIDIA GTX 1650 и выше, всё должно работать из коробки и простыню ниже можно не читать.

Сразу оговорюсь, что решение, представленное ниже, не зависит от дистрибутива и DE и не прибито к Wayland или X11. Хотя некоторые лайфхаки могут быть специфичны для GNOME, так как он является моей основной средой рабочего стола.

Единственным требованием является использование проприетарного драйвера NVIDIA.

Дано

  • Ноутбук MSI GS63VR с GTX 1060 на борту;
  • ОС: Fedora 38;
  • Проприетарный драйвер NVIDIA (из RPMFusion);
  • Основной рабочий сеанс: GNOME Shell / Wayland.

Что хочется получить

  1. Полноценное отключение дискретной GPU по умолчанию, соответственно, продлевая жизнь от батареи;
  2. Возможность включить дискретную GPU и запустить какие-либо приложения на ней с помощью технологии PRIME Offloading штатными средствами DE;
  3. Возможность переключения на сеанс, запущенный полностью на NVIDIA (без использования PRIME) по необходимости;
  4. Возможность выключить дискретную GPU в любое время (вернуть в состояние по умолчанию);
  5. Включение/отключение GPU должно происходить без перезагрузки системы, а так же без выхода из рабочей сессии;
  6. По возможности отслеживать запущенные процессы на GPU и мониторить показания.

Мир OpenSource-решений предлагает нам 2 стула:

  • Bumblebee + bbswitch. Несмотря на то, что сам Bumblebee устарел и использование VirtualGL при наличии PRIME Offloading смысла не имеет, bbswitch продолжает работать довольно неплохо и делает ровно то, что мне нужно. Я даже попытался использовать bumblebeed в качестве исключительно обёртки над bbswitch (для загрузки/выгрузки модулей ядра и собственно дёргания /proc/acpi/bbswitch), сделав для этого целый bash-костыль. Несмотря на то, что это даже работает, претендовать на нормальное решение никак не может: обратная связь отсутствует, а во время работы GPU его могут «увидеть» другие приложения, которые мы напрямую не запускали через скрипт, и bumblebeed про них не в курсе. В таком случае, GPU не сможет выключиться, когда придёт время, так как модули используются этими приложениями (пункты 4 и 5). Второй минус - нам приходится запускать нужные приложения через скрипт, DE не предлагает нам пункта меню с запуском на дискретной GPU (пункт 2).
  • system76-power и optimus-manager/prime-select и им подобные: такие утилиты позволяют менять конфигурацию модулей в initramfs и конфиг X11 в зависимости от выбранного режима. Как можно понять, это требует иногда длительного ожидания пересборки initramfs, а затем перезагрузки ОС, что противоречит пунктам 4 и 5.

Спустя около года мучений я пришёл к законченному решению, которым делюсь с вами.

Решение

Что ж, раз из коробки ничего не придумали для моих хотелок, пришлось это запилить. Так как решение с bbswitch в целом меня устраивало, не хватает лишь адекватной обёртки над ним. Вырисовывается следующая простейшая архитектура:

  • bbswitchd: backend-демон, занимающийся только тем, что загружает/выгружает нужные модули, а так же пишет в /proc/acpi/bbswitch. Эдакий Bumblebee на минималках, однако, работающий из коробки и поставляющийся с необходимыми политиками SELinux, правилами udev и конфигурацией modprobe. Общение происходит через UNIX-сокет (для этого не забыть добавить пользователя в группу bbswitchd). В комплекте идёт простейшая утилита bbswitch для включения и выключения GPU:
    $ bbswitch
    Usage: bbswitch on | off | status
    $ bbswitch on     # Turn discrete GPU on
    $ bbswitch status # Request current status
    ON
    $ bbswitch off    # Turn discrete GPU off
    
  • bbswitch-gui: соответственно, графический фронтэнд на Python+GTK3, позволяющий:
    • Включать и выключать питание дискретной GPU;
    • Просматривать список процессов, использующих в данный момент дискретный GPU с возможностью быстро убить выбранные процессы;
    • Мониторить параметры видеокарты (с помощью NVML API), а так же список загруженных модулей ядра;
    • Адекватно обрабатывать ошибки при загрузке модулей и работе с bbswitch;
    • Висеть в системном лотке как AppIndicator и не мешать.

Более детальная информация со скриншотами и примерами использования доступна в README на GitHub для обоих проектов.

Оба приложения опакечены для Fedora (Copr):

$ sudo dnf copr enable polter/bumblebee
$ sudo dnf install bbswitch-gui

И для Ubuntu (PPA):

$ sudo add-apt-repository ppa:polter-rnd/bbswitch-gui
$ sudo apt update
$ sudo apt-get install bbswitch-gui

После установки видим следующие конфигурационные файлы:

  • Запрет на автоматическую загрузку модулей nvidia, а так же опция load_state=0 для модуля bbswitch для выключения дискретной GPU при загрузке:

    $ cat /lib/modprobe.d/bbswitch.conf 
    options bbswitch load_state=0
    blacklist nvidia
    blacklist nvidia-drm
    blacklist nvidia-modeset
    blacklist nvidia-uvm
    blacklist nouveau
    
  • Автоматическая загрузка модуля bbswitch:

    $ cat /lib/modules-load.d/bbswitch.conf 
    # Load bbswitch.ko at boot
    bbswitch
    
  • Udev-правило для запрета оконному менеджеру mutter обнаруживать дискретную GPU:

    $ cat /lib/udev/rules.d/60-bbswitch-nvidia-mutter.rules
    DRIVERS=="nvidia", SUBSYSTEM=="drm", TAG+="mutter-device-ignore"
    
  • Udev-правило для автоматического удаления файлов устройств NVIDIA:

    $ cat /lib/udev/rules.d/90-bbswitch-nvidia-dev.rules
    # Put this file in /lib/udev/rules.d or /etc/udev/rules.d
    # Prevent the nvidia card from "randomly" turning on
    DEVPATH=="/module/nvidia", ACTION=="remove", RUN+="/bin/sh -c 'rm -f /dev/nvidiactl /dev/nvidia[0-9] /dev/nvidia-modeset /dev/nvidia-uvm /dev/nvidia-uvm-tools'"
    
  • А так же systemd-сервис и соответствующий сокет:

    $ systemctl status bbswitchd.service
    ● bbswitchd.service - GPU power state management daemon
         Loaded: loaded (/usr/lib/systemd/system/bbswitchd.service; disabled; preset: disabled)
    TriggeredBy: ● bbswitchd.socket
    ...
    
    $ systemctl status bbswitchd.socket
    ● bbswitchd.socket - Socket for bbswitchd daemon
         Loaded: loaded (/usr/lib/systemd/system/bbswitchd.socket; enabled; preset: enabled)
         Active: active (running) since Fri 2023-08-11 17:54:11 MSK; 5h 17min ago
       Triggers: ● bbswitchd.service
    ...
    

После перезагрузки получаем максимально удобный механизм запуска приложений на внешней GPU: после включения дискретного адаптера DE начнёт предлагать запустить приложения на ней (при наличии switcheroo-control, который установлен из коробки в большинстве дистрибутивов).

Если GPU не может выключиться из-за того, что какие-либо приложения её используют, это видно в главном окне (вместе с информацией об утилизации ресурсов) и при необходимости можно их убить.

Tips & Tricks

Ниже несколько лайфхаков, которые делают использование всего этого более мягким и шелковистым.

Автозапуск bbswitch-gui

Чтобы bbswitch-gui запускался свёрнутым в трей, можно создать файл ~/.config/autostart/io.github.polter-rnd.bbswitch-gui.desktop со следующим содержимым (опция -m означает запуск в свёрнутом состоянии):

[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=BBswitch GUI
Comment=GUI tool for managing NVIDIA GPU power states and utilization
Exec=/usr/bin/bbswitch-gui -v -m
Icon=bbswitch-gui
Categories=System;Monitor;Utility;X-GNOME-Utilities;
Keywords=nvidia;bbswitch;optimus;prime;
X-AppInstall-Keywords=nvidia;bbswitch;optimus;prime;
X-GNOME-Keywords=nvidia;bbswitch;optimus;prime;
X-GNOME-UsesNotifications=true

Запуск gnome-shell всегда на встроенной видеокарте

Если выйти из Wayland-сессии со включенной NVIDIA GPU (например, чтобы зайти в X11 сессию), то при следующем входе gnome-shell увидит включенную видеокарту и подключится к ней. В результате не получится отключить дискретную GPU, т.к. процесс композитора к ней подключён.

Для решения этого переопределим конфигурацию сервиса org.gnome.Shell@wayland.service:

$ systemctl --user edit org.gnome.Shell@wayland.service

Следующим содержимым:

[Service]
ExecStartPre=/usr/bin/mkdir -p /tmp/egl_vendor.d
ExecStartPre=/usr/bin/rm -f /tmp/egl_vendor.d/10_nvidia.json
ExecStartPre=/usr/bin/ln -fs /usr/share/glvnd/egl_vendor.d/50_mesa.json /tmp/egl_vendor.d
Environment=__EGL_VENDOR_LIBRARY_DIRS=/tmp/egl_vendor.d
ExecStartPost=/usr/bin/ln -fs /usr/share/glvnd/egl_vendor.d/10_nvidia.json /tmp/egl_vendor.d

Теперь видеокарта NVIDIA скрыта от gnome-shell при запуске на Wayland, в то время, как для остальных процессов она остаётся доступна.

Если вы не пользуетесь Wayland и хотите такое же поведение для X11 сессии, переопределять нужно org.gnome.Shell@x11.service.

Переключение на сеанс, запущенный полностью на NVIDIA GPU

Чтобы реализовать пункт 3 в моем случае было проще всего настроить X11 для работы в NVIDIA-only режиме, в то время, как дефолтная Wayland-сессия всегда запускается на встроенном видеоадаптере:

$ cat /etc/X11/xorg.conf.d/10-nvidia.conf 

Section "OutputClass"
	Identifier "nvidia"
	MatchDriver "nvidia-drm"
	Driver "nvidia"
	Option "AllowEmptyInitialConfiguration"
	Option "SLI" "Auto"
	Option "BaseMosaic" "on"
	Option "PrimaryGPU" "yes"
EndSection

Section "ServerLayout"
	Identifier "layout"
	Option "AllowNVIDIAGPUScreens"
EndSection

Таким образом, при входе в сеанс X11 при включенной дискретной GPU иксы запустятся полностью на NVIDIA, в тоже время, при выключенной - запустятся на встроенном графическом адаптере. Удобно (при наличии сеанса Wayland, из которого можно всегда выключить дискретный адаптер при необходимости).

Сохранение конфигурации экранов при переключении X11/Wayland

В моём случае в сеансе Wayland используется дробное масштабирование (экспериментальная возможность mutter). Однако, при запуске сеанса X11 наличие дробного масштаба в конфигурации мониторов делает её невалидной, и оконный менеджер сбрасывает её на конфигурацию по-умолчанию. Чтобы комфортно сохранять конфигурацию в отдельных файлах для X11 и Wayland, можно сделать следующее:

$ cp ~/.config/monitors.xml ~/.config/monitors.xml.wayland
$ cp ~/.config/monitors.xml ~/.config/monitors.xml.x11
$ ln -sf ~/.config/monitors.xml.${XDG_SESSION_TYPE} ~/.config/monitors.xml

Таким образом мы сохранили конфигурацию в отдельные файлы и выставили символьную ссылку на конфигурацию текущего сеанса.

Осталось добавить костыль в ~/.bash_profile для переключения конфигурации при входе:

if [ "${XDG_SESSION_TYPE}" = "wayland" -o "${XDG_SESSION_TYPE}" = "x11" ]
then
    MONITORS_XML="${HOME}/.config/monitors.xml"
    if [ -L "${MONITORS_XML}~" ]
    then
        cp "${MONITORS_XML}" $(readlink -f "${MONITORS_XML}~")
        rm -f "${MONITORS_XML}~"
    fi

    ln -sf ${MONITORS_XML}{.${XDG_SESSION_TYPE},}
fi
★★

Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 16)

зелёную GPU до поколения Turing (GTX 1650 и выше)

Наверное, было бы неплохо вставить в статью ссылочку на таблицу этих самых поколений с обозначениями моделей (например, на Википедию, или может, ещё получше есть), а то в них чёрт ногу сломит. Саму таблицу не надо, а ссылочка была бы очень в тему.

hobbit ★★★★★
()

А статья приятная, тянет на полновесную. Отдельно радует, что автор рассмотрел как X11, так и Wayland.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Спасибо, добавил ссылку на вики

POLTER ★★
() автор топика

Кажется в направлении гибридной графики наконец то появился прогресс.

kirill_rrr ★★★★★
()

Павел, доброе утро!
Статья – прелесть! )
bbswitchd, bbswitch-gui – это ваши детища?

Так а для каких карт это подходит, а какого по какое поколение?..

SerW
()

Тогда было неприятно Оптимус ковырять, а сейчас - и подавно

somemong
()
Ответ на: комментарий от SerW

Приветствую!

Да, bbswitchd/bbswitch-gui моё :)

Для каких карт подходит - определяется только тем, поддерживается ли карта модулем bbswitch. По идее, должно работать на всём, для чего есть проприетарный драйвер, до поколения Turing (NVIDIA GTX 1650) не включительно. Можно проверить вначале, работает ли bbswitch, затем двигаться дальше.

POLTER ★★
() автор топика

всё должно работать из коробки

неть :(

bo4ok
()

А теперь тоже самое в кедах, с включенным композитором

DumLemming ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.