Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -50,6 +55,7 @@ conflicts = [
{ extra = "cu118" },
{ extra = "cu126" },
{ extra = "mps" },
{ extra = "xpu" },
],
]

Expand All @@ -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
Expand Down
37 changes: 35 additions & 2 deletions src/enhance/lib/gpu.py
Original file line number Diff line number Diff line change
@@ -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:

Expand All @@ -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()
Expand All @@ -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)]
Expand All @@ -43,14 +60,17 @@ 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:
if self.mpsAvailable:
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))
Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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
Expand Down
13 changes: 13 additions & 0 deletions src/setup/probeGPU.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down