From 3d10bdc43c4c136dd3fa8a9e6cceddbb9a7e1df3 Mon Sep 17 00:00:00 2001 From: gkyle Date: Wed, 12 Nov 2025 10:33:26 -0800 Subject: [PATCH] support intel xpu --- pyproject.toml | 7 +++++++ src/enhance/lib/gpu.py | 37 +++++++++++++++++++++++++++++++++++-- src/setup/probeGPU.py | 13 +++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3f7fa5c..7f47464 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,11 @@ mps = [ "torch>=2.6.0", "torchvision", ] +xpu = [ + "torch>=2.6.0", + "torchvision", + "intel-extension-for-pytorch>=2.1.0", +] detect = [ # TODO: This feature is not enabled by default and the deps may require local compilation. # UV attempts to resolve all deps, including optionaly ones (https://github.com/astral-sh/uv/issues/6729). @@ -50,6 +55,7 @@ conflicts = [ { extra = "cu118" }, { extra = "cu126" }, { extra = "mps" }, + { extra = "xpu" }, ], ] @@ -61,6 +67,7 @@ torch = [ { index = "pytorch-cu124", extra = "cu126", marker = "platform_system == 'Windows'" }, { index = "pytorch-cu126", extra = "cu126", marker = "platform_system != 'Windows'" }, { index = "pytorch-cpu", extra = "mps" }, + { index = "pytorch-cpu", extra = "xpu" }, ] sam-2 = { git = "https://github.com/facebookresearch/sam2.git", rev = "c2ec8e14a185632b0a5d8b161928ceb50197eddc" } # For windows, prefer a prebuilt flash_attn wheel. https://huggingface.co/lldacing/flash-attention-windows-wheel/tree/main diff --git a/src/enhance/lib/gpu.py b/src/enhance/lib/gpu.py index 8368c20..2b2f59c 100644 --- a/src/enhance/lib/gpu.py +++ b/src/enhance/lib/gpu.py @@ -1,7 +1,13 @@ import torch import pynvml import psutil -from typing import List, Tuple +from typing import Tuple + +try: + import intel_extension_for_pytorch as ipex + IPEX_AVAILABLE = True +except ImportError: + IPEX_AVAILABLE = False class GPUInfo: @@ -16,6 +22,12 @@ def __init__(self): except Exception as e: self.mpsAvailable = False + try: + # Check for Intel XPU support + self.xpuAvailable = IPEX_AVAILABLE and hasattr(torch, 'xpu') and torch.xpu.is_available() + except (AttributeError, Exception) as e: + self.xpuAvailable = False + try: pynvml.nvmlInit() device_count = pynvml.nvmlDeviceGetCount() @@ -33,6 +45,11 @@ def getGpuNames(self): try: if self.mpsAvailable: return [["mps", "Apple Silicon GPU (MPS)"]] + if self.xpuAvailable: + return [ + [f"xpu:{i}", torch.xpu.get_device_name(i)] + for i in range(torch.xpu.device_count()) + ] if self.cudaAvailable: return [ [f"cuda:{i}", torch.cuda.get_device_name(i)] @@ -43,7 +60,7 @@ def getGpuNames(self): return [] def getGpuPresent(self): - return self.cudaAvailable or self.mpsAvailable + return self.cudaAvailable or self.mpsAvailable or self.xpuAvailable def getGpuMemory(self) -> Tuple[float, float]: # Return (total GB, available GB) try: @@ -51,6 +68,9 @@ def getGpuMemory(self) -> Tuple[float, float]: # Return (total GB, available GB total_bytes = psutil.virtual_memory().total free_bytes = psutil.virtual_memory().available return float(toGB(total_bytes)), float(toGB(free_bytes)) + if self.xpuAvailable: + free_bytes, total_bytes = torch.xpu.mem_get_info() + return float(toGB(total_bytes)), float(toGB(free_bytes)) if self.cudaAvailable: free_bytes, total_bytes = torch.cuda.mem_get_info() return float(toGB(total_bytes)), float(toGB(free_bytes)) @@ -63,6 +83,9 @@ def getGpuMemeoryTotal(self) -> float: if self.mpsAvailable: total_bytes = psutil.virtual_memory().total return float(toGB(total_bytes)) + if self.xpuAvailable: + free_bytes, total_bytes = torch.xpu.mem_get_info() + return float(toGB(total_bytes)) if self.cudaAvailable: free_bytes, total_bytes = torch.cuda.mem_get_info() return float(toGB(total_bytes)) @@ -75,6 +98,9 @@ def getGpuMemoryAvailable(self) -> float: if self.mpsAvailable: free_bytes = psutil.virtual_memory().available return float(toGB(free_bytes)) + if self.xpuAvailable: + free_bytes, total_bytes = torch.xpu.mem_get_info() + return float(toGB(free_bytes)) if self.cudaAvailable: free_bytes, total_bytes = torch.cuda.mem_get_info() return float(toGB(free_bytes)) @@ -86,6 +112,13 @@ def getGpuUtilization(self) -> float: try: if self.mpsAvailable: return None + if self.xpuAvailable and IPEX_AVAILABLE: + try: + xpu_utilization = ipex.xpu.get_device_utilization(0) / 100.0 + return xpu_utilization + except Exception as e: + pass + return None if self.cudaAvailable and self.nvmlHandle: gpu_utilization = pynvml.nvmlDeviceGetUtilizationRates(self.nvmlHandle).gpu / 100.0 return gpu_utilization diff --git a/src/setup/probeGPU.py b/src/setup/probeGPU.py index a2de3d8..95ca6a9 100644 --- a/src/setup/probeGPU.py +++ b/src/setup/probeGPU.py @@ -41,11 +41,24 @@ def has_mps_support(): pass return False + +def has_intel_gpu(): + """Check if Intel GPU is available.""" + try: + result = subprocess.run(['xpu-smi', 'discovery'], capture_output=True, text=True, timeout=5) + if result.returncode == 0 and 'Device' in result.stdout: + return True + except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired): + pass + return False if __name__ == "__main__": # First check for MPS on macOS if has_mps_support(): print("mps", end="") + # Check for Intel GPU + elif has_intel_gpu(): + print("xpu", end="") else: # Check for CUDA cuda_version = get_cuda_version()