mirror of
https://github.com/forkless/XPUSYS-Monitor-NG.git
synced 2026-08-16 00:46:37 +02:00
174 lines
6.1 KiB
Python
174 lines
6.1 KiB
Python
"""
|
|
providers/__init__.py — Provider registry and auto-detection factory.
|
|
|
|
Usage:
|
|
from .providers import auto_detect_provider, BaseGPUProvider, GPUSnapshot
|
|
|
|
provider = auto_detect_provider(interval_ms=1000)
|
|
snap = provider.get_snapshot()
|
|
|
|
Detection strategy — align with ComfyUI's own device selection:
|
|
ComfyUI uses torch.cuda.is_available() for NVIDIA and torch.xpu.is_available()
|
|
for Intel. We follow the same signals so the monitor always tracks whichever
|
|
device ComfyUI is actually running on.
|
|
|
|
Detection order:
|
|
1. torch.cuda.is_available() + torch.version.roc → AMDProvider (ROCm)
|
|
2. torch.cuda.is_available() → NvidiaProvider (NVIDIA)
|
|
3. torch.xpu.is_available() → IntelProvider (Intel Arc)
|
|
4. ze_loader.dll present → IntelProvider (fallback)
|
|
5. pynvml available → NvidiaProvider (fallback)
|
|
6. Last resort → IntelProvider (limited)
|
|
|
|
Fallback tiers 4-5 cover edge cases where torch is not yet imported or the
|
|
user is running a non-standard environment without torch.
|
|
"""
|
|
|
|
import logging
|
|
from .base import BaseGPUProvider, GPUSnapshot
|
|
|
|
logger = logging.getLogger("XPUSYSMonitor")
|
|
|
|
|
|
def auto_detect_provider(interval_ms: int = 1000) -> BaseGPUProvider:
|
|
"""
|
|
Detect the available GPU hardware and return the appropriate provider.
|
|
|
|
Primary strategy: mirror ComfyUI's own torch-based device selection so the
|
|
monitor always tracks the same device that ComfyUI is running inference on.
|
|
Fallback strategy: raw driver/library probing for non-standard environments.
|
|
"""
|
|
|
|
# --- Primary: follow torch (mirrors ComfyUI model_management.py) ---
|
|
if _detect_nvidia_torch():
|
|
# torch.cuda available — determine if NVIDIA or AMD via torch.version.roc
|
|
if _is_amd_rocme():
|
|
# torch.version.roc is not None → AMD ROCm
|
|
logger.info("XPUSYSMonitor: torch.cuda + ROCm — using AMDProvider.")
|
|
from .amd import AMDProvider
|
|
return AMDProvider(interval_ms=interval_ms)
|
|
else:
|
|
# torch.version.roc is None → NVIDIA
|
|
logger.info("XPUSYSMonitor: torch.cuda (NVIDIA) — using NvidiaProvider.")
|
|
from .nvidia import NvidiaProvider
|
|
return NvidiaProvider(interval_ms=interval_ms)
|
|
|
|
if _detect_intel_torch():
|
|
logger.info("XPUSYSMonitor: torch.xpu available — using IntelProvider.")
|
|
from .intel import IntelProvider
|
|
return IntelProvider(interval_ms=interval_ms)
|
|
|
|
# --- Fallback: raw driver probing (torch not imported yet / non-std env) ---
|
|
if _detect_intel_driver():
|
|
logger.info(
|
|
"XPUSYSMonitor: ze_loader.dll found (torch unavailable) — "
|
|
"using IntelProvider."
|
|
)
|
|
from .intel import IntelProvider
|
|
return IntelProvider(interval_ms=interval_ms)
|
|
|
|
if _detect_nvidia_driver():
|
|
logger.info(
|
|
"XPUSYSMonitor: NVIDIA driver found (torch unavailable) — "
|
|
"using NvidiaProvider."
|
|
)
|
|
from .nvidia import NvidiaProvider
|
|
return NvidiaProvider(interval_ms=interval_ms)
|
|
|
|
# --- Last resort ---
|
|
logger.warning(
|
|
"XPUSYSMonitor: no supported GPU detected — "
|
|
"falling back to IntelProvider (limited functionality)."
|
|
)
|
|
from .intel import IntelProvider
|
|
return IntelProvider(interval_ms=interval_ms)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Primary detectors — torch-based (align with ComfyUI)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def _detect_nvidia_torch() -> bool:
|
|
"""Return True if torch has a working CUDA backend (mirrors ComfyUI)."""
|
|
try:
|
|
import torch
|
|
return torch.cuda.is_available()
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def _detect_intel_torch() -> bool:
|
|
"""Return True if torch has a working XPU backend (mirrors ComfyUI)."""
|
|
try:
|
|
import torch
|
|
return torch.xpu.is_available()
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Fallback detectors — raw driver / library probing
|
|
# Used when torch is not yet available or in non-standard environments.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def _detect_intel_driver() -> bool:
|
|
"""Return True if Intel Level Zero runtime (ze_loader.dll) is present."""
|
|
import ctypes
|
|
try:
|
|
ctypes.WinDLL("ze_loader.dll")
|
|
return True
|
|
except OSError:
|
|
return False
|
|
|
|
|
|
def _detect_nvidia_driver() -> bool:
|
|
"""Return True if pynvml is installed and NVIDIA driver is reachable."""
|
|
try:
|
|
import pynvml
|
|
pynvml.nvmlInit()
|
|
count = pynvml.nvmlDeviceGetCount()
|
|
pynvml.nvmlShutdown()
|
|
return count > 0
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def _is_amd_rocme() -> bool:
|
|
"""
|
|
Check if torch.cuda is backed by AMD ROCm.
|
|
|
|
Primary signal: torch.version.roc is set (AMD ROCm PyTorch).
|
|
Secondary signal: torch.version.hip is set (HIP backend).
|
|
Fallback signal: GPU device name contains AMD/Radeon markers
|
|
(catches Windows ROCm builds that don't set version.roc).
|
|
|
|
Uses getattr() so missing attributes are handled cleanly
|
|
without raising AttributeError (some Windows ROCm builds
|
|
lack the `roc` attribute entirely).
|
|
|
|
Returns False for NVIDIA or standard CUDA.
|
|
"""
|
|
try:
|
|
import torch
|
|
# Primary: ROCm version string (may not exist on some Windows ROCm builds)
|
|
if getattr(torch.version, 'roc', None) is not None:
|
|
return True
|
|
# Secondary: HIP version string (alternative ROCm signal)
|
|
if getattr(torch.version, 'hip', None) is not None:
|
|
return True
|
|
# Fallback: check GPU name for AMD identifiers
|
|
name = torch.cuda.get_device_name(0).lower()
|
|
for marker in ["amd", "radeon", "advanced micro devices"]:
|
|
if marker in name:
|
|
return True
|
|
return False
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
__all__ = [
|
|
"BaseGPUProvider",
|
|
"GPUSnapshot",
|
|
"auto_detect_provider",
|
|
]
|