From ab7a7f9f1c97d99d5dd13da0ef371904c5cc5e6b Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 1 Jun 2026 02:55:57 -0700 Subject: [PATCH] Studio: match the Linux llama.cpp prebuilt to the runtime cudart major (#5914) * Studio: match the Linux llama.cpp prebuilt to the runtime cudart major * [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> --- studio/install_llama_prebuilt.py | 11 ++- .../test_install_llama_prebuilt_logic.py | 74 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/studio/install_llama_prebuilt.py b/studio/install_llama_prebuilt.py index 2afd54bec9..77d0905020 100644 --- a/studio/install_llama_prebuilt.py +++ b/studio/install_llama_prebuilt.py @@ -1402,7 +1402,16 @@ def direct_linux_release_plan( attempts: list[AssetChoice] = [] if host.has_usable_nvidia: - selection = linux_cuda_choice_from_release(host, bundle) + # Prefer the cudart major Studio loads at runtime (torch's bundled + # libcudart), not the newest detected on disk. Without this a stray + # cuda13 runtime outranks the torch cuda12 the binary links against. + torch_preference = detect_torch_cuda_runtime_preference(host) + selection = linux_cuda_choice_from_release( + host, + bundle, + preferred_runtime_line = torch_preference.runtime_line, + selection_preamble = torch_preference.selection_log, + ) if selection is not None: attempts.extend(selection.attempts) if host.has_rocm and not host.has_usable_nvidia: diff --git a/tests/studio/install/test_install_llama_prebuilt_logic.py b/tests/studio/install/test_install_llama_prebuilt_logic.py index 49ad6da177..4a427d6f54 100644 --- a/tests/studio/install/test_install_llama_prebuilt_logic.py +++ b/tests/studio/install/test_install_llama_prebuilt_logic.py @@ -438,6 +438,80 @@ def test_simple_linux_direct_release_uses_published_source_checksums_for_branch( assert exact_source is True +def test_simple_linux_direct_release_honors_torch_cudart_preference( + monkeypatch: pytest.MonkeyPatch, +): + # Regression: a Blackwell host (sm_120, driver 13.0) with BOTH cudart majors + # visible -- a stray cuda13 wheel plus torch's cuda12 -- must install the + # cuda12 build that matches the runtime torch, not the newest-major cuda13 + # build (which loads no GPU and silently falls back to CPU). + release = { + "tag_name": "b9334", + "assets": [ + { + "name": f"app-b9334-linux-x64-{profile}.tar.gz", + "browser_download_url": f"https://example.test/app-b9334-linux-x64-{profile}.tar.gz", + } + for profile in ( + "cuda12-newer", + "cuda12-portable", + "cuda13-newer", + "cuda13-portable", + ) + ], + } + # cuda13 detected first (newest-major order); both compatible with driver 13.0. + monkeypatch.setattr( + INSTALL_LLAMA_PREBUILT, + "detected_linux_runtime_lines", + lambda: ( + ["cuda13", "cuda12"], + { + "cuda13": ["/usr/local/lib/python3.13/site-packages/nvidia/cu13/lib"], + "cuda12": [ + "/venv/lib/python3.13/site-packages/nvidia/cuda_runtime/lib" + ], + }, + ), + ) + host = HostInfo( + system = "Linux", + machine = "x86_64", + is_windows = False, + is_linux = True, + is_macos = False, + is_x86_64 = True, + is_arm64 = False, + nvidia_smi = "nvidia-smi", + driver_cuda_version = (13, 0), + compute_caps = ["120"], + visible_cuda_devices = None, + has_physical_nvidia = True, + has_usable_nvidia = True, + ) + + def first_asset_for_torch(line): + monkeypatch.setattr( + INSTALL_LLAMA_PREBUILT, + "detect_torch_cuda_runtime_preference", + lambda h: INSTALL_LLAMA_PREBUILT.CudaRuntimePreference( + runtime_line = line, selection_log = [] + ), + ) + plan = INSTALL_LLAMA_PREBUILT.direct_linux_release_plan( + release, host, "unslothai/llama.cpp", "latest" + ) + return plan.attempts[0] + + # torch reports cuda12 (the cu128 runtime) -> install the cuda12 build. + primary = first_asset_for_torch("cuda12") + assert primary.name == "app-b9334-linux-x64-cuda12-newer.tar.gz" + assert primary.runtime_line == "cuda12" + + # torch unavailable -> unchanged newest-major fallback (documents the residual). + assert first_asset_for_torch(None).name == "app-b9334-linux-x64-cuda13-newer.tar.gz" + + @pytest.mark.parametrize( "mutate, expected_match", [