User-friendly NVIDIA Optimus management
Users of laptops with NVIDIA Optimus are probably aware of some traits of getting it work on Linux:
- It is properly supported only in proprietary NVIDIA driver which is not shipped by default with the majority of Linux distributions;
- Until recently there was no support for NVIDIA Optimus which allows using your integrated video-card for casual applications and GPU for games and other GPU-heavy processes. This problem is semi-solved with PRIME which is the best case requires to log out and log in back;
- NVIDIA GPU consumes a lot of power when it’s not used. So there is no official way to turn it off when it’s not used at least for pre-Turing GPU generations.
As you might already know, NVIDIA finally managed to implement
D3 power management
of dedicated GPU on Optimus-powered laptops in version 435.xx
of their proprietary driver, so #3
is no more relevant.
The problem #2
is also solved in latest drivers by adding support for
PRIME Render Offloading
which allows rendering GPU heavy applications on GPU and others on the integrated.
Unfortunately, to have all this working your laptop has to meet the requirements:
- Turing-generation GPU or higher. Those are GPUs starting from GTX 1650, see the link for more details;
- Intel 8th generation Coffee Lake processor.
If your laptop meets the requirements you can enable D3 power management mode, otherwise, you only can enable Nvidia Offloading which without D3 is not that useful on laptops as NVIDIA GPUs consumes a lot of power and drain the battery very fast.
Fortunately, there’s an old time-proved solution of managing external GPU power state: it’s bbswitch. While it is often used together with Bumblebee which is deprecated now in favor of PRIME, nothing is stopping you to use it separately just to turn GPU on/of without need to re-login every time.
I maintain a
COPR repo
with bbswitch-kmod
and bumblebee
packages for Fedora, while in Ubuntu
bbswitch-dkms
is shipped in
universe repo.
However it’s not really user-friendly and works only for root
:
# tee /proc/acpi/bbswitch <<<OFF
# tee /proc/acpi/bbswitch <<<ON
So I got an idea of making the complete solution consisting of:
- Daemon for managing
bbswitch
state running under privileged user; - Simple command-line utility that allows manage power state for a user from special group;
- GUI utility sitting in tray and allowing to do it fith a few mouse clicks and providing a simple GPU utilization monitoring.
And it is finally ready!
- bbswitchd
is a daemon that communicates with
bbswitch
from the one side, and providing a UNIX socket interface for checking status and turning the GPU on and off for the users frombbswitchd
group. For the complete guide please proceed to Initial Configuration section of the official README. The usage is quite simple then, just callbbswitch
front-end script with one of the available options:
$ bbswitch
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 is a PyGTK frontend application that allows to manage dedicated GPU power state as well as see GPU utilization, running processes and loaded kernel modules:
When NVIDIA GPU is turned on, some application may utilize it unintentionally and you won’t be able to turn it off until all applications utilizing the GPU are stopped.
That’s why it is useful to see the list of applications using the GPU and being able to kill any (or all) of them by single click.
Also a nice tray icon will appear allowing you to switch the power state even without launching the window:
If you have switchroo-control installed, When GPU is in use, your desktop environment may offer to launch an application on it:
To launch from console you need to setup environment variables, e.g.:
$ __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxgears
To use PRIME offload for Vulkan applications:
$ __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only vkmark
All this works in both Wayland and X11.
The most straightforward way to install bbswitchd/bbswitch-gui is to use prebuilt packages from copr for Fedora or PPA for Ubuntu.
For Fedora:
$ sudo dnf copr enable polter/bumblebee
$ sudo dnf install bbswitch-gui
For Ubuntu:
$ sudo add-apt-repository ppa:polter-rnd/bbswitch-gui
$ sudo apt update
$ sudo apt install bbswitch-gui
After package installation please check that your user have been added to bbswitchd
group using groups
command, and then re-login or reboot the machine to apply it.
For more information please proceed to GitHub page.
Tips & Tricks
To make bbswitch-gui
auto-start minimized to tray, one can create a file
~/.config/autostart/io.github.polter-rnd.bbswitch-gui.desktop
with the following
content (-m
option means run minimized):
[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
Known issues and workarounds
After logout from GNOME shell with enabled NVIDIA GPU, on next login it will detect it and take in use, thus making it impossible to turn dedicated GPU off.
Workaround is to hide NVIDIA GPU from gnome-shell
process while keeping it available
for all other processes. It can be solved by creating a fake directory on startup for
EGL library configurations which is normally in /usr/share/glvnd/egl_vendor.d
:
$ ls /usr/share/glvnd/egl_vendor.d/
10_nvidia.json 50_mesa.json
Then override configuration of org.gnome.Shell@wayland.service
user-owned systemd unit:
$ 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
On each gnome-shell
startup it will see only 50_mesa.json
configuration
and only then 10_nvidia.json
will appear therefore making it availabe for all other processes.