Enhance HVideoTool with background processing and device detection: implemented a background job system for detection and restoration tasks, updated the UI to display CUDA/CPU status, and improved device diagnostics. Documentation in README and CLAUDE.md reflects these changes.
This commit is contained in:
@@ -54,15 +54,20 @@ class YoloDetector(Detector):
|
||||
"(и PyTorch с CUDA отдельно — см. README)."
|
||||
) from exc
|
||||
|
||||
# Resolve the device: explicit override, else CUDA when available.
|
||||
# Resolve the device: CUDA only when actually available, else CPU. A CPU-only
|
||||
# torch build raises "Torch not compiled with CUDA enabled" if asked for cuda,
|
||||
# so we never request it without a working GPU (even on an explicit override).
|
||||
try:
|
||||
import torch
|
||||
|
||||
cuda_ok = torch.cuda.is_available()
|
||||
except Exception: # noqa: BLE001
|
||||
cuda_ok = False
|
||||
device = self.cfg.yolo_device
|
||||
if device is None:
|
||||
try:
|
||||
import torch
|
||||
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
except Exception: # noqa: BLE001
|
||||
device = "cpu"
|
||||
device = "cuda" if cuda_ok else "cpu"
|
||||
elif "cuda" in str(device) and not cuda_ok:
|
||||
device = "cpu"
|
||||
self._device = device
|
||||
self._model = YOLO(model_path)
|
||||
|
||||
|
||||
@@ -118,6 +118,14 @@ class DeepMosaicsRestorer(Restorer):
|
||||
return
|
||||
if str(_VENDOR) not in sys.path:
|
||||
sys.path.insert(0, str(_VENDOR)) # so vendored `from models/util import …` resolve
|
||||
|
||||
# Fall back to CPU when CUDA isn't available: DeepMosaics calls `.cuda()`
|
||||
# whenever gpu_id != "-1", which raises "Torch not compiled with CUDA enabled"
|
||||
# on a CPU-only torch build.
|
||||
import torch # noqa: E402
|
||||
if self._gpu != "-1" and not torch.cuda.is_available():
|
||||
self._gpu = "-1"
|
||||
|
||||
from models import loadmodel, runmodel # type: ignore # noqa: E402
|
||||
import util.image_processing as impro # type: ignore # noqa: E402
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
"""Probe the PyTorch / CUDA situation, so the UI can show a device badge.
|
||||
|
||||
Pure (no Qt). ``gather()`` imports torch (slow / heavy) — call it off the GUI
|
||||
thread. The rest are tiny formatters the UI uses to explain *why* it's on CPU and
|
||||
how to enable the GPU.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
# pip index for the CUDA build (matches the README).
|
||||
CUDA_WHEEL_INDEX = "https://download.pytorch.org/whl/cu121"
|
||||
|
||||
|
||||
def gather() -> dict:
|
||||
"""Collect torch/CUDA facts. Never raises — missing torch is a valid result."""
|
||||
info: dict = {
|
||||
"installed": False,
|
||||
"version": None, # torch.__version__ (e.g. "2.12.0+cpu")
|
||||
"built_cuda": None, # torch.version.cuda (None on a CPU-only build)
|
||||
"cuda_available": False,
|
||||
"device_name": None, # the active GPU's name, if any
|
||||
"import_error": None,
|
||||
}
|
||||
try:
|
||||
import torch
|
||||
except Exception as exc: # noqa: BLE001 - report any import failure, not just ImportError
|
||||
info["import_error"] = str(exc)
|
||||
return info
|
||||
info["installed"] = True
|
||||
info["version"] = getattr(torch, "__version__", None)
|
||||
try:
|
||||
info["built_cuda"] = torch.version.cuda
|
||||
except Exception: # noqa: BLE001
|
||||
info["built_cuda"] = None
|
||||
try:
|
||||
info["cuda_available"] = bool(torch.cuda.is_available())
|
||||
except Exception: # noqa: BLE001
|
||||
info["cuda_available"] = False
|
||||
if info["cuda_available"]:
|
||||
try:
|
||||
info["device_name"] = torch.cuda.get_device_name(0)
|
||||
except Exception: # noqa: BLE001
|
||||
info["device_name"] = None
|
||||
return info
|
||||
|
||||
|
||||
def device_label(info: dict) -> str:
|
||||
return "CUDA" if info.get("cuda_available") else "CPU"
|
||||
|
||||
|
||||
def reason(info: dict) -> str:
|
||||
"""One-sentence human explanation of the current device choice."""
|
||||
if not info.get("installed"):
|
||||
return ("PyTorch не установлен — детектор YOLO и восстановление DeepMosaics "
|
||||
"работают на CPU (классический детектор torch не требует).")
|
||||
if info.get("cuda_available"):
|
||||
name = info.get("device_name") or "GPU"
|
||||
return f"PyTorch использует CUDA: {name}. Вычисления идут на видеокарте."
|
||||
version = info.get("version") or "?"
|
||||
built = info.get("built_cuda")
|
||||
if not built:
|
||||
return (f"Установлена CPU-сборка PyTorch ({version}) — без поддержки CUDA, "
|
||||
"поэтому вычисления идут на процессоре (медленно).")
|
||||
return (f"PyTorch собран с CUDA {built} ({version}), но GPU недоступен: нет "
|
||||
"NVIDIA-видеокарты, не установлен/устарел драйвер, либо версия CUDA "
|
||||
"несовместима с драйвером.")
|
||||
|
||||
|
||||
def install_hint() -> str:
|
||||
"""Steps to enable the GPU (shown when running on CPU)."""
|
||||
return (
|
||||
"Как включить GPU (NVIDIA):\n"
|
||||
"1. Нужна видеокарта NVIDIA и свежий драйвер (проверка в консоли: nvidia-smi).\n"
|
||||
"2. Переустановите PyTorch со сборкой CUDA:\n\n"
|
||||
" pip uninstall -y torch torchvision\n"
|
||||
f" pip install torch torchvision --index-url {CUDA_WHEEL_INDEX}\n\n"
|
||||
"3. Перезапустите приложение.\n\n"
|
||||
"Классический детектор работает и без CUDA. На CPU детекция и расцензуривание "
|
||||
"просто медленнее."
|
||||
)
|
||||
Reference in New Issue
Block a user