混合显卡

出自 ArchWiki

混合显卡是一种涉及在同一台计算机上使用两块显卡的概念。笔记本电脑制造商开发了在单台计算机上使用两种不同性能和功耗显卡的技术。混合显卡旨在支持高性能和节能用例,方法是保持独立/离散图形处理器处于非活动状态,除非其 3D 渲染性能在集成图形处理器之上是必需的。

存在各种各样的技术,每个制造商都开发了自己的解决方案来解决这个问题。这项技术在 Windows 上得到了很好的支持,但在 Linux 发行版中仍然存在一些粗糙之处。本文将尝试简单解释每种方法,并描述一些社区解决方案,以解决供应商缺乏 GNU/Linux 系统支持的问题。

注意: 除非您的设置是 2010 年之前的,否则很可能使用的是动态切换模型。以前的混合显卡解决方案要么需要重启(最粗糙的方式),要么需要完全图形堆栈重启,这需要重新登录才能生效。

动态切换

大多数新的混合显卡技术都涉及两块显卡:专用显卡和集成显卡连接到帧缓冲区,并且没有硬件多路复用器。集成显卡始终处于开启状态,而专用显卡在需要省电或高性能渲染时开启/关闭。在大多数情况下,无法使用专用显卡,所有切换和渲染都由软件控制。启动时,Linux 内核开始使用视频模式并设置应用程序将使用的底层图形驱动程序。大多数 Linux 发行版然后使用 X.org 创建图形环境。最后,启动其他一些软件,首先是登录管理器,然后是窗口管理器,等等。这种分层系统旨在用于大多数情况下的单显卡。

注意: 阅读 NVIDIA OptimusBumblebee 以了解 NVIDIA 使用混合显卡和 NVIDIA 专有驱动程序的详细信息。阅读 PRIME 以了解基本上所有其他内容(例如 AMD 或 NVIDIA GPU 与 nouveau 驱动程序)。

完全关闭独立 GPU 电源

您可能希望关闭高性能图形处理器以节省电池电量。

使用 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
# Remove NVIDIA USB xHCI Host Controller devices, if present
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{power/control}="auto", ATTR{remove}="1"

# Remove NVIDIA USB Type-C UCSI devices, if present
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{power/control}="auto", ATTR{remove}="1"

# Remove NVIDIA Audio devices, if present
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{power/control}="auto", ATTR{remove}="1"

# Remove NVIDIA VGA/3D controller devices
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#内核 4.8 损坏的电源管理

使用 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 后遇到休眠或挂起系统的问题,请尝试通过发送相应的 acpi_call 再次启用它。另请参阅 电源管理/挂起和休眠#自定义 systemd 单元
自动关闭 GPU

目前,芯片将在下次重启时重新开启。为了解决这个问题,在启动时加载模块

/etc/modules-load.d/acpi_call.conf
#Load 'acpi_call.ko' at boot.
acpi_call
在启动时

要在启动时关闭 GPU,可以使用 systemd-tmpfiles

/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 服务器初始化后禁用 GPU,这可以通过一些显示管理器实现。例如,在 LightDM 中,可以使用 display-setup-script 座位配置参数来执行一个以 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。此命令不是持久性的,每次启动后都需要运行。

故障排除

某些应用程序启动时间延迟 30 秒

这篇文章或章节是与 Vulkan 合并的候选对象。

注意: 这似乎与 Vulkan#AMDGPU - Vulkan 应用程序启动缓慢 非常相似,除了它完全取消设置变量,而不是根据使用的 iGPU 为其传递正确的值。(在 Talk:Hybrid graphics 中讨论)

调用时,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 后功耗仍然很高

如果在禁用独立 GPU 总线 #使用 acpi_call 后,功耗仍然很高,请检查是否加载了 nouveau 内核模块,使用 lsmod 命令。如果未加载,请确保已安装它,删除 /etc/modprobe.d/ 中任何禁用 Nouveau 的 .conf 文件中的条目,并确保 Nouveau 内核模块在启动时自动加载。重启后,功耗应该会降低。

提示: 另请参阅 内核模块 以了解有关内核模块加载和禁用的更多详细信息。
注意: 如果重启后您在亮度控制方面遇到问题,并且在 /sys/class/backlight 中有多个目录,请将 acpi_backlight=native 行添加到您的 内核参数