Manjaro/X11 环境下通过 bbswitch 关闭 NVIDIA 显卡以延长续航
本文适用于:
使用 X11 显示服务器的 Linux 桌面环境;
使用混合显卡(Intel + NVIDIA)的笔记本;
需要通过某种方式延长笔记本续航以应对个别场景的用户
去年大概十一月份吧,为了一些新鲜感以及续航问题,从Windows转向了Linux发行版,在一开始换成Ubuntu时,续航能撑个保底5小时,虽说仍不算很长,但至少是比起Windows下那两个小时的续航好很多了。但后来到今年一月份的时候不知道怎么回事续航突然又下降了不少,空载这功耗都能跑到40w。
后面又是来回折腾,从Ubuntu换成Manjaro,一直用到现在。刚换的时候续航也和Ubuntu一样,两个小时左右,那这就可以确定不是系统问题了,于是就看功耗情况,在限制频率的状态下,CPU功耗已经稳定到个位数了,但是总功耗还是能到30多w,其他的设备,比如屏幕、键盘、鼠标啥的,按理来说也不可能达到二十多瓦,于是就把目标放到显卡上。
在折腾了许久后,也算是找到了解决方法:禁用NVIDIA显卡模块+bbswitch关闭显卡电源。但需要注意的是,该方法中的完整脚本仅适用于NVIDIA显卡以及使用X11进行显示的窗口管理器,同时也无法做到热切换,在调整显卡激活情况后,需要重启才能生效。
具体实现
接下来步入正题,这套思路主要分为两部分,第一部分通过调整/etc/modprobe.d/
目录下的NVIDIA模块启用情况以及X11所用到的显卡,来确保NVIDIA模块在下次启动时不会被加载; 第二部分主要用于通过调用bbswitch
来关闭显卡电源,修改cpu的频率来达到真正的省电。
禁用NVIDIA模块
在/etc/modprobe.d
目录下需要准备文件blacklist-nvidia.conf.bak
,先加上.bak
后缀,等待后续需要时再手动激活。
install nouveau /bin/false
install nvidiafb /bin/false
install rivafb /bin/false
install nvidia /bin/false
install nvidia_drm /bin/false
install nvidia_modeset /bin/false
install nvidia_uvm /bin/false
同样的,在/etc/X11/xorg.conf.d/
也需要文件10-intel.conf.bak
指定使用Intel核显,也先写成未激活状态。
Section "Device"
Identifier "Intel Graphics"
Driver "modesetting"
Option "AccelMethod" "glamor"
EndSection
Section "Monitor"
Identifier "Monitor0"
Option "DPMS"
EndSection
Section "Screen"
Identifier "Screen0"
Device "Intel Graphics"
Monitor "Monitor0"
DefaultDepth 24
SubSection "Display"
Depth 24
EndSubSection
EndSection
Section "ServerLayout"
Identifier "Layout0"
Screen "Screen0"
EndSection
接下来就是切换脚本了,在~/.local/bin/
中新建文件toggle-nvidia
,文件内容如下:
#!/bin/bash
set -e # 遇到错误立即退出
# 检查并切换 modprobe 配置
if [ -f "/etc/modprobe.d/99-nvidia.conf" ]; then
sudo mv /etc/modprobe.d/99-nvidia.conf /etc/modprobe.d/99-nvidia.conf.bak
sudo mv /etc/modprobe.d/blacklist-nvidia.conf.bak /etc/modprobe.d/blacklist-nvidia.conf
sudo mv /etc/X11/xorg.conf.d/10-intel.conf.bak /etc/X11/xorg.conf.d/10-intel.conf
echo "Nvidia模块将被关闭..."
else
sudo mv /etc/modprobe.d/99-nvidia.conf.bak /etc/modprobe.d/99-nvidia.conf
sudo mv /etc/modprobe.d/blacklist-nvidia.conf /etc/modprobe.d/blacklist-nvidia.conf.bak
sudo mv /etc/X11/xorg.conf.d/10-intel.conf /etc/X11/xorg.conf.d/10-intel.conf.bak
echo "Nvidia模块将被启动..."
fi
echo "请重启系统"
脚本中的原NVIDIA模块配置文件名为99-nvidia.conf
,可根据实际文件名进行调整。
然后chmod +x ~/.local/bin/toggle-nvidia
赋予执行权限。现在运行toggle-nvidia
并重启之后,上面提到的几份配置就能够生效了(实际上只是把那几个文件重命名一下而已)。
关闭显卡电源
在上述配置生效之后,通过nvidia-smi
命令可以确定当前NVIDIA模块已经没有加载了,其他应用按说也是用不了NVIDIA显卡🤔。
但是我这边发现哪怕禁用了NVIDIA模块,实际上显卡仍在运行消耗电量,那么就需要bbswitch
来切断显卡电源。运行sudo pacman -S bbswitch
进行下载,然后运行命令加载bbswitch模块并关闭显卡电源:
sudo modprobe bbswitch
echo OFF | sudo tee /proc/acpi/bbswitch
我这边在尝试bbswitch
切断之后 ,虽说可以看到功耗明显降低,续航也大幅延长,但是启动某些应用之后功耗又会回升,可以确信是NVIDIA显卡又在吃电了,而且此时运行cat /proc/acpi/bbswitch
看到的状态已经变成了ON
,但是如果再直接运行echo OFF | sudo tee /proc/acpi/bbswitch
会发现不起作用,无法修改状态。
然后又是一顿折腾,最终发现重现加载bbswitch
模块后进行修改才能生效(这太奇怪了...
那这样的话也就好办了,虽说不懂原理,倒也能干!
在~/.local/bin/
下新建一个脚本integrate
,内容如下:
#!/bin/bash
if ! lsmod | grep -Eq "nvidia(_modeset|_uvm|_drm)?\b"; then
sudo modprobe bbswitch
echo OFF | sudo tee /proc/acpi/bbswitch
echo 192 | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference
echo 10000000 | sudo tee /sys/class/powercap/intel-rapl/intel-rapl:0/constraint_0_power_limit_uw
sudo cpupower frequency-set --governor powersave
xrandr --output eDP-1 --mode 1920x1080 --rate 60
# 启动 bbswitch 监测功能(放入后台)
nohup bash -c '
while true; do
if grep -q "ON" /proc/acpi/bbswitch; then
sudo rmmod bbswitch
sudo modprobe bbswitch
echo OFF | sudo tee /proc/acpi/bbswitch
fi
sleep 1
done
' >/dev/null 2>&1 &
echo "省电设置已应用,开启bbswitch监测"
else
echo "检测到nvidia模块,不执行省电设置"
fi
在脚本中,将先检查是否存在NVIDIA相关模块,再决定是否执行bbswitch
以及其他的操作,包括CPU功率限制、节能模式、CPU调速器(需要安装cpupower)以及屏幕刷新率什么的。同时也会放一个循环用于检测bbswitch
是不是又恢复了原状,并作出相应的调整,防止显卡又开始吃电。
总结
所以说,通过上面给出的两个脚本可以确定如下流程来达到省电效果:
toggle-nvidia -> 重启 -> integrate
等到不再需要省电场景时,运行toggle-nvidia
并重启即可。
总之,通过这种方式禁用NVIDIA模块、关闭显卡电源,也算是把显卡这一耗电大户给干掉了,目前我这边的续航也是能到5个小时,虽说比不上那些轻薄本吧,但差不多也足以应对那些需要长时间用到电脑,教室却又没有插座的情况了。
不过局限性也的确有,上面已经提到过:
需要注意的是,该方法中的完整脚本仅适用于NVIDIA显卡以及使用X11进行显示的窗口管理器,同时也无法做到热切换,在调整显卡激活情况后,需要重启才能生效。