mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-10-17 05:14:19 +02:00
Upgraded AMD iGPU installs sometimes carry a working HSA_OVERRIDE_GFX_VERSION on nomad_ollama, set by hand or by an older install path, but have no ai.amdHsaOverride KV and no .nomad-amd-gfx marker. The CPU-fallback banner offered Fix: Reinstall, and the reinstall rebuilt the container without the override, so a 780M (gfx1103) stayed on CPU. - Add pickAmdHsaOverride to utils/amd_hsa_override.ts with the resolution order KV, marker, existing container override, none. A marker still wins even when it maps to none. KV "none" still disables the override. - forceReinstall inspects nomad_ollama before removing it and saves a container-only override to ai.amdHsaOverride. Saving it keeps the value through a reinstall that fails after the removal and shows it in the Set GFX Override modal. - The update path passes the old container env to the resolver, so a routine Update keeps the override too. - The GPU health check passes the container env, so diffAmdOllamaConfig compares against what a reinstall would build. On the reported box, the only drift is OLLAMA_IGPU_ENABLE=1. - diagnoseAmdCpuFallback suggests the container's current override when one is set. With an override applied, Ollama logs the coerced target (gfx1100), which maps to none and would suggest removing a working value. - Remove the unused _mapGfxToHsaOverride wrapper. parseAmdGfxTargetFromLogs is unchanged. It still matches only gpu_type=. The "dropping integrated GPU ... compute=gfx..." line needs a full sample from an affected box before we can write a regex for it. We'll address in a later PR.
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import * as assert from 'node:assert/strict'
|
|
import { test } from 'node:test'
|
|
|
|
import {
|
|
mapGfxToHsaOverride,
|
|
pickAmdHsaOverride,
|
|
readHsaOverrideFromEnv,
|
|
} from '../../app/utils/amd_hsa_override.js'
|
|
|
|
test('gfx1103 (Phoenix 780M) coerces to 11.0.0 — the #1076 regression', () => {
|
|
// Not on the bundled rocblas allowlist; without this ollama drops it to CPU.
|
|
assert.equal(mapGfxToHsaOverride('gfx1103'), '11.0.0')
|
|
})
|
|
|
|
test('gfx1150 / gfx1151 (Strix 890M, Strix Halo) stay native — no override', () => {
|
|
// These ARE on the allowlist; forcing an override would needlessly coerce them.
|
|
assert.equal(mapGfxToHsaOverride('gfx1150'), null)
|
|
assert.equal(mapGfxToHsaOverride('gfx1151'), null)
|
|
})
|
|
|
|
test('RDNA 2 iGPUs (gfx1031..gfx1036, e.g. 680M) coerce to 10.3.0', () => {
|
|
assert.equal(mapGfxToHsaOverride('gfx1035'), '10.3.0')
|
|
assert.equal(mapGfxToHsaOverride('gfx1031'), '10.3.0')
|
|
assert.equal(mapGfxToHsaOverride('gfx1036'), '10.3.0')
|
|
})
|
|
|
|
test('discrete cards on the ROCm allowlist get no override', () => {
|
|
for (const gfx of ['gfx1030', 'gfx1100', 'gfx1101', 'gfx1102']) {
|
|
assert.equal(mapGfxToHsaOverride(gfx), null)
|
|
}
|
|
})
|
|
|
|
test('unknown / newer targets default to native discovery (no override)', () => {
|
|
assert.equal(mapGfxToHsaOverride('gfx9999'), null)
|
|
assert.equal(mapGfxToHsaOverride(''), null)
|
|
})
|
|
|
|
const OVERRIDE_ENV = ['OLLAMA_NO_CLOUD=1', 'HSA_OVERRIDE_GFX_VERSION=11.0.0']
|
|
|
|
test('readHsaOverrideFromEnv reads the override or null', () => {
|
|
assert.equal(readHsaOverrideFromEnv(OVERRIDE_ENV), '11.0.0')
|
|
assert.equal(readHsaOverrideFromEnv(['OLLAMA_NO_CLOUD=1']), null)
|
|
assert.equal(readHsaOverrideFromEnv(null), null)
|
|
})
|
|
|
|
test('pickAmdHsaOverride: a KV version wins over the marker and container', () => {
|
|
assert.deepEqual(pickAmdHsaOverride({ manual: '10.3.0', markerGfx: 'gfx1103', containerEnv: OVERRIDE_ENV }), {
|
|
value: '10.3.0',
|
|
source: 'kv',
|
|
})
|
|
})
|
|
|
|
test('pickAmdHsaOverride: KV none disables even a container override', () => {
|
|
assert.deepEqual(pickAmdHsaOverride({ manual: 'none', markerGfx: null, containerEnv: OVERRIDE_ENV }), {
|
|
value: null,
|
|
source: 'kv-disabled',
|
|
})
|
|
})
|
|
|
|
test('pickAmdHsaOverride: a marker is authoritative even when it maps to none', () => {
|
|
assert.deepEqual(pickAmdHsaOverride({ manual: null, markerGfx: 'gfx1151', containerEnv: OVERRIDE_ENV }), {
|
|
value: null,
|
|
source: 'marker',
|
|
})
|
|
})
|
|
|
|
test('pickAmdHsaOverride keeps the container override with no KV or marker (#1377)', () => {
|
|
assert.deepEqual(pickAmdHsaOverride({ manual: null, markerGfx: null, containerEnv: OVERRIDE_ENV }), {
|
|
value: '11.0.0',
|
|
source: 'container',
|
|
})
|
|
assert.deepEqual(pickAmdHsaOverride({ manual: '', markerGfx: null, containerEnv: OVERRIDE_ENV }), {
|
|
value: '11.0.0',
|
|
source: 'container',
|
|
})
|
|
})
|
|
|
|
test('pickAmdHsaOverride ignores a malformed container override', () => {
|
|
assert.deepEqual(
|
|
pickAmdHsaOverride({ manual: null, markerGfx: null, containerEnv: ['HSA_OVERRIDE_GFX_VERSION=gfx1103'] }),
|
|
{ value: null, source: 'default' }
|
|
)
|
|
})
|
|
|
|
test('pickAmdHsaOverride skips an invalid KV value and reports it', () => {
|
|
assert.deepEqual(pickAmdHsaOverride({ manual: 'bogus', markerGfx: null, containerEnv: OVERRIDE_ENV }), {
|
|
value: '11.0.0',
|
|
source: 'container',
|
|
invalidManual: 'bogus',
|
|
})
|
|
})
|