Update to thread:
So far, the best options I have found to reduce power consumptions have been to install & use auto-cpufreq
and power off the nvidia dedicated gpu.
I ditched TLP in favor of auto-cpufreq
, power-profiles-daemon
was (at a glance) worthless in comparison to both of those.
Using the powersave
governor over the performance
governor saves me about 3w under idle loads (I configured auto-cpufreq
to always use powersave
).
I also enabled PCI Runtime power management enabled and it seems to be saving me about 1.5w/h
The most critical component of lowering power consumption so far is disabling turbo boost (reduces idle consumption by about 10w!), auto-cpufreq does this automatically whenever turbo boost would not be needed, but re-enables it when it is granting the ideal compromise between power saving and performance for most users (the pc will draw less power under low load essentially)
Another important component for lowering power draw is limiting the igpu frequency, it can be done with this script
igpu_limit
:
#!/bin/sh
#Must be run as root/sudo
#Identifier for igpu (should usually be 0)
card=0
#Limiter Status
limiter=$(( $(cat /sys/class/drm/card$card/gt_max_freq_mhz) / $(cat /sys/class/drm/card$card/gt_min_freq_mhz) ))
if [ $limiter != 1 ]; then
limiter=0
fi
#Main
if [ "$1" == "on" ]; then #Limit igpu frequency to it's minimum
echo $(cat /sys/class/drm/card$card/gt_min_freq_mhz) > /sys/class/drm/card$card/gt_max_freq_mhz
echo $(cat /sys/class/drm/card$card/gt_min_freq_mhz) > /sys/class/drm/card$card/gt_boost_freq_mhz
elif [ "$1" == "off" ]; then #Restore max igpu frequency to default
echo $(cat /sys/class/drm/card$card/gt_RP0_freq_mhz) > /sys/class/drm/card$card/gt_max_freq_mhz
echo $(cat /sys/class/drm/card$card/gt_RP0_freq_mhz) > /sys/class/drm/card$card/gt_boost_freq_mhz
elif [ "$1" == "boot" ]; then #Limit igpu frequency to it's minimum on boot
echo w /sys/class/drm/card$card/gt_max_freq_mhz - - - - $(cat /sys/class/drm/card$card/gt_min_freq_mhz) > /etc/tmpfiles.d/igpu_powersave.conf
echo w /sys/class/drm/card$card/gt_boost_freq_mhz - - - - $(cat /sys/class/drm/card$card/gt_min_freq_mhz) >> /etc/tmpfiles.d/igpu_powersave.conf
elif [ "$1" == "boot-off" ]; then #Don't limit igpu frequency to it's minimum on boot
rm /etc/tmpfiles.d/igpu_powersave.conf
elif [ "$1" == "toggle" ]; then #Toggle limiter on and off
DISPLAY=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
username=$(who | grep '('$DISPLAY')' | awk '{print $1}' | head -n 1)
user_id=$(id -u $username)
case $limiter in
1)
echo $(cat /sys/class/drm/card$card/gt_RP0_freq_mhz) > /sys/class/drm/card$card/gt_max_freq_mhz
echo $(cat /sys/class/drm/card$card/gt_RP0_freq_mhz) > /sys/class/drm/card$card/gt_boost_freq_mhz
;;
0)
echo $(cat /sys/class/drm/card$card/gt_min_freq_mhz) > /sys/class/drm/card$card/gt_max_freq_mhz
echo $(cat /sys/class/drm/card$card/gt_min_freq_mhz) > /sys/class/drm/card$card/gt_boost_freq_mhz
;;
*)
echo "Error! Something went wrong!"
exit
;;
esac
sudo -u $username DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$user_id/bus notify-send "iGPU Max Frequency: $(cat /sys/class/drm/card$card/gt_max_freq_mhz)mHz"
else
echo "Usage: igpu_limit [arg]
on - Limits igpu frequency to minimum
off - Resets limit on igpu frequency
boot - Limits igpu frequency to minimum on boot
boot-off - Disable limiting igpu frequency on boot
toggle - Toggle limit on and off"
fi
disabling the nvidia dgpu is a solid 3w power saving, however when it is on it may occasionally jump up to 8w even when it should not be in use. so overall it should help quite a bit.
Here is the script to power down the nvidia gpu
nvidia_toggle
:
#!/bin/sh
#The nvidia gpu can only be toggled on and off between reboots, i have not found a way to disable it without a reboot that doesn't cause the system to crash (may be possible on muxed laptops), and I have not found a way to re-enable it without a reboot because I can't find a way to make the nvidia drivers detect the gpu.
#The bus is autodetected, should be fine on most laptos but no idea how it'd behave on a desktop
bus=$(lspci | grep -m1 NVID | cut -d '.' -f1 | sed 's/:/\\\\:/g')
#Sanity check to see if the gpu is currently enabled requires the bus value given in a slightly different format
busalt=$(lspci | grep -m1 NVID | cut -d '.' -f1)
#This acpi id is the most common one for nvidia dgpus on laptops, but some laptops might have a different id, if the script doesn't work for you this is most likely the problem.
#You should be able to use this script to find the correct method for your laptop: https://github.com/mkottman/acpi_call/blob/master/examples/turn_off_gpu.sh
acpi_id=SB.PCI0.PEG0.PEGP
#Check and report the current status of the dgpu
if [ -d /sys/bus/pci/devices/0000:$busalt.0 ]; then
gpu="On"
else
gpu="Off"
fi
if [ -f /etc/tmpfiles.d/nvidia_off.conf ]; then
gpuboot="Off"
else
gpuboot="On"
fi
echo "
Nvidia GPU current status: $gpu
Nvidia GPU status on next boot: $gpuboot
"
if [ "$1" == "off" ] && [ -d /sys/bus/pci/devices/0000:$busalt.0 ]; then #Disable nvidia gpu (confirm it is running before the command is executed to prevent errors, as it must be running for automatic detection of bus ID)
#The command below which disables the nvidia driver on boot, it may not be necessary, however there's no reason to leave them running in the background doing nothing, therefore I kept the command in.
echo "$(lsmod | grep nvidia | cut -d ' ' -f1 | sed 's/^/blacklist /')" | sudo tee /etc/modprobe.d/nvidia-off.conf
sudo sh -c "echo w /sys/bus/pci/devices/0000\\\\:$bus.*/remove - - - - 1 > /etc/tmpfiles.d/nvidia_off.conf"
sudo sh -c "echo w /proc/acpi/call - - - - \\\\\\\\_$acpi_id._OFF >> /etc/tmpfiles.d/nvidia_off.conf"
sudo systemctl enable root-resume
#Make sure this is the only Xorg config file that references the nvidia gpu! Uf there are any others left in Xorg likely will not launch properly.
sudo rm /etc/X11/xorg.conf.d/10-intel-nvidia-drm-outputclass.conf
echo "The nvidia GPU will be disabled upon reboot
"
elif [ "$1" == "on" ]; then #Re-enable nvidia gpu
sudo rm /etc/modprobe.d/nvidia-off.conf
sudo systemctl disable root-resume
sudo systemctl stop root-resume
sudo rm /etc/tmpfiles.d/nvidia_off.conf
#Add a xorg config file that references the nvidia gpu back in, otherwise Xorg may not launch properly.
sudo cp /usr/share/X11/xorg.conf.d/10-intel-nvidia-drm-outputclass.conf /etc/X11/xorg.conf.d/
echo "The Nvidia GPU will be enabled upon reboot
"
#the two commands below (must be run in order) will re-enable the nvidia gpu immediately, however I haven't found a way to get the nvidia driver to detect it again afterwards which is why they're commented out.
#sudo sh -c "echo \\\\_$acpi_id._ON > /proc/acpi/call"
#sudo sh -c "echo 1 > /sys/bus/pci/rescan"
else
echo "Usage: nvidia_toggle [arg]
on - Enables nvidia GPU (requires reboot)
off - Disable nvidia GPU (requires reboot)
"
fi
Here is /etc/systemd/system/root-resume.service
(required to keep gpu disabled after suspend)
[Unit]
Description=Local system resume actions
After=suspend.target
[Service]
Type=simple
ExecStart=/usr/bin/sh -c "echo 1 > /sys/bus/pci/devices/0000:01:00.*/remove; echo '\\_SB.PCI0.PEG0.PEGP._OFF' > /proc/acpi/call"
[Install]
WantedBy=suspend.target
Lastly, for truly extreme powersaving, the cpu frequency can be limited to it’s minimum
limit_cpufreq
:
#!/bin/sh
#Limit cpu frequency to 800mhz with auto-cpufreq
limit=800000
if [ "$1" == "on" ]; then #Limit cpu frequency to it's minimum
sudo cpufreqctl.auto-cpufreq --frequency-max --set=$limit
echo "CPU Frequency limited to $(( $limit / 1000 ))mHz"
elif [ "$1" == "off" ]; then #Unlimit cpu frequency (restore max freq to default)
sudo systemctl restart auto-cpufreq
echo "CPU Frequency limit reset"
elif [ "$1" == "toggle" ]; then #Unlimit cpu frequency (restore max freq to default)
if [ "$(cpufreqctl.auto-cpufreq --frequency-max)" == "$limit" ]; then
sudo systemctl restart auto-cpufreq
echo "CPU Frequency limit reset"
else
sudo cpufreqctl.auto-cpufreq --frequency-max --set=$limit
echo "CPU Frequency limited to $(( $limit / 1000 ))mHz"
fi
else
echo "Usage: cpu_limit [arg]
on - Limits cpu frequency to minimum
off - Resets limit on cpu frequency
toggle - Toggles limit on or off"
fi
With every setting applied, my power draw is 18.5w under idle loads, and can go up to about 32w under load
With no powersaving settings applied my power draw was around 50w on idle loads with up to ~160w under full load.
With all changes except the cpu frequency limiter applied, it uses 18.5-80w (I think with the igpu frequency not limited to it’s minimum this goes up a further 10-20w. didn’t properly test it)
A potential alternative to limiting the cpu frequency for greater powersaving that has been suggested is limiting the CPU cores (more testing required to determine which is better)
For reference, under windows with it’s power manager settings set to maximum power saving options and with the laptop manufacturer’s ‘eco mode’ engaged, I’ve seen idle load power draw go as low as 16w, however in general it will use aroun 25w with the occasional spike up to 45w under idle loads, so with these settings my linux installation has finally well and truly surpassed the best powersaving options windows seems to have on offer for my laptop.
Although even with all the settings on it seems windows is still more efficient with certain tasks (for instance in the OP i mentioned the difference in consumption browsing youtube on windows vs linux, with the new settings the consumption on linux doing that is 25-28w (instead of just more or less around 28w, so it’s improved a little bit at least) but that’s still 3-4w higher than what it is on windows; I suspect this might have something to do with the soundcard, i’ve done what I can to improve powersaving on it on linux but it seems that intel hd audio soundcards are very poorly supported on linux in general (more like they’re a nightmare on linux))