AMD: gfx1101 (RX 7800 XT, #254 by jhohertz) and gfx1200 (RX 9060 XT, #256 by Efeisot) as community-validated cards

Cut down from #254 and #256 onto 0.1.30's AMD tables:
- setup.py: AMD_ARCHS / AMD_NAMES / ROCM_INDEXES / AMD_CARDS list gfx1101 (TheRock gfx110X-dgpu) and gfx1200
  (gfx120X-all); amd_gpus() takes the sysfs root so the detection can be tested.
- cmake/hip_backend.cmake: gfx1101 and gfx1200 build without the "not validated" warning (a status line names
  them community-validated); gfx1102 (#192: ctest only) keeps the warning.
- docs/AMD_HIP.md (Community-validated cards: the owners' setups, ctest and numbers) and README.
- tools/test_setup_amd.py: detection on a mocked KFD topology (every family, the CPU node, an iGPU and gfx1102
  listed as not supported, product-name fallbacks, the ROCm index per family).
Left out: the PRs' own cmake/device.cu arch checks (0.1.30's compiled_for covers them), the dp4a change (main has
it), math_constants.h, the bench JSONs, the launcher, and both hipBLASLt tables (neither PR measured the prompt speed
without its table).

Co-Authored-By: Joseph Hohertz <[email protected]>
Co-Authored-By: efeisot <[email protected]>
This commit is contained in:
committed 2026-10-01 00:35:39 +02:00
1 parent 600d73070c
commit 489623c7d3
5 files changed
+145 -30

No files matched your search

+2 -1
View File
@@ -84,7 +84,8 @@ one later with `SETUP.bat` (the same as `START-HERE.bat --setup`; on Linux `./se
For **OrcaRouter's Flash-Next Uncensored IQ3_XXS**, see the [manual compatibility setup](docs/ORCA.md).
It needs an explicit packing conversion and is not an installer menu option.
An **AMD Radeon RX 7900 XT / XTX, RX 9070 / 9070 XT or Radeon AI PRO R9700 on Linux** works too (experimental):
An **AMD Radeon RX 7900 XT / XTX, RX 9070 / 9070 XT or Radeon AI PRO R9700 on Linux** works too (experimental; the
RX 7800 XT / 7700 XT and RX 9060 XT were validated by their owners):
`./setup.sh --backend hip`, chosen by itself on a PC with no NVIDIA card Strata can use. It installs ROCm without sudo
and compiles the engine (one GPU, no images yet). Details: [AMD HIP](docs/AMD_HIP.md).
+8 -5
View File
@@ -4,20 +4,23 @@
if(NOT DEFINED CMAKE_HIP_ARCHITECTURES OR CMAKE_HIP_ARCHITECTURES STREQUAL "")
set(CMAKE_HIP_ARCHITECTURES gfx1100 CACHE STRING "Strata HIP target architecture(s), e.g. gfx1100 or gfx1100;gfx1201")
endif()
# Validated on real cards: gfx1100 (RX 7900 XT / XTX) and gfx1201 (RX 9070 / 9070 XT, Radeon AI PRO R9700).
# The other RDNA3 / RDNA4 wave32 chips have the same LDS limit and dot4 instruction and build the same code, but
# the maintainers have not run them (community reports: gfx1102 #192, gfx1200 #176).
# Validated on real cards: gfx1100 (RX 7900 XT / XTX) and gfx1201 (RX 9070 / 9070 XT, Radeon AI PRO R9700) by the
# maintainers; gfx1101 (RX 7800 XT, #254) and gfx1200 (RX 9060 XT, #256) by their owners. gfx1102 (RX 7600) has the
# same LDS limit and dot4 instruction and passed ctest (#192), but no model run has been reported yet.
set(_strata_hip_validated gfx1100 gfx1201)
set(_strata_hip_unvalidated gfx1101 gfx1102 gfx1200)
set(_strata_hip_community gfx1101 gfx1200)
set(_strata_hip_unvalidated gfx1102)
set(STRATA_HIP_ARCH_LIST "")
foreach(_arch IN LISTS CMAKE_HIP_ARCHITECTURES)
string(REGEX REPLACE ":.*$" "" _base "${_arch}") # gfx1100:xnack- -> gfx1100
if(_base IN_LIST _strata_hip_validated)
elseif(_base IN_LIST _strata_hip_community)
message(STATUS "Strata HIP: ${_base} was validated by community reports (docs/AMD_HIP.md)")
elseif(_base IN_LIST _strata_hip_unvalidated)
message(WARNING "Strata HIP: ${_base} builds, but it is not validated on a real card yet; please report results")
else()
message(FATAL_ERROR
"Strata HIP supports wave32 gfx1100 and gfx1201 (unvalidated: ${_strata_hip_unvalidated}); "
"Strata HIP supports wave32 gfx1100, gfx1101, gfx1200 and gfx1201 (unvalidated: ${_strata_hip_unvalidated}); "
"CMAKE_HIP_ARCHITECTURES is '${CMAKE_HIP_ARCHITECTURES}'")
endif()
list(APPEND STRATA_HIP_ARCH_LIST "${_base}")
+35 -12
View File
@@ -1,8 +1,9 @@
# Experimental AMD HIP backend (gfx1100, gfx1201)
# Experimental AMD HIP backend (gfx1100, gfx1101, gfx1200, gfx1201)
This is a Linux source build for the RX 7900 XT / XTX (RDNA3, gfx1100) and the
RX 9070 / 9070 XT / Radeon AI PRO R9700 (RDNA4, gfx1201; see [RDNA4](#rdna4-gfx1201)).
It is opt-in; the NVIDIA installer and CUDA build remain the default. Other AMD
RX 9070 / 9070 XT / Radeon AI PRO R9700 (RDNA4, gfx1201; see [RDNA4](#rdna4-gfx1201)). The RX 7800 XT / 7700 XT
(gfx1101) and the RX 9060 XT (gfx1200) were validated by their owners (see [Community-validated
cards](#community-validated-cards)). It is opt-in; the NVIDIA installer and CUDA build remain the default. Other AMD
architectures, wave64, Windows HIP, and mixed AMD/NVIDIA execution are outside this contribution.
The backend maps the CUDA-shaped runtime and BLAS calls to HIP/hipBLAS, uses
@@ -15,8 +16,8 @@ This does not claim bit-identical model answers across backends. See
## Install with setup (recommended)
On Linux with an RX 7900 XT / XTX or an RX 9070 / 9070 XT / Radeon AI PRO R9700 and the kernel's amdgpu driver
(no ROCm install needed):
On Linux with an RX 7900 XT / XTX, RX 7800 XT / 7700 XT, RX 9060 XT, RX 9070 / 9070 XT or Radeon AI PRO R9700 and
the kernel's amdgpu driver (no ROCm install needed):
```sh
./setup.sh --backend hip
@@ -26,8 +27,8 @@ On Linux with an RX 7900 XT / XTX or an RX 9070 / 9070 XT / Radeon AI PRO R9700
supported. On a PC without an NVIDIA card Strata can use, `--backend hip` is chosen automatically.
- **ROCm:** a system ROCm 7 in `/opt/rocm` (or `$ROCM_PATH`) with hipcc and hipBLAS is used when present. Otherwise
(or when it is older than 7.0) ROCm is installed into `.venv` from AMD's TheRock wheels (~10 GB, no sudo), pinned
to the version this backend was tested with, from the card family's index: `gfx110X-dgpu` for gfx1100,
`gfx120X-all` for gfx1201 (`STRATA_ROCM_VERSION` / `STRATA_ROCM_INDEX` override them).
to the version this backend was tested with, from the card family's index: `gfx110X-dgpu` for gfx1100 / gfx1101,
`gfx120X-all` for gfx1200 / gfx1201 (`STRATA_ROCM_VERSION` / `STRATA_ROCM_INDEX` override them).
- **Engine:** compiled on your PC for the card's architecture (10-20 minutes, once; again after a `git pull` that
changes it, or when you pick a card of another architecture). This needs a C++ compiler and git
(`sudo apt install build-essential git`).
@@ -54,9 +55,9 @@ cmake -S . -B build-hip \
cmake --build build-hip --target strata -j2
```
`CMAKE_HIP_ARCHITECTURES` is `gfx1100`, `gfx1201`, or a list such as `"gfx1100;gfx1201"` (one binary for both).
gfx1101, gfx1102 and gfx1200 (the same wave32, 64 KiB LDS and dot4 instruction) build with a warning: they have
not been validated on a real card here. At startup the engine and `strata-device` compare each GPU they use
`CMAKE_HIP_ARCHITECTURES` is `gfx1100`, `gfx1101`, `gfx1200`, `gfx1201`, or a list such as `"gfx1100;gfx1201"`
(one binary for both). gfx1102 (the same wave32, 64 KiB LDS and dot4 instruction) builds with a warning: it passed
ctest (#192) but no model run has been reported. At startup the engine and `strata-device` compare each GPU they use
(`gcnArchName` up to the `:` feature suffix) with the architectures the binary was compiled for, and require
wave32. A binary carried to another card stops with the card's name, its architecture and the build's list,
instead of failing later with "invalid device function".
@@ -168,8 +169,30 @@ an RX 9070 XT 16 GB and a Radeon AI PRO R9700 32 GB (both gfx1201), a Ryzen 9 39
expert arena (a Windows limit that also applies here).
- **Known:** rarely (about 1 start in 10) a HIP run's greedy output differs from another start's at some token, on
one card or two and on engine 0.1.29 as well; not yet explained.
- **Not validated:** gfx1200 (RX 9060 XT; a community report is #176), images, long contexts beyond 16K,
answer-quality benchmarks.
- **Not validated:** images, long contexts beyond 16K, answer-quality benchmarks.
## Community-validated cards
Run by their owners, not on the maintainers' machines; setup accepts them like gfx1100 / gfx1201. No hipBLASLt table
is shipped for them (make one with [Tuning table](#tuning-table) and compare the prompt speed with and without it).
- **gfx1101, RX 7800 XT 16 GB** (jhohertz, #254; engine 0.1.29, Ryzen 9 5950X, 121 GiB RAM, system ROCm with
hipBLASLt 1.4.1): `./setup.sh --backend hip` detected the card and compiled the engine; `strata-device --selftest`
passed; ctest 30/32 (`ple_parity` needs the Q2_0 fixture, `platform_memory_test` the memlock limit). Coder IQ1_M,
64K context, MTP, with a table the owner calibrated: fresh prompts of 4K-9K tokens at 898-953 tok/s, decode
38-44 tok/s (128 tokens).
- **gfx1200, RX 9060 XT 16 GB** (Efeisot, #256 after #176; engine 0.1.29, Ryzen 9 7950X, 64 GiB RAM, ROCm 7.2 with
hipBLASLt 1.2.2): ctest 32/32 (without `ple_parity` and `platform_memory_test`). Coder IQ1_M, greedy, MTP
`--spec 4 --spec-min-p 0.5`, with a table the owner calibrated:
| prompt | prompt speed | decode |
|---|---|---|
| 2,374 tokens | 540 tok/s | 27.1 tok/s (0.69 draft acceptance; 31.0 at 1.00) |
| 65K (`--kv int8 --kv-resident 65536 --prefill 16384`) | 748-753 tok/s | 26-40 tok/s by acceptance |
| 130K (the same flags) | 725 tok/s | - |
Greedy output was the same across runs. For comparison, llama.cpp's HIP build measured 20 tok/s decode and
450 tok/s prompt on that card.
## Tuning table
+19 -12
View File
@@ -710,27 +710,34 @@ def cuda_lib_dirs():
# ------------------------------------------------------------------------------------------------ AMD (experimental)
# The RX 7900 XT / XTX (gfx1100) and the RX 9070 series / Radeon AI PRO R9700 (gfx1201) on Linux, through the HIP
# backend (docs/AMD_HIP.md). There is no ready-made AMD engine: ROCm comes from AMD's TheRock Python wheels into .venv
# (no sudo; a system ROCm 7 in /opt/rocm is used when it has hipcc and hipBLAS) and the engine is compiled here for
# the card. One GPU, no images yet.
# backend (docs/AMD_HIP.md); the RX 7800 XT / 7700 XT (gfx1101, #254) and the RX 9060 XT (gfx1200, #256) were run by
# their owners. There is no ready-made AMD engine: ROCm comes from AMD's TheRock Python wheels into .venv (no sudo;
# a system ROCm 7 in /opt/rocm is used when it has hipcc and hipBLAS) and the engine is compiled here for the cards.
# No images yet.
ROCM_INDEXES = {"gfx1100": "https://rocm.nightlies.amd.com/v2/gfx110X-dgpu/", # TheRock's wheels per GPU family
"gfx1101": "https://rocm.nightlies.amd.com/v2/gfx110X-dgpu/",
"gfx1200": "https://rocm.nightlies.amd.com/v2/gfx120X-all/",
"gfx1201": "https://rocm.nightlies.amd.com/v2/gfx120X-all/"}
ROCM_VERSION = os.environ.get("STRATA_ROCM_VERSION", "7.10.0a20251120") # what Strata's HIP build was tested with
ROCM_SYSTEM_MIN = (7, 0) # an older system ROCm is passed over for the wheels (gfx1201 needs ROCm 6.4 or newer)
AMD_ARCHS = ("gfx1100", "gfx1201")
AMD_ARCHS = ("gfx1100", "gfx1101", "gfx1200", "gfx1201")
AMD_NAMES = {"gfx1100": "AMD Radeon RX 7900 series (gfx1100)", # when sysfs has no product name
"gfx1101": "AMD Radeon RX 7800 XT / 7700 XT (gfx1101)",
"gfx1200": "AMD Radeon RX 9060 series (gfx1200)",
"gfx1201": "AMD Radeon RX 9070 series / AI PRO R9700 (gfx1201)"}
AMD_CARDS = "the RX 7900 XT / XTX (gfx1100) and the RX 9070 / 9070 XT / Radeon AI PRO R9700 (gfx1201)"
AMD_CARDS = ("the RX 7900 XT / XTX (gfx1100), RX 7800 XT / 7700 XT (gfx1101), RX 9060 XT (gfx1200) and "
"RX 9070 / 9070 XT / Radeon AI PRO R9700 (gfx1201)")
def rocm_index(arch):
return os.environ.get("STRATA_ROCM_INDEX") or ROCM_INDEXES[arch]
def amd_gpus():
def amd_gpus(sysfs="/sys"):
"""AMD GPUs from the kernel's KFD topology (the amdgpu driver; no ROCm needed), numbered as HIP numbers them:
the GPU nodes in order, the CPU nodes skipped. Integrated GPUs are listed too (not supported)."""
base = Path("/sys/class/kfd/kfd/topology/nodes")
the GPU nodes in order, the CPU nodes skipped. Integrated GPUs are listed too (not supported).
sysfs: the tree to read (tools/test_setup_amd.py passes a mocked one)."""
base = Path(sysfs) / "class/kfd/kfd/topology/nodes"
found = []
if WIN or not base.is_dir():
return found
@@ -746,7 +753,7 @@ def amd_gpus():
except (OSError, ValueError):
continue
arch = f"gfx{ver // 10000}{(ver // 100) % 100:x}{ver % 100:x}"
dev = Path(f"/sys/class/drm/renderD{props.get('drm_render_minor', '')}/device")
dev = Path(sysfs) / f"class/drm/renderD{props.get('drm_render_minor', '')}/device"
try:
vram = int((dev / "mem_info_vram_total").read_text()) / 2 ** 30
except (OSError, ValueError):
@@ -1767,8 +1774,8 @@ def main() -> int:
"this mode the experts the GPU does not hold are copied into RAM once when they fit (resident), "
"else read through the OS file cache (mmap); resident / mmap force one of the two")
ap.add_argument("--backend", choices=["cuda", "hip"],
help="cuda = NVIDIA (default), hip = AMD RX 7900 XT/XTX or RX 9070 / AI PRO R9700 on Linux (experimental; chosen by itself "
"when the PC has no NVIDIA card Strata can use)")
help="cuda = NVIDIA (default), hip = AMD RX 7900 / 7800 / 7700 XT, RX 9060 XT / 9070 / AI PRO R9700 on "
"Linux (experimental; chosen by itself when the PC has no NVIDIA card Strata can use)")
ap.add_argument("--skip-build", action="store_true", help=argparse.SUPPRESS)
a = ap.parse_args()
if a.gpu is not None: # --gpu 0,2 means --gpus 0,2 (a user tried it: issue report)
@@ -1882,7 +1889,7 @@ def main() -> int:
if not found:
fail("no NVIDIA GPU found (nvidia-smi did not answer)",
"install the NVIDIA driver from https://www.nvidia.com/drivers and restart the PC"
+ ("; an AMD RX 7900 XT/XTX or RX 9070 / AI PRO R9700: --backend hip" if amd else ""))
+ (f"; AMD ({', '.join(AMD_ARCHS)}): --backend hip" if amd else ""))
if len(found) > 1 or gpu_problem(found[0]) is not None:
gpu_table(found)
sel = choose_gpus(a, found) # asked when two or more cards can share the model
+81
View File
@@ -0,0 +1,81 @@
"""Tests for setup.py's AMD card detection on a mocked KFD topology (/sys/class/kfd + /sys/class/drm): the arch
names from gfx_target_version, the CPU node skipped, HIP numbering, product names, which cards are supported and
which TheRock index each family installs from. No GPU, no ROCm, no downloads.
python -m unittest tools.test_setup_amd
"""
from __future__ import annotations
import sys
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
import setup # noqa: E402
def fake_sysfs(root: Path, nodes: list) -> None:
"""nodes: (gfx_target_version, simd_count, render_minor, product_name or None, vram_bytes)"""
for i, (ver, simd, minor, name, vram) in enumerate(nodes):
n = root / "class/kfd/kfd/topology/nodes" / str(i)
n.mkdir(parents=True)
(n / "properties").write_text(f"cpu_cores_count {0 if simd else 12}\nsimd_count {simd}\n"
f"gfx_target_version {ver}\ndrm_render_minor {minor}\n")
if simd:
d = root / f"class/drm/renderD{minor}/device"
d.mkdir(parents=True)
(d / "mem_info_vram_total").write_text(str(vram))
if name is not None:
(d / "product_name").write_text(name + "\n")
class KfdDetection(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.root = Path(self.tmp.name)
self.win = setup.WIN
setup.WIN = False
def tearDown(self):
setup.WIN = self.win
self.tmp.cleanup()
def test_every_family(self):
fake_sysfs(self.root, [
(0, 0, 0, None, 0), # the CPU node: skipped
(110001, 120, 128, "", 16 << 30), # gfx1101 without a product name
(120000, 64, 129, None, 16 << 30), # gfx1200, no product_name file
(120001, 128, 130, "AMD Radeon AI PRO R9700", 32 << 30),
(110002, 64, 131, None, 8 << 30), # gfx1102: listed, not supported
(100306, 4, 132, None, 512 << 20), # an integrated gfx1036: listed, not supported
(110000, 192, 133, "Radeon RX 7900 XTX", 24 << 30),
])
g = setup.amd_gpus(str(self.root))
self.assertEqual([x["arch"] for x in g], ["gfx1101", "gfx1200", "gfx1201", "gfx1102", "gfx1036", "gfx1100"])
self.assertEqual([x["index"] for x in g], [0, 1, 2, 3, 4, 5]) # HIP numbers: GPU nodes only
self.assertEqual(g[0]["name"], setup.AMD_NAMES["gfx1101"])
self.assertEqual(g[1]["name"], setup.AMD_NAMES["gfx1200"])
self.assertEqual(g[2]["name"], "AMD Radeon AI PRO R9700")
self.assertEqual(g[3]["name"], "AMD Radeon (gfx1102)")
self.assertAlmostEqual(g[2]["vram_gb"], 32.0)
ok = [x["arch"] for x in g if setup.amd_problem(x) is None]
self.assertEqual(ok, ["gfx1101", "gfx1200", "gfx1201", "gfx1100"])
self.assertIn("gfx1102", setup.amd_problem(g[3]))
self.assertIn("gfx1036", setup.amd_problem(g[4]))
def test_no_kfd(self):
self.assertEqual(setup.amd_gpus(str(self.root)), [])
def test_rocm_index_per_family(self):
for arch in setup.AMD_ARCHS:
self.assertIn(arch, setup.ROCM_INDEXES)
self.assertTrue(setup.ROCM_INDEXES["gfx1101"].endswith("/gfx110X-dgpu/"))
self.assertTrue(setup.ROCM_INDEXES["gfx1200"].endswith("/gfx120X-all/"))
self.assertEqual(setup.ROCM_INDEXES["gfx1101"], setup.ROCM_INDEXES["gfx1100"])
self.assertEqual(setup.ROCM_INDEXES["gfx1200"], setup.ROCM_INDEXES["gfx1201"])
if __name__ == "__main__":
unittest.main()