From 2dce261f4a66afea529d8e8dfa9dfee231d61ffe Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Sat, 11 Apr 2026 01:14:23 +0000 Subject: [PATCH] Install ROCm SDK wheels and relax HIP SDK prerequisite on Windows The previous Windows AMD install was incomplete in two material ways, both surfaced while verifying whether PyTorch has upstream Windows ROCm wheels (it does not -- pytorch.org's get-started page states "ROCm is not available on Windows" and every wheel under download.pytorch.org /whl/rocm7.x is manylinux_2_28_x86_64 only; upstream work is tracked in pytorch/pytorch#159520 and targeted for a future release). repo.radeon.com therefore remains the only source for Windows ROCm torch until that RFC lands, and AMD's install docs at rocm.docs.amd.com/projects/radeon-ryzen/.../install-pytorch.html document a two-step pip procedure that we were only implementing half of. Fixing both bugs here so the PR actually produces a working torch.version.hip import on a fresh Windows host. Bug 1: missing ROCm SDK wheels install step AMD's procedure first installs rocm_sdk_core, rocm_sdk_devel, rocm_sdk_libraries_custom, and rocm-.tar.gz (about 1.4 GB total). These wheels ship the ROCm runtime libraries that torch links against at import time. Without them `import torch` fails with missing DLL errors even when the torch wheels themselves are installed. Both 7.1.1 and 7.2.1 need this step; 7.1.1 stamps its SDK wheels with the `0.1.dev0` version string while 7.2.1 uses `7.2.1`. This adds the 4 SDK URLs per release to the wheel map and installs them as Step 1 ahead of the existing torch install (Step 2). Both steps are passed in a single pip call each so pip's dep resolver does not reset torch between wheels (matches AMD's troubleshooting guidance for the same failure mode). Bug 2: HIP SDK was a hard prerequisite, should be optional install.ps1 / setup.ps1 / install_python_stack.py all errored out when $env:HIP_PATH was absent, pointing users at the HIP SDK download page. But the HIP SDK developer toolkit at C:\Program Files\AMD\ROCm\ is for people compiling HIP kernels, not for running PyTorch. AMD's docs list only (a) the AMD graphics driver 26.2.2+ and (b) Python 3.12 as prerequisites. Gating on HIP_PATH was blocking the exact audience that #4280 is about -- regular Radeon users running Unsloth. HIP_PATH is now an optional version hint. When present and valid we use it to select the matching ROCm release; when absent or unsupported (e.g. HIP 6.4) we fall back to the newest stable release (_DEFAULT_WINDOWS_ROCM_VERSION = (7, 2)) and print a visible note pointing at the graphics driver download page. The HIP SDK install prompts have been removed from all three files. Use pip (not uv) for the Radeon wheels Both the SDK and torch install steps call `python -m pip install` directly via the new force_pip=True path added in the previous commit. AMD's documented procedure uses pip, uv has known wheel-corruption issues on similar large ROCm wheels (unslothai/unsloth#4966 for bitsandbytes), and pip is the combination AMD validates. This matches the fix applied to bitsandbytes on Linux ROCm. --- install.ps1 | 133 ++++++++++++++++----- studio/install_python_stack.py | 203 +++++++++++++++++++++++++-------- studio/setup.ps1 | 118 ++++++++++++++----- 3 files changed, 350 insertions(+), 104 deletions(-) diff --git a/install.ps1 b/install.ps1 index 5d70be4b4d..bb52ba58ab 100644 --- a/install.ps1 +++ b/install.ps1 @@ -255,30 +255,53 @@ function Install-UnslothStudio { return $null } - # Map a detected HIP SDK version to Radeon's Windows torch wheels. - # Returns @{ Torch = ...; Torchvision = ...; Torchaudio = ... } or $null - # when the version is unsupported. Wheels are cp312 only. + # Map a ROCm release version to the full Radeon Windows wheel set. + # Returns @{ SdkCore, SdkDevel, SdkLibraries, SdkTarball, Torch, + # Torchvision, Torchaudio } or $null when unsupported. AMD's docs at + # rocm.docs.amd.com/projects/radeon-ryzen/.../install-pytorch.html + # require a two-step install: first the rocm_sdk_* wheels (~1.4 GB; + # ship the runtime that torch links against), then torch itself. Both + # are mandatory -- torch import fails with missing DLLs otherwise. + # Wheels are cp312 only. function Get-RocmWheelUrls { param([Parameter(Mandatory = $true)]$Version) $base721 = 'https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/' $base711 = 'https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/' if ($Version.Major -eq 7 -and $Version.Minor -eq 2) { return @{ - Torch = $base721 + 'torch-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' - Torchvision = $base721 + 'torchvision-0.24.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' - Torchaudio = $base721 + 'torchaudio-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' + SdkCore = $base721 + 'rocm_sdk_core-7.2.1-py3-none-win_amd64.whl' + SdkDevel = $base721 + 'rocm_sdk_devel-7.2.1-py3-none-win_amd64.whl' + SdkLibraries = $base721 + 'rocm_sdk_libraries_custom-7.2.1-py3-none-win_amd64.whl' + SdkTarball = $base721 + 'rocm-7.2.1.tar.gz' + Torch = $base721 + 'torch-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' + Torchvision = $base721 + 'torchvision-0.24.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' + Torchaudio = $base721 + 'torchaudio-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' } } if ($Version.Major -eq 7 -and $Version.Minor -eq 1) { + # 7.1.1 stamps SDK wheels with `0.1.dev0`; torch gets rocmsdk date tag. return @{ - Torch = $base711 + 'torch-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' - Torchvision = $base711 + 'torchvision-0.24.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' - Torchaudio = $base711 + 'torchaudio-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' + SdkCore = $base711 + 'rocm_sdk_core-0.1.dev0-py3-none-win_amd64.whl' + SdkDevel = $base711 + 'rocm_sdk_devel-0.1.dev0-py3-none-win_amd64.whl' + SdkLibraries = $base711 + 'rocm_sdk_libraries_custom-0.1.dev0-py3-none-win_amd64.whl' + SdkTarball = $base711 + 'rocm-0.1.dev0.tar.gz' + Torch = $base711 + 'torch-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' + Torchvision = $base711 + 'torchvision-0.24.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' + Torchaudio = $base711 + 'torchaudio-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' } } return $null } + # Default Windows ROCm release when HIP_PATH is absent. HIP_PATH is an + # optional hint, NOT a prerequisite -- regular torch users only need + # an AMD graphics driver (26.2.2+ for 7.2.1) and Python 3.12. PyTorch + # does not publish Windows ROCm wheels on download.pytorch.org (see + # the "ROCm is not available on Windows" note on pytorch.org), so + # repo.radeon.com is the only source until pytorch/pytorch#159520 + # lands upstream Windows ROCm hosting in a future release. + $DefaultWindowsRocmVersion = @{ Major = 7; Minor = 2 } + function New-StudioShortcuts { param( [Parameter(Mandatory = $true)][string]$UnslothExePath @@ -646,9 +669,12 @@ shell.Run cmd, 0, False # users with both cards get the NVIDIA torch path they expect. if ($HasNvidiaSmi) { $HasAmdGpu = $false } - # Resolve HIP SDK when we are taking the AMD path. We still probe here - # even when $HasAmdGpu is $false so the status line is informative on - # mixed NVIDIA+AMD hosts. + # Probe HIP SDK as an OPTIONAL version hint. The HIP SDK developer + # toolkit is NOT a prerequisite for running torch on Windows -- AMD's + # install docs only require the graphics driver (26.2.2+ for 7.2.1) + # and Python 3.12. We use $HipSdkVersion when present to select a + # matching ROCm wheel release; otherwise we fall back to the newest + # stable release ($DefaultWindowsRocmVersion). $HipSdkVersion = $null if ($HasAmdGpu) { $HipSdkVersion = Get-HipSdkVersion @@ -658,11 +684,11 @@ shell.Run cmd, 0, False step "gpu" "NVIDIA GPU detected" } elseif ($HasAmdGpu) { if ($HipSdkVersion) { - step "gpu" ("AMD GPU detected (HIP SDK {0}.{1})" -f $HipSdkVersion.Major, $HipSdkVersion.Minor) + step "gpu" ("AMD GPU detected (HIP SDK {0}.{1} hint)" -f $HipSdkVersion.Major, $HipSdkVersion.Minor) } else { - step "gpu" "AMD GPU detected (HIP SDK missing)" "Yellow" - substep "Install HIP SDK from https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" "Yellow" - substep "and re-run this installer." "Yellow" + step "gpu" ("AMD GPU detected (will use rocm-rel-{0}.{1}.x)" -f $DefaultWindowsRocmVersion.Major, $DefaultWindowsRocmVersion.Minor) + substep "HIP SDK not found (optional). Ensure AMD graphics driver is up to date:" "DarkGray" + substep "https://www.amd.com/en/support/download/drivers.html" "DarkGray" } } else { step "gpu" "none (chat-only / GGUF)" "Yellow" @@ -925,12 +951,26 @@ shell.Run cmd, 0, False # The AMD/ROCm path does not use a --index-url; instead it installs # explicit wheel URLs from repo.radeon.com. $TorchIndexUrl stays $null - # on that branch so the NVIDIA/CPU path is visibly bypassed. + # on that branch so the NVIDIA/CPU path is visibly bypassed. HIP_PATH + # is a hint only -- we fall back to $DefaultWindowsRocmVersion when + # it is absent or points at an unsupported version, because the HIP + # SDK is NOT a runtime prerequisite for torch on Windows. $TorchIndexUrl = $null $RocmWheelUrls = $null + $RocmReleaseVersion = $null if ($HasAmdGpu) { if ($HipSdkVersion) { $RocmWheelUrls = Get-RocmWheelUrls -Version $HipSdkVersion + if ($RocmWheelUrls) { + $RocmReleaseVersion = $HipSdkVersion + } + } + if (-not $RocmWheelUrls) { + if ($HipSdkVersion) { + substep ("HIP SDK {0}.{1} is too old; falling back to rocm-rel-{2}.{3}.x" -f $HipSdkVersion.Major, $HipSdkVersion.Minor, $DefaultWindowsRocmVersion.Major, $DefaultWindowsRocmVersion.Minor) "Yellow" + } + $RocmWheelUrls = Get-RocmWheelUrls -Version $DefaultWindowsRocmVersion + $RocmReleaseVersion = $DefaultWindowsRocmVersion } } else { $TorchIndexUrl = Get-TorchIndexUrl @@ -1008,26 +1048,57 @@ shell.Run cmd, 0, False if ($SkipTorch) { substep "skipping PyTorch (--no-torch flag set)." "Yellow" } elseif (-not $RocmWheelUrls) { - if (-not $HipSdkVersion) { - Write-Host "[ERROR] AMD GPU detected but HIP SDK is not installed." -ForegroundColor Red - Write-Host " Download it from https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" -ForegroundColor Yellow - Write-Host " and re-run this installer." -ForegroundColor Yellow - } else { - Write-Host "[ERROR] AMD HIP SDK $($HipSdkVersion.Major).$($HipSdkVersion.Minor) detected." -ForegroundColor Red - Write-Host " Unsloth requires HIP SDK 7.1 or later on Windows. Please update from" -ForegroundColor Yellow - Write-Host " https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" -ForegroundColor Yellow - } + # Should be unreachable because the detection block above + # always falls back to $DefaultWindowsRocmVersion, but guard + # anyway so a future refactor that drops the fallback does + # not install CPU torch on an AMD host. + Write-Host "[ERROR] Could not resolve Windows ROCm wheel URLs." -ForegroundColor Red + Write-Host " This is a bug; please file it at github.com/unslothai/unsloth/issues" -ForegroundColor Yellow return } else { - substep "installing PyTorch ROCm wheels from repo.radeon.com..." - substep "(first wheel is ~780 MB; download may take a few minutes)" + # Verify the venv's Python is 3.12 -- Radeon's wheels are cp312 + # only and pip would fail with a confusing error otherwise. + $venvPyVer = '' + try { + $venvPyVer = (& $VenvPython -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>$null | Out-String).Trim() + } catch {} + if ($venvPyVer -and $venvPyVer -ne "3.12") { + Write-Host "[ERROR] Radeon Windows ROCm wheels require Python 3.12 (venv has $venvPyVer)." -ForegroundColor Red + Write-Host " Install Python 3.12 from https://www.python.org/downloads/ and re-run." -ForegroundColor Yellow + return + } + + substep ("installing Radeon ROCm wheels for rocm-rel-{0}.{1}.x ..." -f $RocmReleaseVersion.Major, $RocmReleaseVersion.Minor) + substep "Step 1/2: ROCm SDK runtime (~1.4 GB -- this will take a while)" + # Use python -m pip (NOT uv) because (a) AMD's documented + # procedure uses pip, (b) uv has known wheel-corruption issues + # on these big ROCm/bnb wheels (unslothai/unsloth#4966), and + # (c) pip's dep resolver is the combination AMD validates. We + # install all four SDK artefacts in one command so pip does + # not reset torch between them. + $sdkInstallExit = Invoke-InstallCommand { + & $VenvPython -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.SdkCore ` + $RocmWheelUrls.SdkDevel ` + $RocmWheelUrls.SdkLibraries ` + $RocmWheelUrls.SdkTarball + } + if ($sdkInstallExit -ne 0) { + Write-Host "[ERROR] Failed to install ROCm SDK wheels (exit code $sdkInstallExit)" -ForegroundColor Red + Write-Host " Verify your AMD graphics driver is recent and repo.radeon.com is reachable." -ForegroundColor Yellow + return + } + + substep "Step 2/2: PyTorch + torchvision + torchaudio (~820 MB)" $torchInstallExit = Invoke-InstallCommand { - uv pip install --python $VenvPython ` - $RocmWheelUrls.Torch $RocmWheelUrls.Torchvision $RocmWheelUrls.Torchaudio + & $VenvPython -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.Torch ` + $RocmWheelUrls.Torchvision ` + $RocmWheelUrls.Torchaudio } if ($torchInstallExit -ne 0) { Write-Host "[ERROR] Failed to install ROCm PyTorch (exit code $torchInstallExit)" -ForegroundColor Red - Write-Host " Verify HIP SDK $($HipSdkVersion.Major).$($HipSdkVersion.Minor) is installed and wheels are reachable." -ForegroundColor Yellow + Write-Host " Update your AMD graphics driver: https://www.amd.com/en/support/download/drivers.html" -ForegroundColor Yellow return } } diff --git a/studio/install_python_stack.py b/studio/install_python_stack.py index 8aa050ad53..d087a4a098 100644 --- a/studio/install_python_stack.py +++ b/studio/install_python_stack.py @@ -43,9 +43,23 @@ _ROCM_TORCH_INDEX: dict[tuple[int, int], str] = { } _PYTORCH_WHL_BASE = "https://download.pytorch.org/whl" -# Windows AMD ROCm torch wheels live at repo.radeon.com, not download.pytorch.org. -# Keyed by HIP SDK (major, minor). Wheels are cp312 only and require the HIP SDK -# to be pre-installed. +# Windows AMD ROCm torch wheels live at repo.radeon.com because PyTorch +# does NOT publish Windows ROCm wheels on download.pytorch.org (and says so +# on pytorch.org/get-started/locally: "ROCm is not available on Windows"). +# Every wheel under download.pytorch.org/whl/rocm{6.4,7.1,7.2}/ is +# manylinux_2_28_x86_64 only. Upstream work to ship Windows ROCm wheels is +# tracked at pytorch/pytorch#159520, targeted for torch 2.10/2.11 but not +# yet delivered. Until then repo.radeon.com is the only source. +# +# AMD's official install procedure +# (rocm.docs.amd.com/projects/radeon-ryzen/.../install-pytorch.html) is a +# TWO-STEP pip install: +# Step 1: rocm_sdk_core + rocm_sdk_devel + rocm_sdk_libraries_custom + +# rocm-.tar.gz. These wheels ship the ROCm runtime libraries +# that torch links against at import time. They total about 1.4 +# GB. The HIP SDK developer toolkit (HIP_PATH) is NOT a substitute +# -- torch imports the Python-packaged runtime from rocm_sdk_*. +# Step 2: torch + torchvision + torchaudio. About 820 MB. # # As of 2026-04, repo.radeon.com/rocm/windows/ contains four release dirs: # rocm-rel-6.4.4/ -- PEP 503 simple index (torch/, torchvision/, torchaudio/ @@ -55,18 +69,38 @@ _PYTORCH_WHL_BASE = "https://download.pytorch.org/whl" # so the filename changes whenever AMD rebuilds and we # cannot hardcode a URL for it. Supporting 6.4.4 would # require parsing the PEP 503 index at install time -- -# out of scope here; users on that SDK get a "please -# upgrade to 7.1+" error. -# rocm-rel-7.1.1/ -- flat layout, stable `+rocmsdk20251116` date tag. -# rocm-rel-7.2/ -- flat layout, stable `+rocmsdk20260116` date tag. -# rocm-rel-7.2.1/ -- flat layout, stable `+rocm7.2.1` version tag. Newest -# 7.2.x release as of writing; superset of rocm-rel-7.2. +# out of scope here. +# rocm-rel-7.1.1/ -- flat layout, torch stable `+rocmsdk20251116` tag, +# SDK wheels stamped `0.1.dev0` (pre-release marker). +# rocm-rel-7.2/ -- flat layout, torch stable `+rocmsdk20260116` tag. +# rocm-rel-7.2.1/ -- flat layout, torch stable `+rocm7.2.1` tag, SDK +# wheels stamped `7.2.1`. Newest 7.2.x release as of +# writing; superset of rocm-rel-7.2. # -# The map below routes HIP SDK 7.2.x -> rocm-rel-7.2.1 wheels (newer, bug -# fixes) rather than rocm-rel-7.2; torch bundles its own ROCm runtime so the -# host SDK point version does not need to match the wheel tag exactly. +# HIP SDK detection via HIP_PATH is an OPTIONAL version hint, not a +# prerequisite. Users only need an AMD graphics driver (26.2.2+ for 7.2.1) +# and Python 3.12. When HIP_PATH is absent or points at an unsupported +# version, we default to the newest stable release (7.2.1). _ROCM_WINDOWS_TORCH_WHEELS: dict[tuple[int, int], dict[str, str]] = { (7, 2): { + # Step 1: ROCm SDK wheels (ship the runtime torch imports) + "sdk_core": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/" + "rocm_sdk_core-7.2.1-py3-none-win_amd64.whl" + ), + "sdk_devel": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/" + "rocm_sdk_devel-7.2.1-py3-none-win_amd64.whl" + ), + "sdk_libraries": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/" + "rocm_sdk_libraries_custom-7.2.1-py3-none-win_amd64.whl" + ), + "sdk_tarball": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/" + "rocm-7.2.1.tar.gz" + ), + # Step 2: torch wheels "torch": ( "https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/" "torch-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl" @@ -81,6 +115,25 @@ _ROCM_WINDOWS_TORCH_WHEELS: dict[tuple[int, int], dict[str, str]] = { ), }, (7, 1): { + # Step 1: ROCm SDK wheels -- note 7.1.1 stamps the SDK wheels with + # `0.1.dev0` while keeping the torch wheels at 2.9.0. + "sdk_core": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/" + "rocm_sdk_core-0.1.dev0-py3-none-win_amd64.whl" + ), + "sdk_devel": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/" + "rocm_sdk_devel-0.1.dev0-py3-none-win_amd64.whl" + ), + "sdk_libraries": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/" + "rocm_sdk_libraries_custom-0.1.dev0-py3-none-win_amd64.whl" + ), + "sdk_tarball": ( + "https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/" + "rocm-0.1.dev0.tar.gz" + ), + # Step 2: torch wheels "torch": ( "https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/" "torch-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl" @@ -95,6 +148,13 @@ _ROCM_WINDOWS_TORCH_WHEELS: dict[tuple[int, int], dict[str, str]] = { ), }, } +# Default Windows ROCm release when HIP_PATH is absent or unreadable. Users +# only need a recent AMD graphics driver and Python 3.12 -- the HIP SDK +# developer toolkit is NOT required for running torch. +_DEFAULT_WINDOWS_ROCM_VERSION: tuple[int, int] = (7, 2) +_AMD_RADEON_DRIVER_URL = ( + "https://www.amd.com/en/support/download/drivers.html" +) _HIP_SDK_DOWNLOAD_URL = ( "https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" ) @@ -373,16 +433,31 @@ def _has_usable_nvidia_gpu() -> bool: def _ensure_rocm_torch_windows() -> None: - """Install Radeon's Windows ROCm torch wheels when an AMD GPU + HIP SDK - are both present. Called from _ensure_rocm_torch(). + """Install Radeon's Windows ROCm SDK + torch wheels when an AMD GPU is + present. Called from _ensure_rocm_torch(). - Silently returns when no AMD GPU is visible, so NVIDIA and CPU-only - Windows hosts are never touched. When an AMD GPU is present but the - HIP SDK is missing or too old, prints a pointer to the HIP SDK - download page and returns without raising -- the Linux helper has the - same shape. NVIDIA takes precedence on mixed AMD+NVIDIA hosts so - install.ps1 and setup.ps1 (which install CUDA torch in that case) - are not clobbered. + AMD's documented install procedure + (rocm.docs.amd.com/projects/radeon-ryzen/.../install-pytorch.html) is + a TWO-STEP sequence: first the rocm_sdk_* wheels (which ship the ROCm + runtime libraries torch links against at import time), then the torch + wheels themselves. Both steps are mandatory -- torch import fails + with missing-DLL errors without the SDK wheels, even on a host that + has the HIP SDK developer toolkit installed, because torch imports + the Python-packaged runtime. + + HIP_PATH is treated as an OPTIONAL version hint, not a prerequisite. + Regular users only need the AMD graphics driver (26.2.2+ for 7.2.1) + and Python 3.12, as documented by AMD. When HIP_PATH is missing or + points at an unsupported version, we default to the newest stable + release (_DEFAULT_WINDOWS_ROCM_VERSION) rather than erroring out. + + NVIDIA takes precedence on mixed AMD+NVIDIA hosts. Silently returns + when no AMD GPU is visible so NVIDIA and CPU-only Windows hosts are + never touched. Both pip installs pass force_pip=True because uv's + installer has known problems with these wheels -- matches the fix in + unslothai/unsloth#4966 for bitsandbytes on Linux ROCm, and AMD's own + troubleshooting notes flag pip dep-resolver overwrite scenarios on + this procedure. """ # NVIDIA wins on mixed hosts -- matches the Linux branch and avoids # overwriting a freshly installed CUDA torch with ROCm wheels. @@ -391,27 +466,6 @@ def _ensure_rocm_torch_windows() -> None: if not _has_rocm_gpu_windows(): return - ver = _detect_rocm_version_windows() - if ver is None: - _safe_print( - _red( - " AMD GPU detected but HIP SDK was not found. Install it " - f"from {_HIP_SDK_DOWNLOAD_URL} and re-run setup." - ) - ) - return - - wheels = _ROCM_WINDOWS_TORCH_WHEELS.get(ver) - if wheels is None: - _safe_print( - _red( - f" HIP SDK {ver[0]}.{ver[1]} detected. Unsloth on Windows " - f"requires HIP SDK 7.1 or 7.2. Please update from " - f"{_HIP_SDK_DOWNLOAD_URL}" - ) - ) - return - # Radeon wheels are cp312 only. Warn (do not crash) when the venv's # Python is not 3.12 -- pip will fail anyway with a clearer message. if (sys.version_info.major, sys.version_info.minor) != (3, 12): @@ -424,20 +478,79 @@ def _ensure_rocm_torch_windows() -> None: ) return + # Prefer HIP_PATH as a version hint when available, but fall back to + # the newest stable release so users without the developer SDK still + # get a working install. + detected = _detect_rocm_version_windows() + ver: tuple[int, int] + using_default = False + if detected is not None and detected in _ROCM_WINDOWS_TORCH_WHEELS: + ver = detected + elif detected is not None: + # Detected but unsupported (e.g. 6.4): fall back to newest with a + # visible notice so the user knows what happened. + _safe_print( + _dim( + f" HIP SDK {detected[0]}.{detected[1]} is too old; " + f"falling back to newest stable wheels " + f"({_DEFAULT_WINDOWS_ROCM_VERSION[0]}.{_DEFAULT_WINDOWS_ROCM_VERSION[1]})" + ) + ) + ver = _DEFAULT_WINDOWS_ROCM_VERSION + using_default = True + else: + ver = _DEFAULT_WINDOWS_ROCM_VERSION + using_default = True + + wheels = _ROCM_WINDOWS_TORCH_WHEELS.get(ver) + if wheels is None: + _safe_print( + _red( + f" No Windows ROCm wheel map for version {ver[0]}.{ver[1]}. " + f"Please file an issue at github.com/unslothai/unsloth/issues." + ) + ) + return + + source = "default" if using_default else "HIP_PATH" _safe_print( _dim( - f" HIP SDK {ver[0]}.{ver[1]} -- installing torch from " - f"repo.radeon.com/rocm/windows/" + f" Installing Radeon ROCm wheels for Windows " + f"(rocm-rel-{ver[0]}.{ver[1]}.x, {source}) from repo.radeon.com" ) ) + if using_default: + _safe_print( + _dim( + f" Ensure your AMD graphics driver is recent; get the " + f"latest from {_AMD_RADEON_DRIVER_URL}" + ) + ) + + # Step 1: ROCm SDK wheels (runtime libraries torch imports). ~1.4 GB + # download on a clean venv. pip_install( - f"ROCm torch (Windows, HIP SDK {ver[0]}.{ver[1]})", + f"ROCm SDK (Windows, {ver[0]}.{ver[1]})", + "--force-reinstall", + "--no-cache-dir", + wheels["sdk_core"], + wheels["sdk_devel"], + wheels["sdk_libraries"], + wheels["sdk_tarball"], + constrain = False, + force_pip = True, + ) + + # Step 2: torch wheels. ~820 MB download. + pip_install( + f"ROCm torch (Windows, {ver[0]}.{ver[1]})", "--force-reinstall", "--no-cache-dir", wheels["torch"], wheels["torchvision"], wheels["torchaudio"], constrain = False, + force_pip = True, ) diff --git a/studio/setup.ps1 b/studio/setup.ps1 index a74b116ff5..f9b9eae11a 100644 --- a/studio/setup.ps1 +++ b/studio/setup.ps1 @@ -320,29 +320,45 @@ function Get-HipSdkVersion { return $null } -# Map a detected HIP SDK version to Radeon's Windows torch wheels. -# Returns @{ Torch = ...; Torchvision = ...; Torchaudio = ... } or $null. +# Map a ROCm release version to Radeon's full Windows wheel set. +# Returns @{ SdkCore, SdkDevel, SdkLibraries, SdkTarball, Torch, +# Torchvision, Torchaudio } or $null when unsupported. AMD's install docs +# require a two-step install: first the rocm_sdk_* wheels (~1.4 GB; +# runtime torch links against), then torch itself. Wheels are cp312 only. function Get-RocmWheelUrls { param([Parameter(Mandatory = $true)]$Version) $base721 = 'https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/' $base711 = 'https://repo.radeon.com/rocm/windows/rocm-rel-7.1.1/' if ($Version.Major -eq 7 -and $Version.Minor -eq 2) { return @{ - Torch = $base721 + 'torch-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' - Torchvision = $base721 + 'torchvision-0.24.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' - Torchaudio = $base721 + 'torchaudio-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' + SdkCore = $base721 + 'rocm_sdk_core-7.2.1-py3-none-win_amd64.whl' + SdkDevel = $base721 + 'rocm_sdk_devel-7.2.1-py3-none-win_amd64.whl' + SdkLibraries = $base721 + 'rocm_sdk_libraries_custom-7.2.1-py3-none-win_amd64.whl' + SdkTarball = $base721 + 'rocm-7.2.1.tar.gz' + Torch = $base721 + 'torch-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' + Torchvision = $base721 + 'torchvision-0.24.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' + Torchaudio = $base721 + 'torchaudio-2.9.1%2Brocm7.2.1-cp312-cp312-win_amd64.whl' } } if ($Version.Major -eq 7 -and $Version.Minor -eq 1) { return @{ - Torch = $base711 + 'torch-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' - Torchvision = $base711 + 'torchvision-0.24.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' - Torchaudio = $base711 + 'torchaudio-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' + SdkCore = $base711 + 'rocm_sdk_core-0.1.dev0-py3-none-win_amd64.whl' + SdkDevel = $base711 + 'rocm_sdk_devel-0.1.dev0-py3-none-win_amd64.whl' + SdkLibraries = $base711 + 'rocm_sdk_libraries_custom-0.1.dev0-py3-none-win_amd64.whl' + SdkTarball = $base711 + 'rocm-0.1.dev0.tar.gz' + Torch = $base711 + 'torch-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' + Torchvision = $base711 + 'torchvision-0.24.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' + Torchaudio = $base711 + 'torchaudio-2.9.0%2Brocmsdk20251116-cp312-cp312-win_amd64.whl' } } return $null } +# Default Windows ROCm release when HIP_PATH is absent. HIP_PATH is an +# optional hint, not a prerequisite -- torch runtime comes from the +# rocm_sdk wheels, so users only need a graphics driver and Python 3.12. +$DefaultWindowsRocmVersion = @{ Major = 7; Minor = 2 } + # Find Visual Studio Build Tools for cmake -G flag. # Strategy: (1) vswhere, (2) scan filesystem (handles broken vswhere registration). # Returns @{ Generator = "Visual Studio 17 2022"; InstallPath = "C:\..."; Source = "..." } or $null. @@ -624,7 +640,9 @@ try { } catch {} if ($HasNvidiaSmi) { $HasAmdGpu = $false } -# Resolve HIP SDK when taking the AMD path. +# Probe HIP SDK as an optional version hint. Not a prerequisite -- torch +# links against the Python-packaged rocm_sdk wheels, so regular users +# only need the AMD graphics driver (26.2.2+ for 7.2.1) and Python 3.12. $HipSdkVersion = $null if ($HasAmdGpu) { $HipSdkVersion = Get-HipSdkVersion @@ -634,13 +652,11 @@ if ($HasNvidiaSmi) { step "gpu" "NVIDIA GPU detected" } elseif ($HasAmdGpu) { if ($HipSdkVersion) { - step "gpu" ("AMD GPU detected (HIP SDK {0}.{1})" -f $HipSdkVersion.Major, $HipSdkVersion.Minor) + step "gpu" ("AMD GPU detected (HIP SDK {0}.{1} hint)" -f $HipSdkVersion.Major, $HipSdkVersion.Minor) } else { - Write-Host "" - step "gpu" "AMD GPU detected (HIP SDK missing)" "Yellow" - substep "Install HIP SDK from https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" "Yellow" - substep "and re-run this installer." "Yellow" - Write-Host "" + step "gpu" ("AMD GPU detected (will use rocm-rel-{0}.{1}.x)" -f $DefaultWindowsRocmVersion.Major, $DefaultWindowsRocmVersion.Minor) + substep "HIP SDK not found (optional). Ensure AMD graphics driver is up to date:" "DarkGray" + substep "https://www.amd.com/en/support/download/drivers.html" "DarkGray" } } else { Write-Host "" @@ -1638,19 +1654,30 @@ if ($HasNvidiaSmi) { } if ($CuTag -eq "rocm") { - if (-not $HipSdkVersion) { - Write-Host "[FAILED] AMD GPU detected but HIP SDK is not installed." -ForegroundColor Red - Write-Host " Download it from https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" -ForegroundColor Yellow - Write-Host " and re-run this setup." -ForegroundColor Yellow - exit 1 + # HIP_PATH is an optional hint -- fall back to newest stable when + # absent or unsupported, because the HIP developer SDK is NOT a + # runtime prerequisite for torch on Windows (AMD's docs only list + # the graphics driver + Python 3.12). Users without HIP_PATH still + # get a working install. + $RocmWheelUrls = $null + $RocmReleaseVersion = $null + if ($HipSdkVersion) { + $RocmWheelUrls = Get-RocmWheelUrls -Version $HipSdkVersion + if ($RocmWheelUrls) { $RocmReleaseVersion = $HipSdkVersion } } - $RocmWheelUrls = Get-RocmWheelUrls -Version $HipSdkVersion if (-not $RocmWheelUrls) { - Write-Host "[FAILED] AMD HIP SDK $($HipSdkVersion.Major).$($HipSdkVersion.Minor) is not supported." -ForegroundColor Red - Write-Host " Unsloth on Windows requires HIP SDK 7.1 or later. Please update from" -ForegroundColor Yellow - Write-Host " https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html" -ForegroundColor Yellow + if ($HipSdkVersion) { + substep ("HIP SDK {0}.{1} is too old; falling back to rocm-rel-{2}.{3}.x" -f $HipSdkVersion.Major, $HipSdkVersion.Minor, $DefaultWindowsRocmVersion.Major, $DefaultWindowsRocmVersion.Minor) "Yellow" + } + $RocmWheelUrls = Get-RocmWheelUrls -Version $DefaultWindowsRocmVersion + $RocmReleaseVersion = $DefaultWindowsRocmVersion + } + if (-not $RocmWheelUrls) { + Write-Host "[FAILED] Could not resolve Windows ROCm wheel URLs (bug)." -ForegroundColor Red + Write-Host " Please file an issue at github.com/unslothai/unsloth/issues" -ForegroundColor Yellow exit 1 } + # Radeon wheels are cp312 only. Warn loudly when the venv's Python is # a different minor version so the pip error makes sense. We do not # exit here because setup.ps1 is also invoked as "unsloth studio update" @@ -1662,14 +1689,49 @@ if ($CuTag -eq "rocm") { substep "Warning: Radeon Windows ROCm wheels require Python 3.12, venv has $venvPyVer." "Yellow" substep "Re-create the venv with Python 3.12 from https://python.org if pip fails below." "Yellow" } - substep "installing PyTorch ROCm wheels from repo.radeon.com..." - substep "(first wheel is ~780 MB; download may take a few minutes)" + + substep ("installing Radeon ROCm wheels for rocm-rel-{0}.{1}.x from repo.radeon.com..." -f $RocmReleaseVersion.Major, $RocmReleaseVersion.Minor) + substep "Step 1/2: ROCm SDK runtime (~1.4 GB, may take several minutes)" + # Use `python -m pip install` NOT uv for the Radeon wheels. AMD's + # docs specify pip; uv has known issues on similar large ROCm wheels + # (matches the bitsandbytes situation in unslothai/unsloth#4966); and + # using pip directly is the combination AMD validates. if ($script:UnslothVerbose) { - Fast-Install $RocmWheelUrls.Torch $RocmWheelUrls.Torchvision $RocmWheelUrls.Torchaudio + & python -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.SdkCore ` + $RocmWheelUrls.SdkDevel ` + $RocmWheelUrls.SdkLibraries ` + $RocmWheelUrls.SdkTarball + $sdkInstallExit = $LASTEXITCODE + $output = "" + } else { + $output = & python -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.SdkCore ` + $RocmWheelUrls.SdkDevel ` + $RocmWheelUrls.SdkLibraries ` + $RocmWheelUrls.SdkTarball | Out-String + $sdkInstallExit = $LASTEXITCODE + } + if ($sdkInstallExit -ne 0) { + Write-Host "[FAILED] ROCm SDK install failed (exit code $sdkInstallExit)" -ForegroundColor Red + Write-Host $output -ForegroundColor Red + Write-Host " Verify your AMD graphics driver is recent: https://www.amd.com/en/support/download/drivers.html" -ForegroundColor Yellow + exit 1 + } + + substep "Step 2/2: PyTorch + torchvision + torchaudio (~820 MB)" + if ($script:UnslothVerbose) { + & python -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.Torch ` + $RocmWheelUrls.Torchvision ` + $RocmWheelUrls.Torchaudio $torchInstallExit = $LASTEXITCODE $output = "" } else { - $output = Fast-Install $RocmWheelUrls.Torch $RocmWheelUrls.Torchvision $RocmWheelUrls.Torchaudio | Out-String + $output = & python -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.Torch ` + $RocmWheelUrls.Torchvision ` + $RocmWheelUrls.Torchaudio | Out-String $torchInstallExit = $LASTEXITCODE } if ($torchInstallExit -ne 0) {