From ef97f3c961acf7fe724f95edc61c16c00f5da39c Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 27 Jul 2026 03:46:38 -0700 Subject: [PATCH] tests: record the gfx1152 llama.cpp bundle gap so the next one is not silent (#7491) * tests: record the gfx1152 llama.cpp bundle gap so the next one is not silent #7431 made gfx1152 (Krackan Point, Radeon 860M/840M) a first-class arch, which fixed torch wheel selection: those laptops were pulling gfx1150 wheels built for a different LLVM target. It also changed llama.cpp prebuilt selection, because no gfx1152 bundle is published. published_rocm_choice_for_host deliberately refuses to serve a sibling-family bundle, so those hosts now fall back to a HIP source build. That is the right outcome, a wrong-ISA binary fails at the first BLAS call rather than merely installing slowly, but nothing recorded it and nothing would have caught it. TestPublishedRocmGfxSelection builds its release from a hardcoded family list, so it can only assert about arches someone already thought to add. Adds TestPublishedRocmBundleCoverage: - PUBLISHED mirrors the mapped_targets in llama-prebuilt-manifest.json. - KNOWN_GAPS lists arches _GFX_TO_AMD_INDEX_ARCH routes torch for that no bundle covers: gfx1033/1035/1036 (RDNA 2, never built) and gfx1152. - test_known_gaps_fall_back_to_source_build pins each to None. - test_every_torch_routed_arch_is_covered_or_a_known_gap compares the routed set against bundle coverage, so adding an arch for torch without a bundle has to be a deliberate KNOWN_GAPS entry. The invariant fires both ways. Simulating a new routed arch fails with "coverage drifted: ['gfx1153'] newly uncovered"; simulating a published gfx1152 bundle fails with "gfx1152 is in KNOWN_GAPS but a bundle now matches it; drop it from the set", so closing the gap cannot leave the list stale. Reads _GFX_TO_AMD_INDEX_ARCH from source instead of importing install_python_stack, which this suite does not otherwise depend on. No production code changes. Install suite 1355 passed, no new failures. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- tests/studio/install/test_selection_logic.py | 94 ++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/tests/studio/install/test_selection_logic.py b/tests/studio/install/test_selection_logic.py index 8ebcd6cc86..15537bb2bf 100644 --- a/tests/studio/install/test_selection_logic.py +++ b/tests/studio/install/test_selection_logic.py @@ -2935,6 +2935,100 @@ class TestPublishedRocmGfxSelection: assert choice.name == "app-b9457-windows-x64-rocm-gfx120X.zip" +class TestPublishedRocmBundleCoverage: + """Every arch the installer routes torch for should also have a llama.cpp + bundle, or be recorded here as a known gap. Routing an arch for torch while + no bundle covers it is silent: the GPU works for training and drops to a HIP + source build for inference, which is correct but much slower to install.""" + + # mapped_targets of each published ROCm bundle, mirroring + # unslothai/llama.cpp's llama-prebuilt-manifest.json. + PUBLISHED = { + "gfx103X": ["gfx1030", "gfx1031", "gfx1032", "gfx1034"], + "gfx110X": ["gfx1100", "gfx1101", "gfx1102", "gfx1103"], + "gfx120X": ["gfx1200", "gfx1201"], + "gfx1150": ["gfx1150"], + "gfx1151": ["gfx1151"], + "gfx908": ["gfx908"], + "gfx90a": ["gfx90a"], + } + + # Arches _GFX_TO_AMD_INDEX_ARCH routes torch for that no bundle covers. + # gfx1033/1035/1036: RDNA 2 variants, never built. + # gfx1152: Krackan Point (Radeon 860M/840M). Torch goes to its own + # repo.amd.com/rocm/whl/gfx1152 leaf, but no llama.cpp bundle exists, so + # these hosts source-build. Publish a -gfx1152 bundle, or add gfx1152 to + # the gfx1150 bundle's mapped_targets if that build genuinely covers it, + # then drop it from this set. + KNOWN_GAPS = {"gfx1033", "gfx1035", "gfx1036", "gfx1152"} + + def _release(self): + return make_release( + [ + make_artifact( + f"app-b9457-linux-x64-rocm-{fam}.tar.gz", + install_kind = "linux-rocm", + runtime_line = None, + coverage_class = None, + supported_sms = [], + min_sm = None, + max_sm = None, + bundle_profile = None, + rank = 1000, + gfx_target = fam, + mapped_targets = targets, + ) + for fam, targets in self.PUBLISHED.items() + ], + upstream_tag = "b9457", + ) + + def _host(self, gfx): + return make_host( + machine = "x86_64", + nvidia_smi = None, + driver_cuda_version = None, + compute_caps = [], + has_physical_nvidia = False, + has_usable_nvidia = False, + has_rocm = True, + rocm_gfx_target = gfx, + ) + + def test_known_gaps_fall_back_to_source_build(self): + """A gap arch must return None rather than be served a sibling bundle: + a wrong-ISA binary fails at the first BLAS call instead of installing + slowly, which is the worse of the two outcomes.""" + release = self._release() + for gfx in sorted(self.KNOWN_GAPS): + assert ( + INSTALL_LLAMA_PREBUILT.published_rocm_choice_for_host( + release, self._host(gfx), "linux-rocm" + ) + is None + ), f"{gfx} is in KNOWN_GAPS but a bundle now matches it; drop it from the set" + + def test_every_torch_routed_arch_is_covered_or_a_known_gap(self): + """The guard that would have caught gfx1152: adding an arch to + _GFX_TO_AMD_INDEX_ARCH without a bundle must be a deliberate entry in + KNOWN_GAPS, not an unnoticed drop to source builds.""" + import re + + # Read the table from source rather than importing the installer module, + # which pulls in a heavy dependency chain this suite does not need. + stack = (PACKAGE_ROOT / "studio" / "install_python_stack.py").read_text(encoding = "utf-8") + body = re.search(r"_GFX_TO_AMD_INDEX_ARCH.*?=\s*\{(.*?)\n\}", stack, re.S) + assert body, "_GFX_TO_AMD_INDEX_ARCH not found in install_python_stack.py" + routed = set(re.findall(r'"(gfx[0-9a-z]+)":', body.group(1))) + assert routed, "parsed no arches out of _GFX_TO_AMD_INDEX_ARCH" + covered = {t.lower() for targets in self.PUBLISHED.values() for t in targets} + uncovered = {a for a in routed if a.lower() not in covered} + assert uncovered == self.KNOWN_GAPS, ( + f"llama.cpp bundle coverage drifted: {sorted(uncovered - self.KNOWN_GAPS)} " + f"newly uncovered, {sorted(self.KNOWN_GAPS - uncovered)} no longer a gap" + ) + + class TestPublishedMacosForkSelection: """macOS routes to the fork's llama--bin-macos-.tar.gz, selected by install_kind."""