mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-06-26 22:31:54 +03:00
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
* Implement per intel-gpu stats collection * Improve device naming * Improve GPU vendor handling * Cleanup
110 lines
3.6 KiB
Python
110 lines
3.6 KiB
Python
"""Resolve human-readable names for Intel GPUs via OpenVINO."""
|
|
|
|
import logging
|
|
import re
|
|
from typing import Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class IntelGpuNameResolver:
|
|
"""Build a pdev -> normalized device name map by enumerating OpenVINO GPUs.
|
|
|
|
The lookup is performed once on first access and cached for the process
|
|
lifetime. OpenVINO exposes DEVICE_PCI_INFO (domain/bus/device/function) and
|
|
FULL_DEVICE_NAME for each GPU it can see, which is enough to associate the
|
|
name with the pdev string used by DRM fdinfo.
|
|
"""
|
|
|
|
_names: Optional[dict[str, str]] = None
|
|
|
|
def get_names(self) -> dict[str, str]:
|
|
if self._names is not None:
|
|
return self._names
|
|
|
|
names: dict[str, str] = {}
|
|
|
|
try:
|
|
from openvino import Core
|
|
except ImportError:
|
|
logger.debug("OpenVINO unavailable; cannot resolve Intel GPU names")
|
|
self._names = names
|
|
return names
|
|
|
|
try:
|
|
core = Core()
|
|
devices = core.available_devices
|
|
except Exception as exc:
|
|
logger.debug(f"OpenVINO Core initialization failed: {exc}")
|
|
self._names = names
|
|
return names
|
|
|
|
cpu_name: Optional[str] = None
|
|
if "CPU" in devices:
|
|
try:
|
|
cpu_name = self._strip_trademarks(
|
|
core.get_property("CPU", "FULL_DEVICE_NAME")
|
|
)
|
|
except Exception as exc:
|
|
logger.debug(f"Failed to read CPU FULL_DEVICE_NAME: {exc}")
|
|
|
|
for device in devices:
|
|
if not device.startswith("GPU"):
|
|
continue
|
|
|
|
try:
|
|
pci = core.get_property(device, "DEVICE_PCI_INFO")
|
|
raw_name = core.get_property(device, "FULL_DEVICE_NAME")
|
|
device_type = core.get_property(device, "DEVICE_TYPE")
|
|
except Exception as exc:
|
|
logger.debug(f"Failed to read properties for {device}: {exc}")
|
|
continue
|
|
|
|
pdev = self._format_pdev(pci)
|
|
if not pdev:
|
|
continue
|
|
|
|
names[pdev] = self._resolve_name(raw_name, device_type, cpu_name)
|
|
|
|
self._names = names
|
|
return names
|
|
|
|
@staticmethod
|
|
def _format_pdev(pci) -> Optional[str]:
|
|
try:
|
|
return f"{pci.domain:04x}:{pci.bus:02x}:{pci.device:02x}.{pci.function:x}"
|
|
except AttributeError:
|
|
return None
|
|
|
|
@classmethod
|
|
def _resolve_name(cls, raw_name: str, device_type, cpu_name: Optional[str]) -> str:
|
|
"""Build a display name for a GPU.
|
|
|
|
Modern integrated Intel GPUs are reported by OpenVINO with a generic
|
|
FULL_DEVICE_NAME like "Intel(R) Graphics (iGPU)" that gives no model
|
|
information. Since the iGPU is part of the CPU on these platforms, fall
|
|
back to the CPU name (which OpenVINO does report specifically) and
|
|
suffix it with "iGPU" so it's clear what the entry is.
|
|
"""
|
|
is_integrated = "INTEGRATED" in str(device_type).upper()
|
|
|
|
if is_integrated and cpu_name:
|
|
short_cpu = re.sub(r"^Intel\s+", "", cpu_name)
|
|
return f"{short_cpu} iGPU"
|
|
|
|
return cls._normalize_name(raw_name)
|
|
|
|
@classmethod
|
|
def _normalize_name(cls, name: str) -> str:
|
|
cleaned = cls._strip_trademarks(name)
|
|
cleaned = re.sub(r"\s*\((?:i|d)GPU\)\s*$", "", cleaned, flags=re.IGNORECASE)
|
|
return " ".join(cleaned.split())
|
|
|
|
@staticmethod
|
|
def _strip_trademarks(name: str) -> str:
|
|
cleaned = re.sub(r"\(R\)|\(TM\)", "", name)
|
|
return " ".join(cleaned.split())
|
|
|
|
|
|
intel_gpu_name_resolver = IntelGpuNameResolver()
|