Skip to content

Commit 45cc49e

Browse files
committed
Merge commit '7d45c7894adff3213cc15175278f5669e92908dd' into pr-7706-xplat-ci
2 parents aa4ea75 + 7d45c78 commit 45cc49e

2 files changed

Lines changed: 94 additions & 3 deletions

File tree

install.ps1

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ function Install-UnslothStudio {
112112
if ([string]::IsNullOrWhiteSpace($TorchIndexUrl)) { return "none" }
113113
# Drop query/fragment first so a token-authenticated pin classifies by family.
114114
$leaf = (($TorchIndexUrl -split '[?#]', 2)[0].TrimEnd('/') -split '/')[-1].ToLowerInvariant()
115-
if (@("cpu", "cu118", "cu124", "cu126", "cu128", "cu130") -contains $leaf) { return $leaf }
115+
if (@("cpu", "xpu", "cu118", "cu124", "cu126", "cu128", "cu130") -contains $leaf) { return $leaf }
116116
if ($leaf -match '^rocm[0-9]+\.[0-9]+$') { return $leaf }
117117
return "auto"
118118
}
@@ -123,6 +123,7 @@ function Install-UnslothStudio {
123123
# Require a digit after "cu" so /current or /custom isn't branded CUDA (parity ^cu[0-9]).
124124
if ($TorchIndexFamily -match '^cu[0-9]') { return "cuda" }
125125
if ($TorchIndexFamily -like "rocm*") { return "rocm" }
126+
if ($TorchIndexFamily -eq "xpu") { return "xpu" }
126127
if ($TorchIndexFamily -eq "cpu") { return "cpu" }
127128
return "unknown"
128129
}
@@ -2222,8 +2223,50 @@ exit 0
22222223
substep "UNSLOTH_ROCM_GFX_ARCH to enable GPU ROCm PyTorch:" "Yellow"
22232224
substep "https://rocm.docs.amd.com/en/latest/deploy/windows/index.html" "Yellow"
22242225
} else {
2225-
step "gpu" "none (chat-only / GGUF)" "Yellow"
2226-
substep "Training and GPU inference require an NVIDIA or AMD ROCm GPU." "Yellow"
2226+
# ── Intel GPU detection (Arc / Data Center GPU Max / Flex) ──
2227+
# PyTorch publishes XPU (SYCL) wheels at download.pytorch.org/whl/xpu that ship
2228+
# their own oneAPI runtime. Windows also needs the Intel GPU driver (and Unsloth
2229+
# additionally documents oneAPI + Level Zero), so an Intel adapter alone is not
2230+
# proof of a usable XPU: $HasIntelGpu is "an Intel GPU is present",
2231+
# $script:IsIntelXpu is "XPU wheels are appropriate for it".
2232+
# Get-CimInstance, not Get-WmiObject: the latter does not exist in PowerShell 7.
2233+
# Only Arc / Data Center parts are XPU-capable; UHD / HD / Iris Xe are not.
2234+
$HasIntelGpu = $false
2235+
$IntelGpuLabel = $null
2236+
try {
2237+
$intelGpus = @(Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue |
2238+
Where-Object { $_.Name -match "(?i)Intel" })
2239+
if ($intelGpus.Count -gt 0) {
2240+
$HasIntelGpu = $true
2241+
$xpuGpu = $intelGpus | Where-Object { $_.Name -match "(?i)Intel.*(Arc|Data Center GPU)" } | Select-Object -First 1
2242+
$IntelGpuLabel = if ($xpuGpu) { $xpuGpu.Name } else { $intelGpus[0].Name }
2243+
if ($xpuGpu) { $script:IsIntelXpu = $true }
2244+
}
2245+
} catch {}
2246+
# torch.xpu.is_available() is authoritative when torch is already installed
2247+
# (migrated env), so let it both confirm and veto the name match above.
2248+
if (Test-Path -LiteralPath $VenvPython) {
2249+
try {
2250+
$xpuCheck = & $VenvPython -c "import torch; print(torch.xpu.is_available())" 2>$null | Out-String
2251+
if ($xpuCheck.Trim() -eq 'True') {
2252+
$HasIntelGpu = $true
2253+
$script:IsIntelXpu = $true
2254+
if (-not $IntelGpuLabel) { $IntelGpuLabel = "Intel GPU (detected by PyTorch XPU)" }
2255+
} elseif ($xpuCheck.Trim() -eq 'False') {
2256+
$script:IsIntelXpu = $false
2257+
}
2258+
} catch {}
2259+
}
2260+
if ($script:IsIntelXpu) {
2261+
step "gpu" "Intel GPU detected" "Green"
2262+
substep "$IntelGpuLabel"
2263+
# The wheel-index message lives with the reroute below: only that point
2264+
# knows whether a pin or --no-torch overrode XPU, and the real mirror URL.
2265+
} else {
2266+
step "gpu" "none (chat-only / GGUF)" "Yellow"
2267+
if ($HasIntelGpu) { substep "Detected: $IntelGpuLabel (not XPU-capable)" "Yellow" }
2268+
substep "Training and GPU inference require an NVIDIA, AMD ROCm, or Intel Arc GPU." "Yellow"
2269+
}
22272270
}
22282271
# On an AMD GPU (no NVIDIA), surface the optional WSL-ROCm driver hint.
22292272
if (-not $HasNvidiaSmi -and ($ROCmGfxArch -or $ROCmGpuLabel)) { Show-AmdWslDriverHint }
@@ -2240,6 +2283,14 @@ exit 0
22402283
return $value.Substring(0, $idx).TrimEnd('/') + $value.Substring($idx)
22412284
}
22422285

2286+
# Index leaf (cpu / cu128 / xpu / gfx1201), query and fragment stripped so a
2287+
# token-authenticated mirror still classifies by family. Shared by the callers below.
2288+
function Get-TorchIndexLeafName {
2289+
param([string]$Url)
2290+
if ([string]::IsNullOrWhiteSpace($Url)) { return "" }
2291+
return ((($Url -split '[?#]', 2)[0].TrimEnd('/') -split '/')[-1]).ToLowerInvariant()
2292+
}
2293+
22432294
# ── Choose the correct PyTorch index URL based on driver CUDA version ──
22442295
# Mirrors Get-PytorchCudaTag in setup.ps1.
22452296
function Get-TorchIndexUrl {
@@ -2302,6 +2353,7 @@ exit 0
23022353
if (-not $TorchVersion) { return $null }
23032354
if ($TorchVersion -match '\+(cu\d+)') { return $Matches[1] }
23042355
if ($TorchVersion -match '\+rocm') { return 'rocm' }
2356+
if ($TorchVersion -match '\+xpu') { return 'xpu' }
23052357
if ($TorchVersion -match '\+cpu') { return 'cpu' }
23062358
return 'cpu'
23072359
}
@@ -2316,6 +2368,7 @@ exit 0
23162368
$leaf = (($TorchIndexUrl -split '[?#]', 2)[0].TrimEnd('/') -split '/')[-1].ToLowerInvariant()
23172369
if ($leaf -match '^cu\d+$') { return $leaf }
23182370
if ($leaf -eq 'cpu') { return 'cpu' }
2371+
if ($leaf -eq 'xpu') { return 'xpu' }
23192372
if ($leaf -match '^rocm') { return 'rocm' }
23202373
# gfx must be followed by a digit (an architecture leaf); gfx-private is custom.
23212374
if ($leaf -match '^gfx[0-9]') { return 'rocm' }
@@ -2359,6 +2412,14 @@ exit 0
23592412
(-not [string]::IsNullOrWhiteSpace($env:UNSLOTH_TORCH_INDEX_FAMILY))
23602413
$TorchIndexUrl = Get-TorchIndexUrl
23612414

2415+
# Intel XPU reroute. Must run AFTER Get-TorchIndexUrl or it would be overwritten;
2416+
# an explicit pin still wins, exactly like the AMD ROCm reroute below.
2417+
if ($script:IsIntelXpu -and -not $TorchIndexPinned -and -not $SkipTorch) {
2418+
$XpuBaseUrl = if ($env:UNSLOTH_PYTORCH_MIRROR) { $env:UNSLOTH_PYTORCH_MIRROR.TrimEnd('/') } else { "https://download.pytorch.org/whl" }
2419+
$TorchIndexUrl = "$XpuBaseUrl/xpu"
2420+
substep "PyTorch XPU (SYCL) wheels will be installed from $(Remove-IndexUrlCredentials $TorchIndexUrl)"
2421+
}
2422+
23622423
# ── GPU arch → newest compatible Windows ROCm wheel release ──
23632424
# Wheels bundle their own ROCm runtime; the installed HIP SDK version does
23642425
# not constrain which release to use. Always picks the newest release that
@@ -2476,6 +2537,10 @@ exit 0
24762537
} elseif ($ROCmGpuLabel) {
24772538
substep "Installing CPU-only PyTorch (AMD GPU arch unknown -- install the HIP SDK" "Yellow"
24782539
substep "or set UNSLOTH_ROCM_GFX_ARCH to enable GPU ROCm)." "Yellow"
2540+
} elseif ($HasIntelGpu -and -not $script:IsIntelXpu) {
2541+
substep "Intel GPU detected but not XPU-capable. Installing CPU-only PyTorch." "Yellow"
2542+
substep "PyTorch XPU needs Intel Arc or Data Center GPU plus a current driver." "Yellow"
2543+
substep "See: https://unsloth.ai/docs/get-started/install/intel" "Yellow"
24792544
} else {
24802545
substep "No NVIDIA GPU detected." "Yellow"
24812546
}
@@ -2590,6 +2655,30 @@ exit 0
25902655
$ROCmIndexUrl = $null
25912656
$ROCmTorchFloor = $null
25922657
}
2658+
} elseif ($script:IsIntelXpu -and (Get-TorchIndexLeafName $TorchIndexUrl) -eq "xpu") {
2659+
# ── Intel Arc / XPU PyTorch install ──
2660+
# XPU wheels ship their own oneAPI runtime (intel-sycl-rt et al.) and
2661+
# are published at https://download.pytorch.org/whl/xpu under PEP 503.
2662+
Write-TauriLog "STEP" "Installing PyTorch (Intel XPU)"
2663+
substep "installing PyTorch from $(Remove-IndexUrlCredentials $TorchIndexUrl)..."
2664+
# Bound the trio exactly like every other index: the XPU index serves torch
2665+
# past Unsloth's ceiling (2.13.0), and torchaudio dropped its exact torch pin,
2666+
# so bare names resolve a mismatched pair and drag unsloth back to an old release.
2667+
$torchInstallExit = Invoke-InstallCommandRetry -Label "install PyTorch (Intel XPU)" { uv pip install --python $VenvPython --force-reinstall "torch>=2.4,<2.11.0" "torchvision>=0.19,<0.26.0" "torchaudio>=2.4,<2.11.0" --default-index $TorchIndexUrl }
2668+
if ($torchInstallExit -ne 0) {
2669+
# Transient XPU-index failure: fall back to CPU base.
2670+
$CpuFallbackIndexUrl = if ($env:UNSLOTH_PYTORCH_MIRROR) { "$($env:UNSLOTH_PYTORCH_MIRROR.TrimEnd('/'))/cpu" } else { "https://download.pytorch.org/whl/cpu" }
2671+
substep "XPU PyTorch install failed (exit $torchInstallExit); using a CPU base." "Yellow"
2672+
$torchInstallExit = Invoke-InstallCommandRetry -Label "install PyTorch (CPU fallback)" { uv pip install --python $VenvPython --force-reinstall "torch>=2.4,<2.11.0" "torchvision>=0.19,<0.26.0" "torchaudio>=2.4,<2.11.0" --default-index $CpuFallbackIndexUrl }
2673+
if ($torchInstallExit -ne 0) {
2674+
Write-Host "[ERROR] Failed to install PyTorch (XPU and CPU base both failed, exit code $torchInstallExit)" -ForegroundColor Red
2675+
return (Exit-InstallFailure "Failed to install PyTorch (exit code $torchInstallExit)" $torchInstallExit)
2676+
}
2677+
# CPU base is in; drop the XPU expectation so the flavor-repair block
2678+
# below won't retry the index that just failed (mirrors the ROCm path).
2679+
$script:IsIntelXpu = $false
2680+
$TorchIndexUrl = $CpuFallbackIndexUrl
2681+
}
25932682
} else {
25942683
Write-TauriLog "STEP" "Installing PyTorch"
25952684
# Windows on ARM lacks only torchaudio (whl/cpu win_arm64: torch 42,

install.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ _tauri_torch_index_family() {
487487
*/cu128) echo "cu128" ;;
488488
*/cu130) echo "cu130" ;;
489489
*/cpu) echo "cpu" ;;
490+
*/xpu) echo "xpu" ;;
490491
*/rocm[0-9]*.[0-9]*)
491492
_diag_family=${_diag_url##*/}
492493
case "$_diag_family" in
@@ -522,6 +523,7 @@ _tauri_gpu_branch() {
522523
echo "rocm"
523524
fi ;;
524525
radeon) echo "rocm_radeon" ;;
526+
xpu) echo "xpu" ;;
525527
cpu) echo "cpu" ;;
526528
none) echo "no_torch" ;;
527529
*) echo "unknown" ;;

0 commit comments

Comments
 (0)