Hybrid graphics on Linux: Intel iGPU plus NVIDIA eGPU for headless compute

Hybrid graphics on Linux - Intel iGPU desktop plus NVIDIA Thunderbolt eGPU for headless compute

Running an Intel integrated GPU alongside an NVIDIA Thunderbolt eGPU used only for compute on Linux — xe versus i915 binding on Arrow Lake, how the desktop picks a primary GPU, keeping GNOME off the eGPU, PRIME render offload versus pure CUDA, and sharing one 16 GB GPU between several compute servers.

verified-as-of: 2026-09-25 Tags: [SOURCED url] = read/returned by a fetched page or search result during the research pass; [INFERRED] = reasoned from mechanism, verify on your box; [BOX] = observed on the reference machine (Intel NUC 15 Pro, Arrow Lake-P iGPU at 00:02.0, Ubuntu 26.04.1 GNOME Wayland, kernel 7.0.0-34, RTX 5080 over TB4, nvidia 610.57.04-open loaded late).

Core Concepts

  1. Two independent GPU roles. A display/compositor GPU owns scanout and the desktop; a compute GPU only runs CUDA/Vulkan-compute. In a hybrid box the goal is usually: iGPU = display, eGPU = compute only. Arch’s eGPU page states compute-only workloads (CUDA) that display nothing “should work without any extra configuration”, and monitors on the iGPU work out of the box [SOURCED https://wiki.archlinux.org/title/External_GPU via search result].
  2. Kernel driver vs userspace stack. xe/i915 (kernel DRM drivers for Intel) and nvidia/nvidia_drm (NVIDIA) are separate kernel stacks; CUDA talks to the nvidia module through /dev/nvidia*, not through DRM. DRM nodes (/dev/dri/cardN, renderDN) matter only to compositors, Vulkan/EGL/GL and PRIME. [INFERRED]
  3. Compositor multi-GPU model. Mutter picks one primary GPU, composites there, and copies buffers to displays on other GPUs [SOURCED https://github.com/GNOME/mutter/blob/main/doc/multi-gpu.md]. Any DRM device it can open may still get probed/initialised, which is the likely source of a few MiB of gnome-shell VRAM on a second GPU [INFERRED].
  4. PRIME render offload = per-application choice of render GPU while display stays on the primary; pure compute = no graphics API at all. They are different mechanisms; CUDA does not need PRIME [INFERRED from NVIDIA PRIME README scope].
  5. Selection is by identifiers, not by order. Device ordering (nvidia-smi index, card0/card1) is not stable across a late-arriving eGPU; use PCI address or UUID [SOURCED CUDA docs https://docs.nvidia.com/cuda/cuda-programming-guide/05-appendices/environment-variables.html for UUID/PCI_BUS_ID].
  6. VGA arbiter / boot_vga. The kernel marks one VGA-class device boot_vga (sysfs /sys/bus/pci/devices/<addr>/boot_vga); the firmware-initialised device normally wins, so an iGPU usually keeps it when an eGPU appears later. Effects of a late-arriving eGPU on vgaarb are [INFERRED]; the vga_switcheroo kernel page does not cover boot_vga [SOURCED https://docs.kernel.org/gpu/vga-switcheroo.html, negative finding]. An RFC exists to let users select the primary adapter at boot [SOURCED https://lkml.iu.edu/hypermail/linux/kernel/2309.0/02231.html (search result title only)].

xe vs i915 on Arrow Lake

Copy-paste checks (read-only)

lspci -nnk -s 00:02.0                       # "Kernel driver in use:" is the binder
readlink /sys/bus/pci/devices/0000:00:02.0/driver
cat /sys/module/xe/parameters/force_probe /sys/module/i915/parameters/force_probe 2>&1
cat /proc/cmdline | tr ' ' '\n' | grep -E 'force_probe|nvidia'

Primary GPU Selection

# /etc/udev/rules.d/61-mutter-preferred-primary-gpu.rules
SUBSYSTEM=="drm", KERNEL=="card*", SUBSYSTEMS=="pci", ATTRS{vendor}=="0x8086", TAG+="mutter-device-preferred-primary"

[INFERRED from the documented shape; NOT verified end-to-end] A new udev rule applies to cards that appear afterwards; on the live desktop, do not run udevadm trigger against the drm subsystem to force it. Take effect at next boot, then check the log line below.

Keeping the Desktop Off the eGPU

nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv
nvidia-smi --query-gpu=index,pci.bus_id,uuid,memory.used --format=csv
nvidia-smi                                  # "Graphics" (type G) entries = gnome-shell/Xwayland; "C" = compute
ls -l /dev/dri/by-path/                     # which cardN is which PCI address
cat /sys/module/nvidia_drm/parameters/modeset /sys/module/nvidia_drm/parameters/fbdev 2>&1
lsmod | grep -E '^(nvidia|nvidia_drm|nvidia_uvm|nvidia_modeset)'

PRIME Offload vs Headless Compute

Decision table

Goal Config Desktop uses eGPU? Needs nvidia_drm modeset Main risk
Desktop on iGPU, eGPU headless compute (recommended for this box, [INFERRED] and not yet verified on it) Pin iGPU with mutter tag; nvidia_drm modeset=0 fbdev=0 or blacklist; CUDA apps only No (except residual few MiB unless drm is off) No If nvidia_drm stays on, gnome-shell keeps small VRAM footprint
PRIME render offload (some GUI/Vulkan apps on the eGPU) iGPU primary + __NV_PRIME_RENDER_OFFLOAD=1 / DRI_PRIME per app Per-app only Yes eGPU absence breaks those apps; extra VRAM per graphical client
eGPU as display (monitors on eGPU or primary=eGPU) udev tag on NVIDIA card; modeset=1 Yes, all of it Yes Session may die or restart if the eGPU drops or arrives late [INFERRED]; see hazards

The table is design guidance derived from the sourced sections above; only the rows’ cited facts are sourced.

Multiple Compute Apps on One GPU

Hazards: eGPU absent or arriving late

  1. Boot without eGPU: the iGPU is boot_vga and the session is unaffected as long as nothing requires the NVIDIA device; services depending on /dev/nvidia* must be conditional [INFERRED].
  2. eGPU arrives after login: a new DRM card node appears; with nvidia_drm modeset on, mutter may hot-add the device (extra probe, possible primary re-evaluation, stutter). With card numbers shifting, any udev rule or script keyed to card0/card1 breaks. Key on PCI address/UUID [INFERRED].
  3. Display manager restarts: loading nvidia_drm modeset=1 while GDM is up, or a udev rule reload/tag change, can require a session re-login (the mutter-primary-gpu extension notes a re-login is required after switching [SOURCED https://github.com/zaidka/mutter-primary-gpu]). Never systemctl restart gdm to “fix” GPU state on a box where the session matters.
  4. eGPU as primary and it drops: the compositor loses its primary GPU; session ends [INFERRED]. Another reason to keep the desktop on the iGPU.
  5. vgaarb changes: a new VGA-class device may register with the arbiter; boot_vga stays with the firmware device [INFERRED]; check cat /sys/bus/pci/devices/*/boot_vga.
  6. Safe change order [INFERRED]: make one change per boot (kernel driver binding, udev primary tag, nvidia_drm options), verify with the read-only checks after each, and keep a second login path (SSH or a spare TTY) open so a blank display does not leave the box unreachable. modprobe.d and udev edits take effect at the next boot or re-login, not mid-session.
  7. Persistence state / order of modules and unplug are covered in sibling references.

Anti-patterns

Sources

  1. Mutter multi-GPU doc - https://github.com/GNOME/mutter/blob/main/doc/multi-gpu.md (fetched via raw.githubusercontent.com)
  2. NVIDIA README, KMS chapter (driver 580.65.06 path) - https://download.nvidia.com/XFree86/Linux-x86_64/580.65.06/README/kms.html
  3. NVIDIA README, PRIME render offload - https://download.nvidia.com/XFree86/Linux-x86_64/580.65.06/README/primerenderoffload.html
  4. CUDA environment variables - https://docs.nvidia.com/cuda/cuda-programming-guide/05-appendices/environment-variables.html
  5. Arch Wiki External GPU / PRIME / NVIDIA (via search results; direct fetch blocked) - https://wiki.archlinux.org/title/External_GPU , https://wiki.archlinux.org/title/PRIME , https://wiki.archlinux.org/title/NVIDIA
  6. Kernel docs vga_switcheroo - https://docs.kernel.org/gpu/vga-switcheroo.html ; Xe merge plan - https://docs.kernel.org/next/gpu/rfc/xe.html
  7. Kconfig DRM_XE_FORCE_PROBE - https://cateee.net/lkddb/web-lkddb/DRM_XE_FORCE_PROBE.html
  8. Phoronix MTL i915 vs xe - https://www.phoronix.com/review/intel-mtl-i915-xe-linux (direct fetch 403; summary from search)
  9. NVIDIA developer forum threads on modeset/fbdev - https://forums.developer.nvidia.com/t/understanding-nvidia-drm-modeset-1-nvidia-linux-driver-modesetting/204068 , https://forums.developer.nvidia.com/t/increased-idle-consumption-with-driver-570/321460
  10. gnome-shell VRAM reports - https://bugs.launchpad.net/bugs/1823544 , https://forums.developer.nvidia.com/t/multiple-wayland-compositors-not-freeing-vram-after-resizing-windows/307939
  11. mutter-primary-gpu extension - https://github.com/zaidka/mutter-primary-gpu