外接显卡 - Arch Linux 中文维基

跳转到内容

# 外接显卡

来自 Arch Linux 中文维基

相关文章

- Xorg
- PRIME
- Thunderbolt
- NVIDIA Optimus
- NVIDIA/Tips and tricks
- Docking

翻译状态：

- 本文（或部分内容）译自 External GPU，最近一次同步于 2024-07-20，若英文版本有所更改，则您可以帮助同步与翻译更改的内容。
- 您可以在 ArchWiki 的对应页面找到本文翻译的原始修订历史。
- 本文可能与英文原文存在出入。

在搭载了雷电 3+ 或 USB4的设备上，可以通过显卡拓展坞连接一张桌面级的外接显卡（eGPU）。eGPU.io 是一个专门讨论外接显卡的社区论坛。尽管大多数时候仍需一些手动配置（如下），Linux 对外接显卡的支持相当不错。

注意：对于搭载了 USB4 的笔记本，其传输速率一般被设置为最小值（20 Gbit/s）。可以手动将其设置得更高（40，80 或更高）来获取更佳的体验。如果您的拓展坞使用雷电接口，可以启用笔记本的 USB4 模式来达到相同效果。

## 安装

### 雷电

使用雷电接口的拓展坞在插入前可能首先需要经过设备认证（取决于 BIOS/UEFI 配置）。详见 Thunderbolt#User device authorization。如果成功插入，外接显卡将在 `lspci` 中显示。

    $ lspci | grep -E 'VGA|3D'

    00:02.0 VGA compatible controller: Intel Corporation UHD Graphics 620 (rev 07)             # 集成显卡
    1a:10.3 VGA compatible controller: NVIDIA Corporation GP107 [GeForce GTX 1050] (rev a1)    # 外接显卡

根据电脑的硬件和拓展坞的硬件情况，雷电接口会限制主机与外接显卡间的带宽。限制程度取决于 PCIe 通道数和封装的DMI互联接口（OPI）模式：

    # dmesg | grep PCIe

    [19888.928225] pci 0000:1a:10.3: 8.000 Gb/s available PCIe bandwidth, limited by 2.5 GT/s PCIe x4 link at 0000:05:01.0 (capable of 126.016 Gb/s with 8.0 GT/s PCIe x16 link)

### 驱动

您应该安装与您的外接显卡兼容的驱动程序：

- AMDGPU AMD 驱动
- NVIDIA 专有 NVIDIA 驱动
- Nouveau 开源 NVIDIA 驱动

成功安装后，`lspci -k` 应当显示显卡与驱动已经成功绑定：

    $ lspci -k

    1a:10.3 VGA compatible controller: NVIDIA Corporation GP107 [GeForce GTX 1050] (rev a1)
            Subsystem: NVIDIA Corporation GP107 [GeForce GTX 1050]
            Kernel driver in use: nvidia
            Kernel modules: nouveau, nvidia_drm, nvidia

注意，在某些情况下，AMDGPU 驱动（无论使用雷电接口还是 USB4）可能会被设置为错误的 pcie_gen_gap 模式，然后回滚到 PCIe 1.1 的速率。这可能会导致性能严重降低。 可以通过调整模块参数（见内核模块#使用 /etc/modprobe.d/中的文件) 或传递内核参数来解决以上问题。

    /etc/modprobe.d/amd-egpu-pcie-speed.conf

    options amdgpu pcie_gen_cap=0x40000

这会将速率设置为 PCIe 3 模式。完整的参数选项见 amd_pcie.h。

## 显卡计算

在完成 #安装之后，像 GPGPU#CUDA 这样无需在屏幕上显示的纯计算工作，理论上无需额外配置即可使用。nvidia-smi 工具（由 nvidia-utils包 提供）在使用专有 NVIDIA 驱动时应该能正常运行。专有的 NVIDIA NVENC/NVDEC 也应该正常运行（不包括与 OpenGL 的互操作）。

在这种使用场景下，热插拔也应该受支持（对拔出支持取决于驱动程序）。不过，对于 NVIDIA 设备，使用 `nvidia-persistenced` 会导致热拔出时设备出现故障。

## Xorg

通过一些额外配置，您可以将集成显卡（iGPU）和外接显卡（eGPU）结合起来使用。这样配置有其优点，但也会带来一些额外的问题。

### Xorg 在外接显卡上渲染，PRIME 显示分载到集成显卡

- 大多数使用显卡的程序可以正常执行在外接显卡上：`glxinfo`/`glxgears`, `eglinfo`/`eglgears_x11`, `NVENC`/`NVDEC`（包括与 OpenGL 的互操作）。
- Xorg 仅能在外接显卡接入后启动。
- 连接到外接显卡上的显示器开箱即用，而 PRIME显示分载适用于连接到集成显卡的显示器（例如笔记本内屏）。

有关这些内容，见 PRIME#将独立显卡作为主 GPU 和 PRIME#反向 PRIME。 同时，NVIDIA 官方驱动文档也有教程： Chapter 33. Offloading Graphics Display with RandR 1.4.

Xorg 的配置文件应该像如下所示：

    /etc/X11/xorg.conf.d/80-egpu-primary-igpu-offload.conf

    Section "Device"
        Identifier "Device0"
        Driver     "nvidia"
        BusID      "PCI:26:16:3"                 # 根据 lspci 填写，将十六进制转换为十进制。
        Option     "AllowExternalGpus" "True"    # 专有 NVIDIA
     驱动所需。
    EndSection

    Section "Module"
        # 为集成显卡加载 modesetting 模块，其提供程序应当是 XrandR 1.4。
        Load "modesetting"
    EndSection

注意：Xorg 使用十进制的总线 ID，但大多数工具使用十六进制。在 `xorg.conf` 中，必须将形如 `1a:10.3` 的总线 ID转换为 `26:16:3`。
提示：在更新的 Xorg 中，无需指定 `ServerLayout` 和 `Screen` 项，这些项将会被自动推断。 第一个定义的 `Device` 会被首先考虑。

要确认此次设置是否有效，使用 `xrandr --listproviders` 检查。输出应当如下：

    Providers: number : 2
    Provider 0: id: 0x1b8 cap: 0x1, Source Output crtcs: 4 outputs: 4 associated providers: 0 name:NVIDIA-0
    Provider 1: id: 0x1f3 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 5 associated providers: 0 name:modesetting

要输出到笔记本内屏及其他连接到集成显卡上的显示，可以使用 RandR 1.4 PRIME显示分载。请使用 `xrandr --listproviders` 输出的设备名：

    xrandr --setprovideroutputsource modesetting NVIDIA-0 && xrandr --auto

注意：`xrandr --auto` 是可选的命令，可以使用其他任何基于 RandR 的显示配置工具替代。这条命令只是防止出现屏幕全黑的情况。

要在显示管理器弹出登录页面或启动桌面环境之前执行这条命令，见 Xrandr#Configuration 和 Xinit。

Vulkan 可能会自行枚举 Xorg 上的所有显卡，所以如果要在本配置下执行如 `vkcube` 这样的程序，可能需要传递参数 `--gpu_number 1`。另外，也可以使用此参数以在枚举期间对显卡重新排序：`__NV_PRIME_RENDER_OFFLOAD=1 vkcube` 或者等效的 `prime-run vkcube`。

提示：在笔记本上使用 optimus-manager 时，仅需将外接显卡的 `BusID` 放入位于 `/etc/optimus-manager/xorg/` 下的管理模式与显卡的配置文件中，就可以在外接显卡上渲染。

### Xorg 在集成显卡上渲染，PRIME 渲染分载到外接显卡

- 程序默认在集成显卡上渲染，但 PRIME 渲染分载可以使程序在外接显卡上渲染。
- Xorg 可以在未连接外接显卡时启动，但在连接外接显卡后，必须重启 Xorg 才能使用渲染与显示分载。
- 连接到集成显卡上的显示器（例如笔记本内屏）开箱即用，而 PRIME 显示分载适用于连接到外接显卡上的显示器。

详细内容见 PRIME#PRIME 显卡分载。NVIDIA 官方驱动文档中也有记录：Chapter 34. PRIME Render Offload。

对大多数独立显卡而言，此模式应当是默认模式，无需手动配置 Xorg。如果存在问题，或是在使用专有 NVIDIA 驱动，应当如下配置：

    /etc/X11/xorg.conf.d/80-igpu-primary-egpu-offload.conf

    Section "Device"
        Identifier "Device0"
        Driver     "modesetting"
    EndSection

    Section "Device"
        Identifier "Device1"
        Driver     "nvidia"
        BusID      "PCI:26:16:3"                 # 根据 lspci 填写，将十六进制转换为十进制。
        Option     "AllowExternalGpus" "True"    # 专有 NVIDIA 驱动所需。
    EndSection

要确认是否配置成功，执行 `xrandr --listproviders` 时，应当显示如下内容：

    $ xrandr --listproviders

    Providers: number : 2
    Provider 0: id: 0x47 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 5 associated providers: 0 name:modesetting
    Provider 1: id: 0x24a cap: 0x2, Sink Output crtcs: 4 outputs: 4 associated providers: 0 name:NVIDIA-G0

本文或本章节可能需要合并到PRIME#配置应用程序使用 GPU 渲染。

附注： 也许应该在专门的页面探讨这些问题，而不是在这里。（在 Talk:外接显卡 中讨论）

要让某些程序在外接显卡上渲染，可以用以下方式启用 PRIME 渲染分载：

- 对于专有 NVIDIA 驱动：

      $ __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia some_program

- 对于专有 NVIDIA 驱动（封装版）：

      $ prime-run some_program

- 对于开源驱动：

      $ DRI_PRIME=1 some_program

要输出到连接至外接显卡的显示器，还可以这样使用 RandR 1.4 PRIME 显示分载：

    $ xrandr --setprovideroutputsource NVIDIA-G0 modesetting && xrandr --auto

提示：提供程序的顺序并不相同，同时 NVIDIA 的命名也稍有不同。

NVIDIA 驱动版本 460.27.04+ 优化了在一些特定情形下对渲染和显示分载的结合支持：

  添加了对 “反向 PRIME 绕行”（Reverse PRIME Bypass）的支持，这使得当某一渲染分载程序处于全屏，非重定向，且仅在给定的使用 NVIDIA 驱动的 PRIME 显示分载输出中显示时，可以绕过 PRIME 渲染分载和 PRIME 显示分载的带宽限制。当 X 服务器启用详细日志时，可以在 X 日志中找到此特性的使用情况。

### 在外接显卡上执行多个独立 Xorg 实例

详见 Nvidia-xrun#External GPU setup.

### 在 Xorg 上使用外接显卡的已知问题

- 大多数独立显卡的 Xorg 驱动不支持热插入：必须在启动 Xorg 前插入外接显卡。注销后重新登录即可重启 Xorg。
- 完全不支持热拔出：这样会导致系统不稳定或卡死（根据 NVIDIA 官方文档）。

## Wayland

有关 Wayland 对外接显卡（或多显卡）支持程度的测试目前尚为数不多，不过理论上其相对于 Xorg 来说配置会更为便捷。

需要注意的是，Wayland 混成器尚无对显卡热插拔的明确支持，不过大多数混成器已经在某种程度上支持了：

- KDE's kwin: https://invent.kde.org/plasma/kwin/-/merge_requests/811
- GNOME's Mutter: https://gitlab.gnome.org/GNOME/mutter/-/issues/17, https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1562
- wl-roots: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1278

使用开源驱动时，需要这样执行 DRI 分载：

    $ DRI_PRIME=1 some_program

一些像 all-ways-egpu 这样的项目正致力于在 Wayland 下提供更为便捷的显卡切换方法。

### 热插拔 NVIDIA 外接显卡

Wayland 支持在使用 PRIME 时热插拔外接显卡。NVIDIA 独立显卡对 PRIME 的优秀支持同样适用于外接显卡。

首先，确保没有进程正在使用 NVIDIA 模块。每个 EGL 程序会占用 1MB 的独显显存，即使其运行在集成显卡上。可以通过 `nvidia-smi` 查看是否有此类进程。 为防止出现此类问题，请将`__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json` 设置为环境变量。 不过，最好将其放在 `/etc/environment.d/50_mesa.conf` 中。

然后，卸载 NVIDIA 模块：

    # rmmod nvidia_uvm
    # rmmod nvidia_drm
    # rmmod nvidia_modeset
    # rmmod nvidia

模块卸载完成后，就可以连接外接显卡。显卡初始化完毕后，使用 `modprobe nvidia-drm` 或 `modprobe nvidia-current-drm` 重新加载 NVIDIA 模块。使用哪条命令取决于模块的来源，例如从 NVIDIA 官网下载或是使用软件包管理器直接安装。在某些情况下（例如 GIGABYTE AORUS GAMING BOX）外接显卡可能不兼容专有驱动，因此需要使用开源驱动的命令：`modprobe nvidia-current-open-drm`。

模块加载成功后，PRIME 就应该能正常使用，不过因为我们设置了 `__EGL_VENDOR_LIBRARY_FILENAMES` 变量来使用 MESA，所以在启动程序前需要添加 `__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/10_nvidia.json`。完整的环境变量列表如下：

    __GLX_VENDOR_LIBRARY_NAME=nvidia __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/10_nvidia.json %command%

对于 GNOME 用户，可能需要修补 switcheroo-control包 来将 `__EGL_VENDOR_LIBRARY_FILENAMES` 包含到环境变量中。这将允许程序原生运行在外接显卡上，不会出现鼠标错位，而且能“使用独立显卡启动”。不过，关于如何修补，就不在本篇文章的讨论范围之内了。

### 热插拔 NVIDIA 外接显卡，并临时停用 NVIDIA 独立显卡

如果您同时拥有集成显卡（iGPU）和 NVIDIA 独立显卡（dGPU），并且尝试连接 NVIDIA 外接显卡（eGPU），显卡间会产生冲突，这会导致只有独立显卡能够使用。要解决冲突，必须临时停用独立显卡，这样 NVIDIA 驱动就不会识别到它。最好的方法就是覆盖驱动。

首先，卸载 NVIDIA 驱动模块：

    # rmmod nvidia_uvm
    # rmmod nvidia_drm
    # rmmod nvidia_modeset
    # rmmod nvidia

然后，使用 driverctlAUR 工具覆盖独立显卡驱动。在下面的例子中，使用 0000:01:00.0 代表独立显卡的地址。您设备的独立显卡地址可以使用 `lspci` 查看。

    # driverctl --nosave set-override 0000:01:00.0 vfio-pci

建议使用参数 `--nosave`，否则 driverctl 会在系统启动时覆盖驱动。这样，在出错的时候，仅需重启就可以恢复独立显卡。

独立显卡禁用后，就可以使用 `modprobe nvidia-drm` 加载内核模块，然后使用 `nvidia-smi` 检查其显示一张或两张显卡。

重新启动独立显卡有点麻烦，因为它很反直觉。首先，卸载 NVIDIA 模块，拔出外接显卡，然后执行以下命令：

    # modprobe nvidia-current
    # driverctl --nosave unset-override 0000:01:00.0
    # modprobe nvidia-current
    # driverctl --nosave unset-override 0000:01:00.0
    # modprobe nvidia-current-modeset
    # modprobe nvidia-current-drm

前两个命令需要执行两次，这看起来尽管很奇怪，不过只有这样才能重新启动独立显卡。第一次执行命令时可能会报错，不过这并不重要。

分类：​

- 图形
- X 服务器

隐藏分类：​

- 使用“模板:合并”标记的页面或章节

外接显卡
添加话题