diff --git a/install.ps1 b/install.ps1 index bb52ba58ab..a8957520ed 100644 --- a/install.ps1 +++ b/install.ps1 @@ -259,10 +259,11 @@ function Install-UnslothStudio { # 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. + # require a two-step install: first the rocm_sdk_* wheels (~1.3 GB + # for 7.2.1; ~3.2 GB for 7.1.1 whose sdk_devel is 2.4 GB) that ship + # the runtime torch links against, then torch itself (~780 MB for + # 7.2.1, ~692 MB for 7.1.1). 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/' @@ -1068,36 +1069,59 @@ shell.Run cmd, 0, False 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 { + substep ("installing Radeon ROCm SDK + PyTorch wheels for rocm-rel-{0}.{1}.x" -f $RocmReleaseVersion.Major, $RocmReleaseVersion.Minor) + # Total download size is release-dependent: 7.2.1 is ~2.1 GB + # (1.3 GB SDK + 780 MB torch) and 7.1.1 is ~3.9 GB (3.2 GB + # SDK + 692 MB torch; 7.1.1's sdk_devel alone is 2.4 GB). + # Show the number so a user on a metered connection is not + # surprised. + if ($RocmReleaseVersion.Major -eq 7 -and $RocmReleaseVersion.Minor -eq 1) { + substep "Downloading ~3.9 GB from repo.radeon.com (7.1.1 sdk_devel is 2.4 GB)" + } else { + substep "Downloading ~2.1 GB from repo.radeon.com" + } + # Bootstrap pip + setuptools + wheel into the venv before + # running `& $VenvPython -m pip install`. uv venvs do not + # ship pip by default. setuptools is needed because the + # rocm-.tar.gz artefact is a source distribution that + # pip must build with setuptools as its backend. + substep "bootstrapping pip, setuptools, wheel into venv..." + $bootstrapExit = Invoke-InstallCommand { uv pip install --python $VenvPython pip setuptools wheel } + if ($bootstrapExit -ne 0) { + Write-Host "[ERROR] Failed to bootstrap pip/setuptools/wheel into venv (exit $bootstrapExit)" -ForegroundColor Red + return + } + # Install all 7 Radeon artefacts in a SINGLE pip call. AMD's + # docs document a two-step install, but torch's metadata has + # `Requires-Dist: rocm[libraries]==` which cascades to + # rocm-sdk-libraries-custom== -- a package that does NOT + # exist on PyPI (PyPI has rocm/rocm-sdk-core/rocm-sdk-devel + # only at version 0.1.0, wrong version). Splitting the + # install and using --force-reinstall on the torch step makes + # pip cascade-resolve the rocm dep chain against PyPI and + # fail. Passing every URL in one command gives pip's resolver + # the full dep graph upfront, so --force-reinstall works and + # pip never tries to reach PyPI for the missing packages. + # + # We use `$VenvPython -m pip install` (not uv) because: + # (a) AMD's docs validate pip specifically; + # (b) uv has known wheel-corruption issues on similar large + # ROCm wheels (unslothai/unsloth#4966 for bitsandbytes); + # (c) pip's default build-isolation is required to build the + # rocm-.tar.gz source distribution and uv's pip + # shim does not set this up the same way. + $rocmInstallExit = 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 { - & $VenvPython -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.SdkTarball ` $RocmWheelUrls.Torch ` $RocmWheelUrls.Torchvision ` $RocmWheelUrls.Torchaudio } - if ($torchInstallExit -ne 0) { - Write-Host "[ERROR] Failed to install ROCm PyTorch (exit code $torchInstallExit)" -ForegroundColor Red + if ($rocmInstallExit -ne 0) { + Write-Host "[ERROR] Failed to install ROCm wheels (exit code $rocmInstallExit)" -ForegroundColor Red 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 6822b02b3d..aea1bc085a 100644 --- a/studio/install_python_stack.py +++ b/studio/install_python_stack.py @@ -55,11 +55,23 @@ _PYTORCH_WHL_BASE = "https://download.pytorch.org/whl" # (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. +# rocm-.tar.gz. The three wheels ship the ROCm runtime +# libraries torch links against at import time; the tar.gz is a +# tiny (~15 KB) Python sdist for a meta-package named "rocm" +# that requires the other three. The HIP SDK developer toolkit +# (HIP_PATH) is NOT a substitute -- torch imports the +# Python-packaged runtime from rocm_sdk_*. Step 1 download size +# varies dramatically by release: 7.2.1 is about 1.3 GB total +# (sdk_core ~615 MB, sdk_devel ~222 MB, sdk_libraries ~467 MB) +# while 7.1.1 is about 3.2 GB total -- its sdk_devel wheel is a +# massive 2.4 GB (debug symbols / unstripped libraries). +# Step 2: torch + torchvision + torchaudio. About 780 MB for 7.2.1 +# (torch itself is 783 MB; vision/audio are small), 692 MB for +# 7.1.1. +# +# All URLs in _ROCM_WINDOWS_TORCH_WHEELS below were verified live on +# 2026-04-11 with HEAD requests; see temp/windows_amd_tests for the +# verification script. # # 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/ @@ -524,25 +536,34 @@ def _ensure_rocm_torch_windows() -> None: ) ) - # Step 1: ROCm SDK wheels (runtime libraries torch imports). ~1.4 GB - # download on a clean venv. + # Install all 7 Radeon artefacts (4 SDK + 3 torch) in a SINGLE pip call. + # + # Why one call instead of AMD's documented two steps? torch's metadata + # declares `Requires-Dist: rocm[libraries]==` which cascades to + # `rocm-sdk-libraries-custom==`. That package does NOT exist on + # PyPI; it is only reachable via the direct URL at repo.radeon.com. + # Similarly, `rocm-sdk-core==` on PyPI is stuck at 0.1.0, wrong + # version. If we split the install and use --force-reinstall on the + # torch step, pip's resolver cascades to re-resolve all transitive + # deps, searches PyPI for rocm-sdk-libraries-custom, fails to find + # it, and aborts the whole install. + # + # Passing every URL in one command gives pip's resolver the full dep + # graph upfront. pip picks the right sources, builds the tarball via + # default build isolation, and --force-reinstall works correctly. + # Total download: ~2.1 GB for 7.2.1, ~3.9 GB for 7.1.1 (7.1.1's + # sdk_devel wheel is a massive 2.4 GB -- appears to ship debug + # symbols or unstripped libraries). pip_install( - f"ROCm SDK (Windows, {ver[0]}.{ver[1]})", + f"ROCm SDK + PyTorch (Windows, {ver[0]}.{ver[1]})", "--force-reinstall", "--no-cache-dir", + # SDK artefacts (AMD docs call this Step 1) 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", + # torch artefacts (AMD docs call this Step 2) wheels["torch"], wheels["torchvision"], wheels["torchaudio"], diff --git a/studio/setup.ps1 b/studio/setup.ps1 index f9b9eae11a..3500b3caf4 100644 --- a/studio/setup.ps1 +++ b/studio/setup.ps1 @@ -323,8 +323,11 @@ function Get-HipSdkVersion { # 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. +# require a two-step install: first the rocm_sdk_* wheels (~1.3 GB for +# 7.2.1; ~3.2 GB for 7.1.1) that ship the runtime torch links against, +# then torch itself (~780 MB for 7.2.1, ~692 MB for 7.1.1). Wheels are +# cp312 only. All 14 URLs in the map below were HEAD-verified live on +# 2026-04-11. function Get-RocmWheelUrls { param([Parameter(Mandatory = $true)]$Version) $base721 = 'https://repo.radeon.com/rocm/windows/rocm-rel-7.2.1/' @@ -1690,53 +1693,57 @@ if ($CuTag -eq "rocm") { substep "Re-create the venv with Python 3.12 from https://python.org if pip fails below." "Yellow" } - 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) { - & python -m pip install --no-cache-dir --force-reinstall ` - $RocmWheelUrls.SdkCore ` - $RocmWheelUrls.SdkDevel ` - $RocmWheelUrls.SdkLibraries ` - $RocmWheelUrls.SdkTarball - $sdkInstallExit = $LASTEXITCODE - $output = "" + substep ("installing Radeon ROCm SDK + PyTorch for rocm-rel-{0}.{1}.x from repo.radeon.com..." -f $RocmReleaseVersion.Major, $RocmReleaseVersion.Minor) + # 7.2.1 total is ~2.1 GB; 7.1.1 is ~3.9 GB (sdk_devel alone is 2.4 GB). + if ($RocmReleaseVersion.Major -eq 7 -and $RocmReleaseVersion.Minor -eq 1) { + substep "Downloading ~3.9 GB (7.1.1 sdk_devel is 2.4 GB -- may take a while)" } else { - $output = & python -m pip install --no-cache-dir --force-reinstall ` + substep "Downloading ~2.1 GB" + } + # setuptools and wheel are required because rocm-.tar.gz is a + # source distribution that pip builds with setuptools.build_meta. + # Ensure both are present in the venv before the install. + if ($script:UnslothVerbose) { + Fast-Install pip setuptools wheel + } else { + Fast-Install pip setuptools wheel | Out-Null + } + # Install all 7 Radeon artefacts in a SINGLE `python -m pip install` + # call. AMD's docs show a two-step install, but torch's metadata + # declares `Requires-Dist: rocm[libraries]==` which cascades to + # rocm-sdk-libraries-custom== -- a package that does NOT exist + # on PyPI. Splitting the install and using --force-reinstall on the + # torch step makes pip cascade-resolve through PyPI and fail. + # Combining into one command gives pip's resolver the full dep graph + # upfront. Use pip (NOT uv) because AMD validates pip, uv has known + # wheel-corruption issues on similar large ROCm wheels (#4966), and + # pip's default build-isolation handles the rocm-.tar.gz sdist. + if ($script:UnslothVerbose) { + & 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.SdkTarball ` $RocmWheelUrls.Torch ` $RocmWheelUrls.Torchvision ` $RocmWheelUrls.Torchaudio - $torchInstallExit = $LASTEXITCODE + $rocmInstallExit = $LASTEXITCODE $output = "" } else { $output = & python -m pip install --no-cache-dir --force-reinstall ` + $RocmWheelUrls.SdkCore ` + $RocmWheelUrls.SdkDevel ` + $RocmWheelUrls.SdkLibraries ` + $RocmWheelUrls.SdkTarball ` $RocmWheelUrls.Torch ` $RocmWheelUrls.Torchvision ` $RocmWheelUrls.Torchaudio | Out-String - $torchInstallExit = $LASTEXITCODE + $rocmInstallExit = $LASTEXITCODE } - if ($torchInstallExit -ne 0) { - Write-Host "[FAILED] PyTorch ROCm install failed (exit code $torchInstallExit)" -ForegroundColor Red + if ($rocmInstallExit -ne 0) { + Write-Host "[FAILED] ROCm SDK + PyTorch install failed (exit code $rocmInstallExit)" -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 } # Triton has no Windows ROCm build; skip the Triton-for-Windows step so