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()}") |