跳至內容
出自 Arch Linux 中文维基

在搭載了雷電 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)

驅動

您應該安裝與您的外接顯卡兼容的驅動程序:

成功安裝後,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#將獨立顯卡作為主 GPUPRIME#反向 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 中,無需指定 ServerLayoutScreen 項,這些項將會被自動推斷。 第一個定義的 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#ConfigurationXinit

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 混成器尚無對顯卡熱插拔的明確支持,不過大多數混成器已經在某種程度上支持了:

使用開源驅動時,需要這樣執行 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-drmmodprobe 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

前兩個命令需要執行兩次,這看起來儘管很奇怪,不過只有這樣才能重新啟動獨立顯卡。第一次執行命令時可能會報錯,不過這並不重要。