跳转到内容
来自 Arch Linux 中文维基

混合图形技术是指在同一计算机上包含两张显卡。笔记本电脑制造商将两张性能和功耗不同的显卡置入一台笔记本电脑,使用混合图形技术来同时支持高性能和节能的使用场景,即在集成显卡的 3D 渲染性能不够用时使用专用/独立显卡。

有许多技术用于应对该问题,许多制造商也开发了自己的解决方案。这项技术在 Windows 上支持完善,但在 Linux 上依然不够完善。本文将简要解释一些方法和社区解决方案,以应对供应商对 GNU/Linux 缺乏支持的现况。

注意:除非您的设备生产于 2010 年前,否则其应当可以使用动态切换方法。以前的混合图形解决方案要么需要简单粗暴地重启电脑,要么需要重启整个图形栈(还得重新登录)才能生效。

动态切换

大部分较新的混合图形技术使用两张显卡:一张专用/独立显卡,一张集成显卡,通过帧缓冲区进行协调,没有硬件多路复用器。集成显卡一直开启,而专用显卡仅在有高性能渲染需求时启用,节电时停用。大部分情况下无法使用专用显卡,且所有切换和渲染都由软件控制。 启动时,Linux 内核开始使用视频模式并设定低级图形驱动(low-level graphic drivers),这会被应用程序使用。大部分 Linux 发行版使用 X.org 创建图形环境。最后,一些其他软件被启动,先是登录管理器,然后是窗口管理器,再往后是其它软件。这个等级制的系统被设计为在单显卡的系统上使用。

注意:请参阅 NVIDIA OptimusBumblebee 以了解使用 NVIDIA 专有驱动的混合图形技术的详细信息。请参阅 PRIME 以了解更为全面的(包括 AMDGPUnouveauNVIDIA 专有驱动)方案。

完全关闭专用显卡

您可能想完全关闭高性能显卡以节省电池电量。

使用 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,或开机自动禁用。

注意:bbswitch 从内核版本 4.8 开始不使用 PCI-E 接口电源管理方法。请参阅 Bumblebee#Broken power management with kernel 4.8 以了解详细信息。
译者注:由于 Bumblebee 页面年久失修,因此上述链接的段落不存在于本维基,您需要前往英文 ArchWiki 的相应页面查看。

使用 acpi_call

另外,对于 bbswitch 不支持的 GPU,相同的效果可以由手动安装的 acpi_call 来完成。

提示:对于不在官方仓库内的内核,可以改为安装 acpi_call-dkms,另见 DKMS

安装后加载内核模块:

# 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 后遇到系统休眠和挂起问题,请尝试通过向其发送相应的 acpi_call 以重新启用它,另见电源管理/挂起与休眠#自定义 systemd 单元
自动关闭 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,分别对应使用 WaylandXorg,将 \_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

附注:Vulkan#AMDGPU - Vulkan 应用程序启动过慢 及其相似,只是本文完全没有为相应的环境变量设定适当的参数。(在 Talk:混合图形技术 中讨论)

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 内核模块在启动时被自动加载。重启后功耗应该就降低了。

提示:请参阅内核模块以了解更多关于内核模块加载和屏蔽的详细信息。
注意:如果重启后亮度控制出现问题,/sys/class/backlight 有多个目录,请将 acpi_backlight=native 添加到内核参数