Fix Windows memory budget detection
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""GPU hardware detection with graceful CPU fallback."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
@@ -12,7 +13,96 @@ def _detect_ram_mb() -> int:
|
||||
page_size = os.sysconf("SC_PAGE_SIZE")
|
||||
return int((pages * page_size) // (1024 * 1024))
|
||||
except (AttributeError, OSError, ValueError):
|
||||
return 0
|
||||
pass
|
||||
return _detect_windows_ram_mb()
|
||||
|
||||
|
||||
def _detect_windows_ram_mb() -> int:
|
||||
"""Return Windows physical RAM in MB, or 0."""
|
||||
try:
|
||||
import ctypes
|
||||
|
||||
class _MemoryStatusEx(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("dwLength", ctypes.c_ulong),
|
||||
("dwMemoryLoad", ctypes.c_ulong),
|
||||
("ullTotalPhys", ctypes.c_ulonglong),
|
||||
("ullAvailPhys", ctypes.c_ulonglong),
|
||||
("ullTotalPageFile", ctypes.c_ulonglong),
|
||||
("ullAvailPageFile", ctypes.c_ulonglong),
|
||||
("ullTotalVirtual", ctypes.c_ulonglong),
|
||||
("ullAvailVirtual", ctypes.c_ulonglong),
|
||||
("ullAvailExtendedVirtual", ctypes.c_ulonglong),
|
||||
]
|
||||
|
||||
status = _MemoryStatusEx()
|
||||
status.dwLength = ctypes.sizeof(_MemoryStatusEx)
|
||||
if ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(status)):
|
||||
return int(status.ullTotalPhys // (1024 * 1024))
|
||||
except (AttributeError, OSError, ValueError):
|
||||
pass
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[
|
||||
"powershell",
|
||||
"-NoProfile",
|
||||
"-Command",
|
||||
"(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
)
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
return int(result.stdout.strip()) // (1024 * 1024)
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired, ValueError):
|
||||
pass
|
||||
return 0
|
||||
|
||||
|
||||
def _detect_windows_gpu_memory() -> dict | None:
|
||||
"""Return Windows GPU memory metadata from Win32_VideoController, if available."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[
|
||||
"powershell",
|
||||
"-NoProfile",
|
||||
"-Command",
|
||||
(
|
||||
"Get-CimInstance Win32_VideoController | "
|
||||
"Select-Object Name,AdapterRAM | ConvertTo-Json -Compress"
|
||||
),
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
)
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired):
|
||||
return None
|
||||
|
||||
if result.returncode != 0 or not result.stdout.strip():
|
||||
return None
|
||||
try:
|
||||
raw = json.loads(result.stdout)
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
entries = raw if isinstance(raw, list) else [raw]
|
||||
best: dict | None = None
|
||||
for entry in entries:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
name = str(entry.get("Name") or "").strip()
|
||||
if not name:
|
||||
continue
|
||||
try:
|
||||
adapter_ram = int(entry.get("AdapterRAM") or 0)
|
||||
except (TypeError, ValueError):
|
||||
adapter_ram = 0
|
||||
vram_mb = max(0, adapter_ram // (1024 * 1024))
|
||||
if best is None or vram_mb > best["vram_mb"]:
|
||||
best = {"gpu_name": name, "vram_mb": vram_mb}
|
||||
return best
|
||||
|
||||
|
||||
def detect_hardware() -> dict:
|
||||
@@ -25,7 +115,15 @@ def detect_hardware() -> dict:
|
||||
name = torch.cuda.get_device_name(idx)
|
||||
props = torch.cuda.get_device_properties(idx)
|
||||
vram_mb = props.total_memory // (1024 * 1024)
|
||||
return {"device": "cuda", "gpu_name": name, "vram_mb": vram_mb, "ram_mb": ram_mb}
|
||||
shared_vram_mb = max(0, ram_mb // 2)
|
||||
return {
|
||||
"device": "cuda",
|
||||
"gpu_name": name,
|
||||
"vram_mb": vram_mb,
|
||||
"dedicated_vram_mb": vram_mb,
|
||||
"shared_vram_mb": shared_vram_mb,
|
||||
"ram_mb": ram_mb,
|
||||
}
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -39,11 +137,37 @@ def detect_hardware() -> dict:
|
||||
parts = line.split(",", 1)
|
||||
gpu_name = parts[0].strip()
|
||||
vram_mb = int(parts[1].strip()) if len(parts) > 1 else 0
|
||||
return {"device": "cuda", "gpu_name": gpu_name, "vram_mb": vram_mb, "ram_mb": ram_mb}
|
||||
shared_vram_mb = max(0, ram_mb // 2)
|
||||
return {
|
||||
"device": "cuda",
|
||||
"gpu_name": gpu_name,
|
||||
"vram_mb": vram_mb,
|
||||
"dedicated_vram_mb": vram_mb,
|
||||
"shared_vram_mb": shared_vram_mb,
|
||||
"ram_mb": ram_mb,
|
||||
}
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired, ValueError, IndexError):
|
||||
pass
|
||||
|
||||
return {"device": "cpu", "gpu_name": None, "vram_mb": 0, "ram_mb": ram_mb}
|
||||
windows_gpu = _detect_windows_gpu_memory()
|
||||
if windows_gpu is not None:
|
||||
return {
|
||||
"device": "cpu",
|
||||
"gpu_name": windows_gpu["gpu_name"],
|
||||
"vram_mb": windows_gpu["vram_mb"],
|
||||
"dedicated_vram_mb": windows_gpu["vram_mb"],
|
||||
"shared_vram_mb": max(0, ram_mb // 2),
|
||||
"ram_mb": ram_mb,
|
||||
}
|
||||
|
||||
return {
|
||||
"device": "cpu",
|
||||
"gpu_name": None,
|
||||
"vram_mb": 0,
|
||||
"dedicated_vram_mb": 0,
|
||||
"shared_vram_mb": 0,
|
||||
"ram_mb": ram_mb,
|
||||
}
|
||||
|
||||
|
||||
def benchmark_throughput(device_str: str = "cpu") -> float:
|
||||
|
||||
Reference in New Issue
Block a user