Spaces:
Running
Running
import platform | |
import subprocess | |
import os | |
import logging | |
from typing import Dict, Optional | |
# Configure logging | |
logger = logging.getLogger(__name__) | |
class HardwareDetector: | |
def __init__(self): | |
logger.info("Initializing HardwareDetector") | |
try: | |
self.specs = self._detect_system_specs() | |
logger.info("Hardware detection completed successfully") | |
logger.debug(f"Detected specs: {self.specs}") | |
except Exception as e: | |
logger.error(f"Failed to detect hardware specs: {e}") | |
raise | |
def _detect_system_specs(self) -> Dict: | |
"""Detect system hardware specifications automatically.""" | |
logger.debug("Starting system hardware detection") | |
platform_info = platform.system() | |
architecture = platform.machine() | |
cpu_count = os.cpu_count() | |
python_version = platform.python_version() | |
logger.debug(f"Platform: {platform_info}, Architecture: {architecture}") | |
logger.debug(f"CPU cores: {cpu_count}, Python: {python_version}") | |
gpu_info = self._detect_gpu() | |
specs = { | |
'platform': platform_info, | |
'architecture': architecture, | |
'cpu_count': cpu_count, | |
'python_version': python_version, | |
'gpu_info': gpu_info, | |
'cuda_available': False, | |
'mps_available': False | |
} | |
# Check for PyTorch and device availability | |
logger.debug("Checking PyTorch availability") | |
try: | |
import torch | |
torch_version = torch.__version__ | |
cuda_available = torch.cuda.is_available() | |
mps_available = torch.backends.mps.is_available() | |
logger.info(f"PyTorch {torch_version} detected") | |
logger.debug(f"CUDA available: {cuda_available}, MPS available: {mps_available}") | |
specs['torch_version'] = torch_version | |
specs['cuda_available'] = cuda_available | |
specs['mps_available'] = mps_available | |
if cuda_available: | |
device_count = torch.cuda.device_count() | |
device_name = torch.cuda.get_device_name(0) | |
device_memory = torch.cuda.get_device_properties(0).total_memory // (1024**3) | |
logger.info(f"CUDA devices: {device_count}, Primary: {device_name} ({device_memory}GB)") | |
specs['cuda_device_count'] = device_count | |
specs['cuda_device_name'] = device_name | |
specs['cuda_memory'] = device_memory | |
except ImportError as e: | |
logger.warning(f"PyTorch not installed: {e}") | |
specs['torch_version'] = 'Not installed' | |
return specs | |
def _detect_gpu(self) -> Optional[Dict]: | |
"""Attempt to detect GPU information using nvidia-smi.""" | |
logger.debug("Attempting GPU detection via nvidia-smi") | |
try: | |
result = subprocess.run([ | |
'nvidia-smi', | |
'--query-gpu=name,memory.total', | |
'--format=csv,noheader,nounits' | |
], capture_output=True, text=True, check=True) | |
logger.debug(f"nvidia-smi output: {result.stdout}") | |
lines = result.stdout.strip().split('\n') | |
gpus = [] | |
logger.debug(f"Found {len(lines)} GPU entries") | |
for line in lines: | |
if line.strip(): | |
try: | |
name, memory = line.split(', ') | |
gpu_entry = {'name': name.strip(), 'memory_mb': int(memory)} | |
gpus.append(gpu_entry) | |
logger.debug(f"Parsed GPU: {gpu_entry}") | |
except ValueError as e: | |
logger.warning(f"Failed to parse GPU line '{line}': {e}") | |
logger.info(f"Successfully detected {len(gpus)} GPUs") | |
return gpus | |
except subprocess.CalledProcessError as e: | |
logger.warning(f"nvidia-smi command failed: {e}") | |
return None | |
except FileNotFoundError: | |
logger.debug("nvidia-smi not found, no NVIDIA GPU detected") | |
return None | |
except Exception as e: | |
logger.error(f"Unexpected error during GPU detection: {e}") | |
return None | |
def get_manual_input(self) -> Dict: | |
"""Get hardware specifications via manual user input.""" | |
logger.info("Starting manual hardware input") | |
print("Enter your hardware specifications manually:") | |
gpu_name = input("GPU Name (e.g., RTX 4090, A100, leave empty if none): ").strip() | |
logger.debug(f"User input GPU name: '{gpu_name}'") | |
if gpu_name: | |
try: | |
vram_gb = int(input("VRAM in GB (e.g., 24): ")) | |
gpu_info = [{'name': gpu_name, 'memory_mb': vram_gb * 1024}] | |
logger.info(f"Manual GPU configured: {gpu_name} with {vram_gb}GB VRAM") | |
except ValueError as e: | |
logger.warning(f"Invalid VRAM input: {e}") | |
gpu_info = None | |
else: | |
gpu_info = None | |
logger.info("No GPU specified in manual input") | |
try: | |
ram_gb = int(input("System RAM in GB (e.g., 32): ")) | |
logger.debug(f"User input RAM: {ram_gb}GB") | |
except ValueError as e: | |
logger.warning(f"Invalid RAM input: {e}, using default 16GB") | |
ram_gb = 16 # Default | |
specs = self.specs.copy() | |
specs['gpu_info'] = gpu_info | |
specs['ram_gb'] = ram_gb | |
specs['manual_input'] = True | |
logger.info(f"Manual hardware specs configured: {specs}") | |
return specs | |
def get_optimization_profile(self) -> str: | |
"""Determine the best optimization profile based on hardware.""" | |
logger.debug("Determining optimization profile") | |
if self.specs['cuda_available']: | |
cuda_memory = self.specs.get('cuda_memory', 0) | |
logger.debug(f"CUDA available with {cuda_memory}GB memory") | |
if cuda_memory >= 20: | |
profile = 'high_end_gpu' | |
elif cuda_memory >= 8: | |
profile = 'mid_range_gpu' | |
else: | |
profile = 'low_vram_gpu' | |
elif self.specs['mps_available']: | |
logger.debug("MPS available, using Apple Silicon profile") | |
profile = 'apple_silicon' | |
else: | |
logger.debug("No GPU acceleration available, using CPU-only profile") | |
profile = 'cpu_only' | |
logger.info(f"Selected optimization profile: {profile}") | |
return profile | |
def print_specs(self): | |
"""Print detected hardware specifications.""" | |
logger.info("Printing hardware specifications") | |
print(f"Platform: {self.specs['platform']} ({self.specs['architecture']})") | |
print(f"CPU Cores: {self.specs['cpu_count']}") | |
print(f"Python: {self.specs['python_version']}") | |
print(f"PyTorch: {self.specs.get('torch_version', 'Not detected')}") | |
print(f"CUDA Available: {self.specs['cuda_available']}") | |
print(f"MPS Available: {self.specs['mps_available']}") | |
logger.debug("Hardware specs display completed") | |
if self.specs['gpu_info']: | |
print("GPU Information:") | |
for i, gpu in enumerate(self.specs['gpu_info']): | |
vram_gb = gpu['memory_mb'] / 1024 | |
print(f" GPU {i}: {gpu['name']} ({vram_gb:.1f} GB VRAM)") | |
else: | |
print("No GPU detected") | |
if __name__ == "__main__": | |
detector = HardwareDetector() | |
print("=== Auto-detected Hardware ===") | |
detector.print_specs() | |
choice = input("\nUse auto-detected specs? (y/n): ").lower() | |
if choice != 'y': | |
specs = detector.get_manual_input() | |
detector.specs = specs | |
print("\n=== Final Hardware Specs ===") | |
detector.print_specs() | |
print(f"\nRecommended optimization profile: {detector.get_optimization_profile()}") |