Issues / #3418
#3418 Picking a single GPU in the app (Ryzen iGPU + discrete Radeon) is broken twice over
open · @squidwardboom · 1 Kommentare · Auf GitHub
Beschreibung
## Environment
| | |
|---|---|
| Strata | 0.1.45.3, **Windows app install** (`Strata-0.2.0-beta-windows-hip-rdna3.exe`) |
| Engine | `strata-engine` 0.1.45.3, `windows-x86_64-hip-rdna3` |
| CPU / iGPU | Ryzen 7 7800X3D → `AMD Radeon(TM) Graphics`, **gfx1036** |
| GPU | **AMD Radeon RX 7900 XTX**, gfx1100, 24 GB |
| Install | default `LOCALAPPDATA` layout; model Qwen3.8-Flash-Next IQ3_S |
The two cards matter: HIP numbers the **iGPU 0** and the **7900 XTX 1**, while the display-adapter order used elsewhere numbers them the other way round.
```
> strata-device.exe --list-devices
device 0: AMD Radeon(TM) Graphics
arch gfx1036, 43.7 GiB, wave32
cannot run: GPU 0 (AMD Radeon(TM) Graphics, gfx1036) is not an architecture this Strata engine was compiled for
(gfx1100,gfx1101,gfx1102,gfx1151); ... or choose another GPU with HIP_VISIBLE_DEVICES
device 1: AMD Radeon RX 7900 XTX
arch gfx1100, 24.0 GiB, wave32
```
```
> Get-CimInstance Win32_VideoController | select Name
AMD Radeon RX 7900 XTX <- display-adapter order: 0
AMD Radeon(TM) Graphics <- display-adapter order: 1
```
---
## Bug 1 — a single-card pick is sent as `gpus` and rejected by the schema
### Steps
1. Settings → pick the GPU → select **Radeon RX 7900 XTX** (the only card the list offers; the iGPU is correctly filtered out).
2. Load the model.
### Actual
```
Gpus='0' is not valid (several GPUs sharing the model: '0,2' or 'all' (experimental))
```
### Expected
The card is accepted and the model loads.
### Cause
`strata_install` carries two mutually exclusive GPU parameters:
```python
# control/tools/strata_mcp.py:1470
GPUS_PATTERN = r"all|\d{1,2}(,\d{1,2}){1,7}"
# control/tools/strata_mcp.py:1532-1535
"gpu": {"type": "integer", "minimum": 0, "maximum": 63,
"description": "one GPU, as nvidia-smi numbers them (default: the one with the most VRAM)"},
"gpus": {"type": "string", "pattern": GPUS_PATTERN, "maxLength": 40,
"description": "several GPUs sharing the model: '0,2' or 'all' (experimental)"},
```
```python
# control/tools/strata_mcp.py:1807-1808
if gpu is not None and gpus is not None:
raise ToolError("give gpu (one card) or gpus (several), not both")
```
The one-card case is meant to go through `gpu` (integer). The app's Settings puts the selection into `gpus` instead, as a string — so a single card arrives as `"0"`, which `GPUS_PATTERN` cannot match (it needs ≥ 2 comma-separated cards, or `all`). The schema rejects it before it ever reaches `install_plan()`.
### Suggested fix
When exactly one card is selected, emit `gpu: <n>` (integer). Reserve `gpus` for 2+ cards. Optionally make the pattern accept a single number and treat it as the one-card case, so a client that never distinguishes the two still works.
---
## Bug 2 — with the app install, that number is the display-adapter index, not the HIP ordinal, so the engine starts on the iGPU and dies
Fixing bug 1 alone (sending `gpu=0`) does **not** help on this machine: the UI's `0` means "the first usable card in display-adapter order", but the engine receives it as `HIP_VISIBLE_DEVICES=0`, which is the iGPU.
### Actual
```
server_exited (exit code 1): EngineDied: the engine exited before it was ready (see strata-iq3_s.log)
```
```
strata: GPU 0 (AMD Radeon(TM) Graphics, gfx1036) is not an architecture this Strata engine was
compiled for (gfx1100,gfx1101,gfx1102,gfx1151); compile it for this card
(./setup.sh --backend hip, or -DCMAKE_HIP_ARCHITECTURES=gfx1036, docs/AMD_HIP.md)
or choose another GPU with HIP_VISIBLE_DEVICES
```
### Cause
`serve/server.py` already has the correction for this (#325), and says what should feed it:
```python
# control/serve/server.py:2964-2977
def hip_visible(cfg: dict) -> list[int]:
"""AMD: the devices the engine should see, as the HIP runtime numbers them (HIP_VISIBLE_DEVICES).
On Linux setup's KFD order is HIP's order, so the config's "gpu" is it. On Windows setup finds the cards in the
display-adapter order, and an integrated Radeon that HIP also enumerates takes ordinal 0 and pushes the discrete
card to 1 (#325): setup records the ordinal `strata-device --list-devices` gave the card as "hip_ordinal", which
wins for a one-card config. Without it (a config from before), the config's "gpu"."""
ordinal = cfg.get("hip_ordinal")
if ordinal is not None and str(ordinal).strip() != "" and len(gpu_list(cfg)) <= 1:
...
return ordered_gpus(cfg)
```
Two things stop that from working on the app install:
**(a) The card list is built in display-adapter order, because the HIP probe is never found.**
```python
# control/setup.py:3503-3513
def hip_devices(probe=None, text=None) -> list[dict] | None:
if text is None:
probe = probe or ROOT / "engine" / ("strata-device.exe" if WIN else "strata-device")
...
if not probe.exists() or not hip_engine:
return None
```
`ROOT` is `Path(__file__).resolve().parent` = `<install>\control`, and the app install keeps the engine in the **component** layout, not at `<install>\control\engine`:
```
<LOCALAPPDATA>\Programs\Strata\control\ <- ROOT
<LOCALAPPDATA>\Programs\Strata\engine-bundle\0.1.45.3-windows-x86_64-hip-rdna3\strata-device.exe
<LOCALAPPDATA>\Strata\components\engine\0.1.45.3-windows-x86_64-hip-rdna3\strata-device.exe <- the one that runs
```
So `hip_devices()` returns `None`, and `amd_gpus_win()` falls back to `amd_gpus_windows()`:
```python
# control/setup.py:3319-3333
def amd_gpus_win() -> list[dict]:
"""Windows: the AMD GPUs as the HIP runtime numbers them once the HIP engine is installed (hip_devices), else in
the display-adapter order (amd_gpus_windows)."""
hip = hip_devices()
if not hip:
return amd_gpus_windows()
```
Observed on this machine:
```
amd_gpus_win():
index=0 AMD Radeon RX 7900 XTX arch=gfx1100 usable=True
index=1 AMD Radeon(TM) Graphics arch=unknown usable=False
```
The 7900 XTX is therefore offered as **GPU 0**, and that 0 is what lands in the config as `"gpu": 0` — which the engine reads as HIP ordinal 0, the iGPU.
Note the Terminal / `git clone` install does not hit this: there `ROOT\engine\strata-device.exe` exists, `hip_devices()` succeeds, and the same card is correctly numbered 1. The two install layouts number the same card differently, and only the app layout gets it wrong.
**(b) Nothing ever writes `hip_ordinal`.** The docstring above says setup records it, but a tree-wide grep for `hip_ordinal` finds only readers and tests — no producer:
```
control/serve/replicas.py:98 c.pop("hip_ordinal", None)
control/serve/server.py:2969,2971 docstring + cfg.get("hip_ordinal")
control/serve/test_server.py:1786-1794
control/serve/test_replicas.py:37,46
```
So no Windows AMD install reaches `hip_visible()` with an ordinal, and the fallback `ordered_gpus(cfg)` always feeds the display-adapter index to `HIP_VISIBLE_DEVICES`.
### Suggested fix
1. Make `hip_devices()` resolve the probe through `strata_control.engine_component` (`engine_dir()` / the current engine component folder) instead of the hardcoded `ROOT / "engine"`, so the app's component layout numbers cards the way HIP does. Then `gpu: 1` for this machine is correct without any ordinal at all.
2. Independently, have setup/Control actually record `hip_ordinal` (from `strata-device --list-devices`) when it writes a one-card Windows AMD config, as `hip_visible()` already expects.
3. As cheap insurance, `hip_visible()` could skip devices whose arch the engine cannot run (`--list-devices` already prints `cannot run:` for them) instead of trusting the ordinal blindly.
---
## Workaround that works today
Add the ordinal by hand to the run config (`<LOCALAPPDATA>\Strata\install\strata-<model>.json`):
```json
"backend": "hip",
"gpu": 0,
"hip_ordinal": 1,
```
With that the model loads and answers normally:
```
strata generate: session is up (engine 0.1.45.3)
strata generate: expert cache 5749 slots, 10.92 GiB of VRAM
```
## Related
#325 (iGPU takes HIP ordinal 0), #524, #942Mehr auf der Site
Links zu Install, Modellen, Releases.