混合图形技术是指在同一计算机上包含两张显卡。笔记本电脑制造商将两张性能和功耗不同的显卡置入一台笔记本电脑,使用混合图形技术来同时支持高性能和节能的使用场景,即在集成显卡的 3D 渲染性能不够用时使用专用/独立显卡。
有许多技术用于应对该问题,许多制造商也开发了自己的解决方案。这项技术在 Windows 上支持完善,但在 Linux 上依然不够完善。本文将简要解释一些方法和社区解决方案,以应对供应商对 GNU/Linux 缺乏支持的现况。
动态切换
大部分较新的混合图形技术使用两张显卡:一张专用/独立显卡,一张集成显卡,通过帧缓冲区进行协调,没有硬件多路复用器。集成显卡一直开启,而专用显卡仅在有高性能渲染需求时启用,节电时停用。大部分情况下无法仅使用专用显卡,且所有切换和渲染都由软件控制。 启动时,Linux 内核开始使用视频模式并设定低级图形驱动(low-level graphic drivers),这会被应用程序使用。大部分 Linux 发行版使用 X.org 创建图形环境。最后,一些其他软件被启动,先是登录管理器,然后是窗口管理器,再往后是其它软件。这个等级制的系统被设计为在单显卡的系统上使用。
完全关闭专用显卡
您可能想完全关闭高性能显卡以节省电池电量。
使用 BIOS/UEFI
一些笔记本电脑制造商在 BIOS 或 UEFI 添加了切换开关,用以禁用专用显卡。
使用 udev 规则
确保移除了所有与 NVIDIA 有关的显示管理器配置。
将 nouveau 驱动加入禁用列表:
/etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau options nouveau modeset=0
然后创建:
/etc/udev/rules.d/00-remove-nvidia.rules
# 如果 NVIDIA USB xHCI Host Controller 设备存在,则将其移除 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{power/control}="auto", ATTR{remove}="1" # 如果 NVIDIA USB Type-C UCSI 设备存在,则将其移除 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{power/control}="auto", ATTR{remove}="1" # 如果 NVIDIA Audio 设备存在,则将其移除 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{power/control}="auto", ATTR{remove}="1" # 移除NVIDIA VGA/3D controller 设备 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", ATTR{power/control}="auto", ATTR{remove}="1"
重启并执行 lspci
以查看您的 NVIDIA GPU 是否还在。
检查电量消耗以确保 GPU 没有偷偷耗电。如果依然耗电,或许可以使用 acpi_call 将其完全关闭。
使用 bbswitch
使用 NVIDIA GPU 时,这可以由 bbswitch 更安全地完成,其由一个内核包构成,会自动发出正确的 ACPI 信号以在不需要时禁用专用 GPU,或开机自动禁用。
- 译者注:由于 Bumblebee 页面年久失修,因此上述链接的段落不存在于本维基,您需要前往英文 ArchWiki 的相应页面查看。
使用 acpi_call
另外,对于 bbswitch 不支持的 GPU,相同的效果可以由手动安装的 acpi_call包 来完成。
安装后加载内核模块:
# modprobe acpi_call
内核模块加载后,执行位于 /usr/share/acpi_call/examples/turn_off_gpu.sh
的脚本。
该脚本会遍历并尝试关闭所有的数据总线,您会看到类似如下的输出:
# /usr/share/acpi_call/examples/turn_off_gpu.sh
Trying \_SB.PCI0.P0P1.VGA._OFF: failed Trying \_SB.PCI0.P0P2.VGA._OFF: failed Trying \_SB_.PCI0.OVGA.ATPX: failed Trying \_SB_.PCI0.OVGA.XTPX: failed Trying \_SB.PCI0.P0P3.PEGP._OFF: failed Trying \_SB.PCI0.P0P2.PEGP._OFF: failed Trying \_SB.PCI0.P0P1.PEGP._OFF: failed Trying \_SB.PCI0.MXR0.MXM0._OFF: failed Trying \_SB.PCI0.PEG1.GFX0._OFF: failed Trying \_SB.PCI0.PEG0.GFX0.DOFF: failed Trying \_SB.PCI0.PEG1.GFX0.DOFF: failed Trying \_SB.PCI0.PEG0.PEGP._OFF: works! Trying \_SB.PCI0.XVR0.Z01I.DGOF: failed Trying \_SB.PCI0.PEGR.GFX0._OFF: failed Trying \_SB.PCI0.PEG.VID._OFF: failed Trying \_SB.PCI0.PEG0.VID._OFF: failed Trying \_SB.PCI0.P0P2.DGPU._OFF: failed Trying \_SB.PCI0.P0P4.DGPU.DOFF: failed Trying \_SB.PCI0.IXVE.IGPU.DGOF: failed Trying \_SB.PCI0.RP00.VGA._PS3: failed Trying \_SB.PCI0.RP00.VGA.P3MO: failed Trying \_SB.PCI0.GFX0.DSM._T_0: failed Trying \_SB.PCI0.LPC.EC.PUBS._OFF: failed Trying \_SB.PCI0.P0P2.NVID._OFF: failed Trying \_SB.PCI0.P0P2.VGA.PX02: failed Trying \_SB_.PCI0.PEGP.DGFX._OFF: failed Trying \_SB_.PCI0.VGA.PX02: failed
看到 "works" 了么?这说明脚本找到了一个 GPU 所在的总线并已将该 GPU 关闭。您的电池续航延长应当能够证明这一点。
自动关闭 GPU
目前,GPU 会在下次启动时重新启用,欲解决,请在启动时加载模块:
/etc/modules-load.d/acpi_call.conf
#Load 'acpi_call.ko' at boot. acpi_call
在启动时加载
可以使用 systemd-tmpfiles 在启动时关闭 GPU:
/etc/tmpfiles.d/acpi_call.conf
w /proc/acpi/call - - - - \\_SB.PCI0.PEG0.PEGP._OFF
以上配置会在启动时被 systemd 加载。其将特定的 OFF 信号写入 /proc/acpi/call
文件。显然您需要将配置中的 \_SB.PCI0.PEG0.PEGP._OFF
修改为适用于您的系统的配置(注意您需要转义反斜杠)。
在 X 服务器初始化后加载
在部分系统上,在 X 服务器初始化前禁用专用 GPU 可能导致系统挂起。这种情况下,在 X 服务器初始化后可能是个更好的选择,可以由显示管理器来完成。在 LightDM 上,一个 display-setup-script seat 配置参数能够以 root 权限执行禁用 GPU 的脚本。如果使用 SDDM 则可以将 echo "\_SB.PCI0.PEG0.PEGP._OFF" > /proc/acpi/call
添加到 /usr/share/sddm/scripts/wayland-session
或 /usr/share/sddm/scripts/Xsession
,分别对应使用 Wayland 或 Xorg,将 \_SB.PCI0.PEG0.PEGP._OFF
修改为适用于您的系统的配置。
System76
一些 System76 笔记本(如 Oryx Pro)有其自己的混合图形选项。欲使用其自己的混合图形选项,请安装 system76-powerAUR,启用 system76-power.service
并运行 system76-power graphics hybrid
。
完全关闭专用 GPU
首先运行 system76-power graphics integrated
以确保您正在使用集成图形模式,然后重启电脑。在集成模式内,执行 system76-power graphics power off
以关闭专用 GPU,该命令并非永久生效,需要每次启动都执行一次。
疑难解答
部分应用程序启动时间延迟 30 秒
Vulkan 在被调用时会尝试初始化 /usr/share/vulkan/icd.d/nvidia_icd.json
中指定的可安装客户端驱动程序(Installable Client Driver,ICD),nvidia-utils包 配置该文件引用 libGLX_nvidia
驱动,以向 Vulkan 提供 GPU 驱动的路径。然而,若 GPU 被禁用,该驱动会初始化失败,导致部分应用程序(如基于 Chromium/Electron 的应用程序)启动需要等待 30 秒的超时。欲阻止 Vulkan 加载驱动以减缓超时,您可以使用 VK_DRIVER_FILES
环境变量覆盖 ICD JSON 文件的路径:
$ export VK_DRIVER_FILES=
禁用 NVIDIA 专用 GPU 后依然高功耗
如果使用 acpi_call 禁用专用 GPU 后功耗依然居高不下,请使用 lsmod
检查 nouveau 内核模块是否被加载,若没有则确保其已被安装,/etc/modprobe.d/
中所有 .conf
文件中屏蔽 Nouveau 的条目被移除,并且 Nouveau 内核模块在启动时被自动加载。重启后功耗应该就降低了。