Skip to content

fix(AMD): recognise the RX 6950 XT, 6850M XT and 6550M instead of leaving them on CPU torch - #10746

Merged
danielhanchen merged 9 commits into
unslothai:mainfrom
LeoBorcherding:fix/amd-rdna2-missing-marketing-names
Sep 15, 2026
Merged

danielhanchen merged 9 commits into
unslothai:mainfrom
LeoBorcherding:fix/amd-rdna2-missing-marketing-names

Conversation

@LeoBorcherding

Copy link
Copy Markdown
Collaborator

The AMD marketing-name → gfx table covers the launch RDNA 2 parts and not the refresh ones, which carry their own model number. RX 6950 XT (Navi 21), RX 6850M XT (Navi 22) and RX 6550M (Navi 24) match no arm in any of the seven copies.

On a host where the name is the only arch source — Windows with the Adrenalin driver and no HIP SDK — no match means no arch, so the installer picks CPU-only torch for a card gfx103X-all does cover. Reported in #10468 on a 6950 XT: Settings > System showed "No visible GPU" while Task Manager listed the card.

The same table also cost the explanation. _amd_device_can_establish_a_mismatch decides whether the panel can say "PyTorch cannot use this card" and list it. When the Windows driver wrote no AdapterFamily — common, and the code's own note says the gfx1151 box's driver wrote none at all — it falls back to this table. An unmatched adapter therefore reads as one the stack declines on purpose, and the panel drops it entirely instead of showing what #9858 and #8620 built for exactly this case.

Before / after

studio/install_python_stack.py::_gfx_arch_from_gpu_name, run on Windows 11 26200:

# d0dbe9059e (base)                        # 6e45c61638 (this PR)
  RX 6950 XT  -> None    CPU-only torch      RX 6950 XT  -> gfx1030  gfx103X-all
  RX 6850M XT -> None    CPU-only torch      RX 6850M XT -> gfx1030  gfx103X-all
  RX 6550M    -> None    CPU-only torch      RX 6550M    -> gfx1034  gfx103X-all
  RX 6900 XT  -> gfx1030 gfx103X-all         RX 6900 XT  -> gfx1030  gfx103X-all
  RX 5700 XT  -> None    CPU-only torch      RX 5700 XT  -> None     CPU-only torch

The RDNA 1 row is the control: it is declined deliberately and stays declined.

What changed

Three names added to all seven copies (install.sh twice, install.ps1, studio/setup.sh, studio/setup.ps1, studio/install_python_stack.py, studio/backend/utils/hardware/hardware.py), plus:

  • a parity case per name in test_rocm_arch_table_parity.py, so a future edit that misses a copy fails naming the file. Verified non-vacuous: reverting the six source files fails 6 of them, each pointing at a different copy.
  • a case per name in tests/studio/test_amd_name_arch_r9700.ps1.
  • a backend test pinning that an AMD adapter named only by its marketing string establishes a mismatch, so the panel reports the card. Fails on base.

6850M XT is Navi 22 and joins the 6750 / 6700 arm as those already do. Every RDNA 2 row resolves to gfx103X-all, so the exact id inside the family picks no different wheel — the parity suite documents that grouping as deliberate.

Nothing about arch → index family, the wheel allowlist, or any other generation moves. 262 tests pass across the two suites; on this Windows host tests/studio/install has 71 pre-existing Linux-path failures, identical set on base and head.

What a matched card actually gets

Worth stating, since the fix is only useful if there is something on the other side. Unpacking our own current Windows prebuilt:

app-b10840-mix-d5c17a0-windows-x64-rocm-gfx103X.zip
  ggml-hip.dll -- all 142 offload bundles carry:
    amdgcn-amd-amdhsa--gfx1030 / gfx1031 / gfx1032 / gfx1034

Compiled code objects, not string-table mentions, so GGUF inference has real kernels for these cards. AMD publishes matching Windows torch wheels (torch-2.10.0+rocm7.13.0-*-win_amd64 on repo.amd.com/rocm/whl/gfx103X-all).

Training is a separate question this PR does not answer. The bf16 trap from #5337 is handled in main (arch_lacks_bf16() flags any gfx10* and _gpu_init.py replaces torch's is_bf16_supported, which returns True unconditionally on ROCm). Two items from the closed #6124 are still absent from main and unrelated to this diff: no RDNA 2 torch-version cap, and no gfx103X guard on for_inference().

Hardware coverage

No hosted GitHub runner has an AMD GPU. The self-hosted Strix Halo runner is Linux gfx1151 and cannot exercise an RDNA 2 Windows path, so this table is the test report.

hardware shape changed here what ran still needed
RX 6950 XT (Navi 21, gfx1030) — the reported card name resolves; CPU torch → gfx103X-all nothing on the silicon. Table resolution and the mismatch gate ran on Windows 11 26200, R9700 seated, at 6e45c61 one boot on a 6950 XT: does Settings > System list the card, does GGUF chat load onto it
RX 6850M XT (Navi 22), RX 6550M (Navi 24) same same, no silicon same. Laptop parts, so hardest to reach
Other RX 6000 (6900/6800/6750/6700/6650/6600/6500/6400/6300) nothing — same arms, same arch, same leaf parity suite asserts each still resolves as before nothing
RDNA 3 / 3.5 / 4 nothing full parity suite including the R9700 and Strix arms; the R9700 is the card in this box nothing
RDNA 1 (gfx101X), Polaris (gfx803) nothing — still matched by no arm, declined on purpose RX 5700 XT still resolves to nothing and still raises no mismatch nothing

Scope

Two of the three names are beyond the letter of #10468, which is a 6950 XT report. RX 6850M XT and RX 6550M came out of sweeping every RX 6000 marketing name against the table and they fail identically; leaving a known-missing name sitting in a line this PR already edits seemed worse than the wider diff. Cutting back to RX 6950 alone is a one-line change per copy if you would rather keep it to the report.

The training paragraph above is deliberate too. The fix is real and the thing it unblocks is unverified, and a body that stated only the first half would read as a promise of the second.

Bottom line. Solid: the routing change, proven by before/after on the real functions and pinned by tests that fail without it, with no other generation touched. Biggest gap: not one line of this ran on RDNA 2 silicon, and nobody on the team has an RDNA 2 card — so it fixes detection, and whether a 6950 XT then trains is untested by anyone, on any OS, since #7277 landed.

…ving them on CPU torch

The seven copies of the AMD marketing-name to gfx table cover the launch RDNA 2
parts and not the refresh ones, which carry their own model number: RX 6950 XT
(Navi 21), RX 6850M XT (Navi 22) and RX 6550M (Navi 24) matched no arm. On a host
where the name is the only arch source -- Windows with the Adrenalin driver and no
HIP SDK -- that means no arch, so CPU-only torch on a card the gfx103X-all index
does cover.

The same table decides whether Settings > System can report a card PyTorch cannot
use, so the gap also cost the message: an unmatched adapter reads as one the stack
declines on purpose, and the panel falls through to a bare "No visible GPU" beside
a card the OS is listing.

Adds the three names to all seven copies, a parity case for each so a future copy
that misses one fails naming the file, and a backend test pinning that a Windows
adapter named only by its marketing string establishes a mismatch.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-15T13:25:43.882247Z 4554fc6 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@danielhanchen

Copy link
Copy Markdown
Member

Confirmed the gap is still there in studio/install_python_stack.py and studio/backend/utils/hardware/hardware.py, where the RDNA 2 arms stop at RX 6900 and the refresh names fall through to CPU torch. Will get this reviewed.

@danielhanchen

Copy link
Copy Markdown
Member

Confirmed the table in studio/backend/utils/hardware/hardware.py and the six installer copies still have no arm for the 6950 XT, 6850M XT or 6550M, so those names fall through to CPU torch. This also flips those hosts from a CPU wheel to gfx103X-all ROCm torch, which nobody has run on RDNA 2 silicon; could you say whether you want that routed for all three or only the reported 6950 XT before I review?

@danielhanchen

Copy link
Copy Markdown
Member

Reviewed this alongside the other six open AMD PRs. Verdict: real issue, correct fix, no regression risk. I have pushed one commit to this branch filling two remaining gaps of the same kind. Details below.

Before and after

Before: AMD Radeon RX 6950 XT, RX 6850M XT and RX 6550M matched nothing in the marketing-name to gfx-arch tables, in any of the copies. Two consequences:

  • On Windows, where the adapter name is often the only architecture source available before torch is installed, those cards fell through to CPU torch.
  • Settings > System dropped the card from the summary rather than explaining it.

After: they resolve to gfx1030 and gfx1034. Because every RDNA2 row routes to the same gfx103X-all wheel index, naming the exact arch does not change which wheel anyone downloads. It changes whether the card is recognised at all.

This is a real issue, not a cosmetic one. Filing the RX 6850M XT (Navi 22) under the gfx1030 arm is fine for the same reason.

Evidence that it works

Sensitivity. I ran this PR's test files against main's tables: 6 parity failures plus 1 backend failure. Against the PR's tables: 0. So the tests genuinely detect the defect rather than passing either way.

Real Windows hardware. Ran base versus head on a self-hosted Windows 11 gfx1151 Strix Halo runner, PowerShell 5.1 Desktop, comparing failing test IDs rather than counts:

state passed failed skipped failing tests
base 87 0 0 none
head 97 0 0 none
merge 97 0 0 none

Verdict NO_REGRESSION. The 87 to 97 move is this PR's own added parametrisation.

Non-AMD. I drove install.sh's get_torch_index_url plus the architecture-routing arm through a 49-cell matrix of [Linux, Windows, WSL, macOS] x [NVIDIA, AMD, CPU-only, Intel XPU, Apple MLX], with the host's own nvidia-smi and /proc/driver/nvidia shadowed out so each cell really answers for its persona. This PR's output is identical to main in all 49 cells. I also ran Studio's hardware.py through 20 [OS] x [accelerator] personas in fresh interpreters: the GPU summary changed in no cell, and no non-AMD persona probed AMD tooling. The only things that moved are the five name-table answers, which is the point of the PR.

One thing I added

Going through every shipped RDNA2 SKU against the table, two more cards of exactly the same class were still missing, both Navi 24:

  • AMD Radeon RX 6450M
  • AMD Radeon PRO W6300

I pushed those to the gfx1034 arm in all six source copies plus the two test tables. 97 tests pass. RDNA1 (RX 5700 XT and friends) stays unmatched, which is correct, those are not supported.

What the hardware could not answer

The only AMD hardware in the pool is gfx1151 Strix Halo. There is no RDNA2 card anywhere, so nothing here is an end-to-end demonstration that an RX 6950 XT now installs correctly. What was measured is the table logic and the parity between the six copies, on a real Windows box under real PowerShell 5.1. The base leg also cannot show the defect, because the PR modifies its own test file and the CI checks out each state whole, so read the Windows result as "the fix and its tests are green on Windows" rather than "the bug was reproduced and closed".

Happy to merge this.

@danielhanchen

Copy link
Copy Markdown
Member

@codex review

@danielhanchen

Copy link
Copy Markdown
Member

@codex security review

@danielhanchen

Copy link
Copy Markdown
Member

On the question of before/after UI screenshots for this PR: I looked into it properly and concluded they are not producible on any hardware I can reach. Recording why, since "we skipped it" and "it cannot be shown here" are different claims.

The PR edits hardware.py's marketing-name table, which feeds Settings > System, so it is a fair candidate on visible effect rather than on file paths. But measuring what actually moves:

torch reports gcnArchName state name_table("RX 6950 XT") get_gpu_summary().gpu_name
gfx1030 main null AMD Radeon RX 6950 XT
gfx1030 this PR gfx1030 AMD Radeon RX 6950 XT
"" (cannot tell) main null AMD Radeon RX 6950 XT
"" (cannot tell) this PR gfx1030 AMD Radeon RX 6950 XT

gpu_name is identical in all four cells, so the card is not dropped from the panel and the summary does not move. The only thing that changes is the internal arch lookup, and its single consumer in the backend is _amd_device_can_establish_a_mismatch at hardware.py:972, which decides whether the torch/GPU mismatch repair is offered.

So the user-visible effect is real but narrow, and reaching it needs all three of: Windows, an RDNA2 Radeon, and a driver that published no AdapterFamily to the DirectX registry (which is the branch the name lookup exists to cover). The AMD pool here is gfx1151 Strix Halo, RDNA3.5, on both its Linux and Windows boxes. There is no RDNA2 card in it.

Shooting the pair anyway would produce two identical images, which reads as "this PR changed nothing" and would be worse than saying this. The evidence for the change is the table logic itself: 97 tests pass on a real Windows 11 gfx1151 box, and running this PR's tests against main's tables gives 6 parity failures plus 1 backend failure, so the tests do detect the defect rather than passing either way.

The rest of the PR's visible effect is installer output, not the web UI, so it is terminal text rather than something a screenshot pair would add to.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 4e987130d8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@unslothai unslothai deleted a comment from chatgpt-codex-connector Bot Sep 14, 2026
danielhanchen added a commit to danielhanchen/unsloth-staging-2 that referenced this pull request Sep 14, 2026
Comments only, no behaviour change. Keeps every load-bearing fact: the issue
number, that 6850M XT is Navi 22 filed under the Navi 21 arm deliberately, that
every RDNA 2 row resolves to gfx103X-all so the exact id picks no different
wheel, and that RDNA 1 stays declined on purpose.
@danielhanchen

Copy link
Copy Markdown
Member

CI triage note, since several checks here are red and none of them are this PR. Posting the evidence rather than asking anyone to take it on trust.

1. Repo tests (CPU, studio) and the staging workflow-trigger lint. Both fail on the same two assertions:

FAILED tests/studio/test_studio_smokes_do_not_trigger_on_the_training_library.py
       ::test_the_filter_lists_exactly_the_github_paths_the_steps_execute[studio-update-smoke.yml]
FAILED tests/studio/test_uv_cache_discipline.py::test_every_warm_installer_job_restores_the_uv_cache
       - these jobs run the installer with no uv download cache: studio-update-smoke.yml:idempotency-windows

This was a transient breakage on main itself. studio-update-smoke.yml gained the test that requires uv-cache-restore before the workflow gained the action; the workflow side landed in b58ea42 at 12:48. Checked directly:

tree uv-cache-restore in idempotency-windows the two tests
upstream main b58ea42 (now) present 11 passed
the base these branches sit on, 289e0df absent 11 passed (the test did not require it yet)

CI runs against main as of run time, and these runs predate 12:48, so they caught the window in between. No PR in this batch touches studio-update-smoke.yml, test_uv_cache_discipline.py or test_studio_smokes_do_not_trigger_on_the_training_library.py (verified across all six). A re-run picks up the fixed main.

2. The three Core jobs fail inside unsloth_zoo @ main - full pytest (CPU) on allocator configuration (PYTORCH_ALLOC_CONF / PYTORCH_CUDA_ALLOC_CONF all None). The same workflow is failure on main itself (run 34820611889), and nothing in this batch reaches unsloth_zoo.

3. Repo tests (CPU, rest) fails on one assertion:

FAILED tests/test_source_read_encoding.py::test_checked_in_file_reads_name_an_encoding
['tests/version_compat/test_bitsandbytes_pinned_symbols.py:288: read_text()']

I ran that test on a clean main checkout and it fails identically, same file and line. It is a genuine small bug (a read_text() without encoding = "utf-8" breaks on Windows the moment that file gains a non-ASCII byte) and deserves its own PR, but it is not this one.

So: buckets 3 and 3 and 3, in the runbook's terms. Nothing here blocks these PRs, and I have re-run the affected jobs now that main carries the fix.

@danielhanchen

Copy link
Copy Markdown
Member

Merged current main (a6cf596) into this branch, and took over driving it.

The branches had drifted far enough that CI was testing a stale combination rather than the change. The clearest case: tests/sh/test_setup_staged_root.sh failed 4 assertions in CI while passing locally on every tree here, because main had changed the sidecar-removal code and grown the test from 34 assertions to 36, while the branch still carried the 34-assertion version. Old test, new code.

tree assertions result
main a6cf596 36 pass
this branch's old base 289e0df 34 pass
the CI merge commit 34 4 failed

Merged cleanly with no conflicts. Verified before pushing:

  • 65 of 65 shell installer suites pass, zero failures
  • the PR's own suites pass

Two other red checks that were also main's rather than this branch's, for the record:

  • Repo tests (CPU, studio) failed on test_uv_cache_discipline and test_studio_smokes_do_not_trigger_on_the_training_library. main gained the test requiring uv-cache-restore before studio-update-smoke.yml gained the action; the workflow side landed in b58ea42. It clears on a re-run against fixed main, which I confirmed.
  • The three Core jobs fail inside unsloth_zoo @ main on allocator configuration, and that workflow is red on main itself.

Still genuinely outstanding and not from this branch: tests/test_source_read_encoding.py flags tests/version_compat/test_bitsandbytes_pinned_symbols.py:288 for a read_text() with no encoding = "utf-8". It reproduces on a clean main checkout, same file and line. Worth its own small PR since it breaks on Windows the moment that file gains a non-ASCII byte.

@danielhanchen

Copy link
Copy Markdown
Member

@codex review

1 similar comment
@danielhanchen

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: d0205f17e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

danielhanchen added a commit to danielhanchen/unsloth-staging-2 that referenced this pull request Sep 15, 2026
@danielhanchen

Copy link
Copy Markdown
Member

Re-validated on current main (1e07231) with the branch merged, on real gfx1151 Strix Halo hardware on both Linux and Windows, and through a hermetic installer matrix. Summary: real issue, correct fix, no regression on NVIDIA, Mac, CPU, Windows or WSL. One commit pushed, comments only.

Before and after

Before: AMD Radeon RX 6950 XT, RX 6850M XT, RX 6550M, RX 6450M and PRO W6300 matched no arm in any of the seven marketing-name tables. On a Windows host whose driver wrote no AdapterFamily, the name is the only architecture source, so those cards fell through to CPU torch (#10468), and Settings > System could not explain why.

After: they resolve to gfx1030 or gfx1034, and every RDNA 2 row routes to the same gfx103X-all wheel, so the change decides whether the card is recognised, not which wheel it gets.

Evidence

Real hardware, self-hosted gfx1151, base 1e07231 versus this head:

job base head verdict
Linux, tests/studio/install (arch parity + ROCm support) 643 passed, 0 failed 653 passed, 0 failed NO_REGRESSION
Linux, backend test_torch_cpu_build_on_nvidia_host.py + test_rocm_windows_vram_7072.py pass pass NO_REGRESSION
Windows 11, same install suites under the runner's Python 3.12 pass pass NO_REGRESSION
Windows 11, test_amd_name_arch_r9700.ps1 + test_amd_venv_repair_loop.ps1 under PowerShell 5.1 pass pass NO_REGRESSION

The added tests move base to head by exactly the new parametrisations; nothing that passed on main fails here.

Installer matrix: install.sh's get_torch_index_url plus the whole torch routing block, extracted and driven under a fake toolchain (uname, nvidia-smi, rocminfo, amd-smi, hipconfig, /proc/version, /opt/rocm), 183 cells across [Linux, WSL, macOS arm64, macOS x86_64, Windows msys] x [NVIDIA, AMD gfx1151 / gfx1102 / gfx1200 / gfx1030 / gfx906 / name-only / mixed three-adapter, CPU, XPU pin] x [tool present, absent, failing, empty]. This branch differs from main in 18 cells, all of them the name-only RDNA 2 refresh cells, and is byte-identical in the other 165 including every NVIDIA, macOS, WSL and CPU cell.

Hosted runners: ubuntu-latest, macos-15 and windows-latest green on the branch's test files.

Local: 67 of 67 shell installer suites, the full tests/studio/install, tests/python and backend selections have the same failing-ID sets as main.

One thing worth knowing

The RX 6850M XT is Navi 22, which is gfx1031. The table files it under the gfx1030 arm, which is how the RX 6700, 6750 XT and 6800M are already filed on main, and torch is unaffected because gfx1030 through gfx1036 all take gfx103X-all. The only consumer that tells them apart is the llama.cpp prebuilt selection in install_llama_prebuilt.py, which lists gfx1030 and gfx1031 as separate bundles. That is a pre-existing grouping decision for all Navi 22 parts and belongs in its own change rather than one row here.

Old installs and updating

A host that already has ROCm torch keeps its wheel: the name table is consulted only when no runtime or driver arch is available. A host with one of these cards that was routed to CPU torch because the name was unknown moves to the ROCm wheel on its next update. That is the point of the change, and it is the same path every already-listed RDNA 2 card takes. The same applies to a hand-built ROCm torch on one of these cards with no AMD SDK metadata: the existing generic-wheel repair replaces it with the per-gfx wheel, exactly as it does for an RX 6600 today, because the installer cannot tell a working custom build from a kernel-less one. Installs with a matching ROCm wheel, CUDA on NVIDIA-primary or mixed hosts, CPU on Intel-only hosts, and an explicit CPU backend or /cpu pin are all left alone on both platforms.

Not tested here

The pool is gfx1151 only, so no RDNA 2 card exercised the end-to-end Windows name-only path; what was measured is the table logic, its parity across the seven copies, and the absence of movement everywhere else. NVIDIA, Intel XPU and Apple MLX were covered by the matrix and the repository's hardware spoof tests, not by hardware.

@danielhanchen

Copy link
Copy Markdown
Member

@codex review

1 similar comment
@danielhanchen

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 4554fc675e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danielhanchen
danielhanchen merged commit 2e0340a into unslothai:main Sep 15, 2026
81 of 83 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants