前言#
当 Linux 中存在多张显卡时,理所当然的会存在程序显卡选择上的问题。
例如游戏选择了核显而非独显运行,浏览器选择了解码单元较弱且较为耗电的独显运行。
这些是用户所不希望的行为,所幸,mesa 给我们提供了一些可以手动指定显卡设备的环境变量。
默认情况#
我们可以使用 MESA_VK_DEVICE_SELECT=list vulkaninfo
查看当前可用的显卡信息。
selectable devices:
GPU 0: 1002:67df "AMD Radeon RX 580 Series (RADV POLARIS10)" discrete GPU 0000:10:00.0
GPU 1: 1002:1638 "AMD Radeon Graphics (RADV RENOIR)" integrated GPU 0000:30:00.0
例如这里拥有两张显卡,GPU 0
为独立显卡 (dGPU),GPU 1
为核显 (iGPU)。
使用 glxinfo
和 vkcube
来进行 opengl
和 vulkan
应用的简单测试。
❯ glxinfo | rg Device
Device: AMD Radeon Graphics (radeonsi, renoir, ACO, DRM 3.61, 6.14.2-2-cachyos) (0x1638)
❯ vkcube
Selected WSI platform: xcb
Selected GPU 1: AMD Radeon RX 580 Series (RADV POLARIS10), type: DiscreteGpu
其中 glxinfo
选择了核显,而 vkcube
选择了独显。
根据 mesa #24750 所述,
vkcube
似乎总是会优先适用独显
环境变量#
在 mesa 的文档中,我们注意到其中 DRI_PRIME 和 MESA_VK_DEVICE_SELECT 这两个变量是和设备选择相关的。
DRI_PRIME
默认 GPU 是 Wayland/Xorg 使用的或连接到显示器的 GPU。此变量允许选择不同的 GPU。它适用于 OpenGL 和 Vulkan(在这种情况下,“选择”意味着该 GPU 将排在报告的物理设备列表的首位)。支持的语法有:
DRI_PRIME=N
: 选择第 N 个非默认 GPU(N > 0)。DRI_PRIME=pci-0000_02_00_0
: 选择连接到此 PCIe 总线的 GPUDRI_PRIME=vendor_id:device_id
: 选择匹配这些 ID 的第一个 GPU。
对于 Vulkan,可以附加
!
,这样只有选定的 GPU 会暴露给应用程序(例如:DRI_PRIME=1!)。MESA_VK_DEVICE_SELECT
当设置为“list”时,打印设备列表。当设置为“vid:did”时,从 PCI 设备中选择编号。该 PCI 设备将被设为默认设备。默认设备会在 vkEnumeratePhysicalDevices API 中作为第一个设备返回。使用“vid:did!”的效果与使用
MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE
变量相同。即被识别为默认的设备将是 vkEnumeratePhysicalDevices API 中唯一返回的设备。
配置#
由于 DRI_PRIME
已经适用于 OpenGL 和 Vulkan,一般情况下只需要配置它就足够了。
经测试,在两者同时设置时,
MESA_VK_DEVICE_SELECT
似乎会优先于DRI_PRIME
对vkcube
生效
虽然 DRI_PRIME
支持 DRI_PRIME=N
的写法,这里不建议这样使用,因为 DRI_PRIME=N!
并不能强制使应用使用序号为 N 的显卡。
❯ DRI_PRIME=0! vkcube
Selected WSI platform: xcb
Selected GPU 1: AMD Radeon RX 580 Series (RADV POLARIS10), type: DiscreteGpu
❯ DRI_PRIME=1! vkcube
Selected WSI platform: xcb
Selected GPU 0: AMD Radeon RX 580 Series (RADV POLARIS10), type: DiscreteGpu
而使用 DRI_PRIME=vendor_id:device_id!
时正常运作。
❯ DRI_PRIME=1002:1638! vkcube
Selected WSI platform: xcb
Selected GPU 0: AMD Radeon Graphics (RADV RENOIR), type: IntegratedGpu
因此,在我们想要指定显卡的应用程序运行前加上 DRI_PRIME=vendor_id:device_id!
就能强制使其使用指定的显卡了。
应用#
使用
MESA_VK_DEVICE_SELECT=list vulkaninfo
查看显卡 id,替换下面样例中的vid:did
一般情况下,使用带感叹号 DRI_PRIME=vid:did!
的并不必要,其会使 vid:did
对应的设备成为应用程序中唯一可见的设备。
建议仅当指定了设备,但应用仍然默认使用另一张显卡或同时使用多张显卡时才使用 !
。
Steam#
右键游戏 - 属性 - 通用 - 启动选项中填入 DRI_PRIME=vid:did %command%
即可。
命令行程序#
DRI_PRIME=vid:did example_binary
或
env DRI_PRIME=vid:did example_binary
通过 drun 或 launcher 启动的软件#
修改其入口 /usr/share/applications/whatever.desktop
,在 Exec
字段最前面插入 env DRI_PRIME=vid:did
。
例如 Exec=env DRI_PRIME=vid:did whatever %F
建议将对应的
.desktop
文件复制到~/.local/share/applications/
中,避免应用更新后.desktop
被覆盖
全局#
不太推荐,可能会搞坏一些东西
如果在将显卡 A(例如核显)用作所有的桌面渲染、视频输出(连接显示器);显卡 B 只在运行游戏、AI 或其他更适合在 B 上运行的任务时手动指定调用,则可以考虑将 DRI_PRIME
设置为全局变量。这样可以将大部分的日常任务负载从显卡 B 上转移到显卡 A,可以维持显卡 B 的长时间休眠以省下一些电以及降低些许温度(理论上)。
编辑 /etc/environment
(对系统生效)或者 ~/.profile
(对用户生效),添加 DRI_PRIME=vid:did
。
包装脚本#
你可以使用一个脚本来更方便地使用环境变量。或者同时使用 mangohud
gamemode
等。
在 ~/.local/bin
中创建一个脚本 exec-dgpu
。
#!/bin/bash
DRI_PRIME=vid:did "$@"
在运行软件时只需要 exec-dgpu whatever
即可。