Skip to content

Fix managed llama.cpp offloading to the integrated GPU instead of the discrete NVIDIA card#36

Open
sachin-detrax wants to merge 2 commits into
AtomicBot-ai:mainfrom
sachin-detrax:fix/discrete-gpu-selection
Open

Fix managed llama.cpp offloading to the integrated GPU instead of the discrete NVIDIA card#36
sachin-detrax wants to merge 2 commits into
AtomicBot-ai:mainfrom
sachin-detrax:fix/discrete-gpu-selection

Conversation

@sachin-detrax

Copy link
Copy Markdown

Closes #35.

auto device selection handed the model to an AMD APU integrated GPU on a machine with an RTX 5070 Ti. Three independent defects stacked to produce it; each is fixed separately below.

1. pickBestDevice only recognised Intel iGPUs

INTEGRATED_DEVICE_RE was /intel|integrated|\buhd\b|\biris\b/i. AMD APU iGPUs (AMD Radeon(TM) Graphics, AMD Radeon 780M Graphics, Radeon(TM) Vega 8 Graphics) matched none of it, scored as discrete, and won the totalMemMiB tiebreak — Vulkan reports their shared-RAM heap as larger than real VRAM (16180 MiB vs the RTX's 15995 MiB). The same pattern demoted a discrete Intel Arc via the bare intel.

Replaced the negative-only test with deviceClassRank:

  • 2 — positive discrete hint (nvidia|geforce|rtx|gtx|quadro|tesla|arc|radeon (rx|pro)), checked first so Arc and Radeon RX can never be demoted
  • 0 — integrated hint, now covering AMD APU naming
  • 1 — unrecognised, assumed discrete (safer default than assuming iGPU)

VRAM remains the tiebreak within a rank.

2. Installed Windows backend variant was never re-checked

All four Windows zips ship an identically-named llama-server.exe; isBackendDownloaded() tests only that filename, and the nvidia-smi probe ran solely inside downloadBackend(). A machine that installed the Vulkan build once — nvidia-smi unavailable at that moment, or an install predating CUDA variant support — kept it forever, with checkForBackendUpdate reporting no update on a matching tag.

That is what places an NVIDIA card on the Vulkan backend, which is the only reason the iGPU is enumerated at all: the CUDA backend lists NVIDIA devices exclusively, so defect 1 cannot fire there.

backend-version.json now records the installed asset, and checkForBackendUpdate treats a variant mismatch as an update even at the same release tag.

3. CUDA build gated on driver >= 13.3

CUDA minor-version compatibility makes a 13.3-built binary valid on any 13.x driver, so gating on the exact minor was unnecessary — and harmful: a driver reporting CUDA Version: 13.0 was routed to the 12.4 build, which carries no sm_120 code because Blackwell postdates that toolkit entirely. RTX 50-series then had to JIT from PTX or fall off the GPU. Now gated on the 13.x major.

Tests

deviceClassRank regressions cover all four iGPU strings from the report plus the Arc false positive; the CUDA threshold test asserts 13.0 resolves to the 13.3 build.

npx vitest run src/local-llm/   # 112 passed (15 files)
npx tsc -p tsconfig.json --noEmit   # clean

Not addressed

  • Linux ships no CUDA asset (platform-assets.ts always resolves the Vulkan zip), so Linux + NVIDIA stays on Vulkan. Fix 1 is what carries those machines; adding a Linux CUDA asset is a separate change requiring a new release artifact.
  • Existing installs have no asset field in backend-version.json and are treated as current, so the CUDA upgrade is pulled on the next models update rather than pushed.

🤖 Generated with Claude Code

sachin-detrax and others added 2 commits July 26, 2026 14:39
On a Windows box with an RTX 5070 Ti and an AMD APU iGPU, `auto`
resolved to the iGPU. Three independent defects stacked:

1. `INTEGRATED_DEVICE_RE` only matched Intel iGPUs, so AMD APUs
   ("AMD Radeon(TM) Graphics", "Radeon 780M Graphics", "Vega 8
   Graphics") scored as discrete and won the `totalMemMiB` tiebreak —
   Vulkan reports their shared-RAM heap as larger than real VRAM
   (16180 MiB vs 15995 MiB). The same regex demoted discrete Intel Arc.

   Replaced with `deviceClassRank`: a positive discrete hint is checked
   first (Arc / Radeon RX never demoted), the integrated list covers AMD
   APU naming, and unrecognised names default to "assume discrete".

2. The installed Windows backend variant was never re-checked. All four
   zips ship the same `llama-server.exe`, `isBackendDownloaded` only
   tests that filename, and the nvidia-smi probe ran solely at download
   time — so a machine that once installed the Vulkan build kept it
   forever. That is what put an NVIDIA card on Vulkan, which is the only
   reason the iGPU was enumerated (the CUDA backend lists NVIDIA only).

   `backend-version.json` now records the installed asset and
   `checkForBackendUpdate` reports an update on variant mismatch even at
   the same release tag.

3. The CUDA build was gated on driver >= 13.3. CUDA minor-version
   compatibility makes a 13.3-built binary valid on any 13.x driver, and
   the gate sent 13.0 drivers to the 12.4 build — which has no sm_120
   code because Blackwell postdates that toolkit. Gated on 13.x major.

Linux still ships Vulkan only (`platform-assets.ts`), so fix 1 is what
carries Linux + NVIDIA machines.

Closes AtomicBot-ai#35

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every Windows release zip ships an identically-named
`llama-server.exe`, so nothing in the CLI output revealed whether a
machine was running the Vulkan or a CUDA build. That is precisely the
state that leaves an NVIDIA box enumerating — and offloading to — its
integrated GPU, and it was invisible while debugging one.

`status` now prints a `compute:` line from the asset recorded in
`backend-version.json`, flagging a mismatch against what the machine
warrants today. Installs predating variant tracking report as unknown
with the remedy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Managed llama.cpp offloads to integrated GPU instead of discrete NVIDIA card

1 participant