Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Daniel Han
e84b39dcde Keep V100 (Volta) GPUs on cu128 instead of cu130
cu130 dropped sm_70/sm_72; cap Volta GPUs to cu128 (last wheels shipping
sm_70) when a CUDA 13 driver is present. install.sh / install.ps1 /
setup.ps1 detect the min compute-cap; tests cover the Volta/Turing/Ampere/
Blackwell routing matrix.

Rebased onto current main (prior branch history was disconnected).
2026-07-20 23:46:20 -07:00
4 changed files with 89 additions and 3 deletions

View file

@ -2014,7 +2014,14 @@ exit 0
# Accept both spellings so we don't fall through to the cu126 default.
if ($output -match 'CUDA(?: UMD)? Version:\s+(\d+)\.(\d+)') {
$major = [int]$Matches[1]; $minor = [int]$Matches[2]
if ($major -ge 13) { return "$baseUrl/cu130" }
if ($major -ge 13) {
# cu130 dropped Volta (sm_70/sm_72); cap V100s to cu128.
$cap = (& $NvidiaSmiExe --query-gpu=compute_cap --format=csv,noheader 2>$null |
ForEach-Object { $_.Trim() } | Where-Object { $_ -match '^\d+\.\d+$' } |
Sort-Object { [version]$_ } | Select-Object -First 1)
if ($cap -eq '7.0' -or $cap -eq '7.2') { return "$baseUrl/cu128" }
return "$baseUrl/cu130"
}
if ($major -eq 12 -and $minor -ge 8) { return "$baseUrl/cu128" }
if ($major -eq 12 -and $minor -ge 6) { return "$baseUrl/cu126" }
if ($major -ge 12) { return "$baseUrl/cu124" }

View file

@ -2260,7 +2260,13 @@ get_torch_index_url() {
fi
_major=${_cuda_ver%%.*}
_minor=${_cuda_ver#*.}
if [ "$_major" -ge 13 ]; then echo "$_base/cu130"
if [ "$_major" -ge 13 ]; then
# cu130 dropped Volta (sm_70/sm_72). A CUDA 13 driver still runs V100s,
# so cap Volta GPUs to cu128 (last wheels shipping sm_70). awk picks the
# lowest compute capability across GPUs (no tr/sort/grep dependency).
_min_cap=$(LC_ALL=C $_smi --query-gpu=compute_cap --format=csv,noheader 2>/dev/null \
| awk '{gsub(/[ \r]/,"")} /^[0-9]+\.[0-9]+$/{split($0,a,"."); v=a[1]*100+a[2]; if(m==""||v<m){m=v;c=$0}} END{if(c!="")print c}')
case "$_min_cap" in 7.0|7.2) echo "$_base/cu128" ;; *) echo "$_base/cu130" ;; esac
elif [ "$_major" -eq 12 ] && [ "$_minor" -ge 8 ]; then echo "$_base/cu128"
elif [ "$_major" -eq 12 ] && [ "$_minor" -ge 6 ]; then echo "$_base/cu126"
elif [ "$_major" -ge 12 ]; then echo "$_base/cu124"

View file

@ -419,7 +419,14 @@ function Get-PytorchCudaTag {
$major = [int]$Matches[1]
$minor = [int]$Matches[2]
# PyTorch 2.10 offers: cu124, cu126, cu128, cu130
if ($major -ge 13) { return "cu130" }
if ($major -ge 13) {
# cu130 dropped Volta (sm_70/sm_72); cap V100s to cu128.
$cap = (& $smiExe --query-gpu=compute_cap --format=csv,noheader 2>$null |
ForEach-Object { $_.Trim() } | Where-Object { $_ -match '^\d+\.\d+$' } |
Sort-Object { [version]$_ } | Select-Object -First 1)
if ($cap -eq '7.0' -or $cap -eq '7.2') { return "cu128" }
return "cu130"
}
if ($major -eq 12 -and $minor -ge 8) { return "cu128" }
if ($major -eq 12 -and $minor -ge 6) { return "cu126" }
if ($major -ge 12) { return "cu124" }

View file

@ -90,6 +90,27 @@ MOCK
echo "$_dir"
}
# Helper: mock nvidia-smi that also answers --query-gpu=compute_cap, so we can
# exercise the Volta (sm_70/sm_72) cu130 -> cu128 cap. $1 = CUDA version,
# $2 = compute_cap output (one cap per line; may be empty/malformed).
make_mock_smi_caps() {
_dir=$(mktemp -d)
cat > "$_dir/nvidia-smi" <<MOCK
#!/bin/sh
case "\$*" in
*--query-gpu=compute_cap*) printf '%s\n' "$2" ;;
*)
case "\$1" in
-L) echo "GPU 0: NVIDIA Test GPU (UUID: GPU-fake-uuid)" ;;
*) echo "| NVIDIA-SMI 590.00 Driver Version: 590.00 CUDA Version: $1 |" ;;
esac
;;
esac
MOCK
chmod +x "$_dir/nvidia-smi"
echo "$_dir"
}
# Helper: create a mock amd-smi that prints a given ROCm version string
# Supports both "amd-smi version" and "amd-smi list" subcommands so that
# the GPU presence check (amd-smi list) also succeeds in tests.
@ -435,6 +456,51 @@ assert_eq "url override path slash trimmed, query kept" "https://mirror.example.
# 50) A #fragment ending in "/" is likewise preserved.
_result=$(UNSLOTH_TORCH_INDEX_URL="https://mirror.example.com/whl/cu128#anchor/" run_func "none")
assert_eq "url override preserves fragment slash" "https://mirror.example.com/whl/cu128#anchor/" "$_result"
# --- Volta (sm_70/sm_72) capped to cu128 on CUDA 13 (cu130 dropped sm_70) ------
# 51) CUDA 13.0 + Volta V100 (sm_70) -> cu128 (cu130 dropped sm_70)
_dir=$(make_mock_smi_caps "13.0" "7.0")
assert_eq "CUDA 13.0 + V100 (7.0) -> cu128" "https://download.pytorch.org/whl/cu128" "$(run_func "$_dir")"
rm -rf "$_dir"
# 52) CUDA 13.0 + Volta sm_72 -> cu128
_dir=$(make_mock_smi_caps "13.0" "7.2")
assert_eq "CUDA 13.0 + Volta (7.2) -> cu128" "https://download.pytorch.org/whl/cu128" "$(run_func "$_dir")"
rm -rf "$_dir"
# 53) CUDA 13.0 + Turing T4 (sm_75) -> cu130 (Turing is kept in cu130)
_dir=$(make_mock_smi_caps "13.0" "7.5")
assert_eq "CUDA 13.0 + T4 (7.5) -> cu130" "https://download.pytorch.org/whl/cu130" "$(run_func "$_dir")"
rm -rf "$_dir"
# 54) CUDA 13.0 + Ampere A100 (sm_80) -> cu130
_dir=$(make_mock_smi_caps "13.0" "8.0")
assert_eq "CUDA 13.0 + A100 (8.0) -> cu130" "https://download.pytorch.org/whl/cu130" "$(run_func "$_dir")"
rm -rf "$_dir"
# 55) CUDA 13.0 + Blackwell B200 (sm_100) -> cu130
_dir=$(make_mock_smi_caps "13.0" "10.0")
assert_eq "CUDA 13.0 + B200 (10.0) -> cu130" "https://download.pytorch.org/whl/cu130" "$(run_func "$_dir")"
rm -rf "$_dir"
# 56) CUDA 13.0 + mixed V100 + B200 -> cu128 (min cap is Volta)
_dir=$(make_mock_smi_caps "13.0" "$(printf '10.0\n7.0')")
assert_eq "CUDA 13.0 + mixed V100+B200 -> cu128" "https://download.pytorch.org/whl/cu128" "$(run_func "$_dir")"
rm -rf "$_dir"
# 57) CUDA 13.1 + V100 -> cu128 (any CUDA 13.x with Volta)
_dir=$(make_mock_smi_caps "13.1" "7.0")
assert_eq "CUDA 13.1 + V100 -> cu128" "https://download.pytorch.org/whl/cu128" "$(run_func "$_dir")"
rm -rf "$_dir"
# 58) CUDA 12.8 + V100 -> cu128 (12.x already ships sm_70; cap path not taken)
_dir=$(make_mock_smi_caps "12.8" "7.0")
assert_eq "CUDA 12.8 + V100 -> cu128" "https://download.pytorch.org/whl/cu128" "$(run_func "$_dir")"
rm -rf "$_dir"
# 59) CUDA 13.0 + empty compute_cap (query unsupported) -> cu130 (safe fallback)
_dir=$(make_mock_smi_caps "13.0" "")
assert_eq "CUDA 13.0 + empty cap -> cu130" "https://download.pytorch.org/whl/cu130" "$(run_func "$_dir")"
rm -rf "$_dir"
rm -f "$_FUNC_FILE"
rm -rf "$_FAKE_SMI_DIR"