Monday, January 4, 2016

Guide: Forcing low-power mode with NVidia cards on Linux

I googled for this for what seems like several hours, and only found wrong solutions. I figured it out myself in the end, so here's how to do it.

If you're like me, you're using Linux for work and Windows only for when you want to play a video game. In that scenario, I want my GPU to use low clocks when running Linux and run at the lowest temperatures possible. Coupled with the GTX 980 Ti I'm using, that translates to the fans of the cooler not spinning at all and thus the card becoming passively cooled. The fans of this particular card model only start spinning when the GPU reaches 60° Celsius.

To keep the card under the 60° threshold at all times, and thus passively cooled with 0db fan noise, the lowest power profile must be used. By default, the card will switch to maximum clock frequencies when there's load.

We can prevent that from happening by instructing the driver to:
  • Use the lowest power profile.
  • Use adaptive clock frequencies with the lowest power profile.
The second part is important, otherwise the GPU will use fixed clocks, which means it will get stuck at the highest clocks available on the lowest power profile. In this case, that would be 405MHz. However, we want the GPU to be able to go all the way down to 135MHz when idle and only switch to 405MHz when needed. Note that 405MHz is the highest it can go; we're forcing the lowest profile and thus the GPU will never use a 1392MHz clock.

So here's how to do it. In your X11 configuration directory, there should be a "xorg.conf.d" subdirectory. Usually that's "/etc/X11/xorg.conf.d/". In there, there should already be a file where the nvidia driver configuration resides. It looks like this:

Section "Device"
  Driver  "nvidia"
  [other options might exist here]

The important thing is to find the 'Section "Device"' entry that has the 'Driver "nvidia"' entry in it. If no such file exists at all, simply create one. You can name it whatever you want as long as it ends with ".conf". In my case, I use "nvidia.conf".

We need to add a new option line to that "Device" section that forces the lowest power mode, and keeps adaptive clocking within that power mode working. Add this line:

Option  "RegistryDwords"   "PowerMizerEnable=0x1; PerfLevelSrc=0x3333; PowerMizerLevel=0x3; PowerMizerDefault=0x3; PowerMizerDefaultAC=0x3"

So the section should now look like this:

Section "Device"
  Driver  "nvidia"
  Option  "RegistryDwords"   "PowerMizerEnable=0x1; PerfLevelSrc=0x3333; PowerMizerLevel=0x3; PowerMizerDefault=0x3; PowerMizerDefaultAC=0x3"
  [other options might exist here - do not touch those]

The various "PowerMizerLevel" entries specify which power mode to use. It doesn't matter how many power levels are shown in the nvidia-settings panel. The configuration file always deals with three:

  • Highest performance (mode 0x1)
  • Balanced (mode 0x2)
  • Lowest performance/maximum power saving (mode 0x3)

So we specify "0x3" as the mode to under all circumstances.

If you've read other guides on the net, you probably seen a "Coolbits" option. You do NOT need that. It's got nothing to do with being able to specify power levels.

You also might have seen the "PerfLevelSrc" entry be "0x2222" instead of "0x3333". That is also wrong. It turns out that this field consists of two bytes that specify whether to use adaptive or fixed clocks. 0x22 means fixed, and 0x33 means adaptive. The first byte specifies the clocks policy when on battery, the second when on AC power (or this might be vice versa, I'm not sure.) In any event, we want to use adaptive clocks for BOTH, so "0x3333" is the correct value and will allow the GPU to downclock to the minimum possible frequency instead of getting stuck at the highest frequency of the lowest power mode.

And that's pretty much it. Restart the X server (or simply reboot if you don't know how to restart X), and the new settings should take effect. You should be able to observe the clocks in the nvidia-settings control panel. In my case, the card will use 135MHz as the minimum, and 405MHz as the maximum. It will never switch to a higher power profile: