# -*- coding: utf-8 -*- """ GPU 유틸리티 모듈 - DirectML 기반 GPU 가속 및 상태 관리 기능: - GPU 사용 가능성 검사 - DirectML 지원 여부 확인 - 전역 GPU 상태 관리 - CPU 폴백 처리 - Windows DirectX 12 기반 범용 GPU 지원 (NVIDIA, AMD, Intel) """ import os import logging import subprocess import platform from typing import Optional, Dict, Any # ONNXRuntime DirectML 메모리 절약형 설정 os.environ['ORT_ENABLE_ALL_OPTIMIZATIONS'] = '0' # 🔧 메모리 절약을 위해 비활성화 os.environ['ORT_DISABLE_MEMCPY_WARNINGS'] = '1' # Memcpy 경고 억제 os.environ['ORT_DISABLE_ALL_CUSTOM_OPS'] = '0' # 커스텀 연산 활성화 os.environ['ORT_LOGGING_LEVEL'] = '3' # 경고만 출력 (0: DEBUG, 1: INFO, 2: WARNING, 3: ERROR) os.environ['ORT_CUDA_CUDNN_CONV_USE_MAX_WORKSPACE'] = '0' # GPU 메모리 안정성 os.environ['ORT_LOG_SEVERITY_LEVEL'] = '3' # 심각한 오류만 로깅 # DirectML 특화 메모리 절약 설정 os.environ['ORT_DML_ENABLE_GRAPH_SERIALIZATION'] = '0' # 그래프 직렬화 비활성화 (안정성) os.environ['ORT_DML_METACOMMANDS_ENABLED'] = '1' # 메타커맨드 활성화 class GPUManager: """GPU 상태 관리 및 DirectML 지원 확인 (하위 호환성을 위해 can_use_cuda 속성 유지)""" def __init__(self, logger: Optional[object] = None): self.logger = logger or self._create_dummy_logger() # GPU 상태 전역 변수들 (하위 호환성을 위해 can_use_cuda 유지) self.can_use_cuda = False # DirectML 사용 가능 여부 (기존 인터페이스 호환성) self.directml_available = False self.gpu_info = {} self.initialization_attempted = False def _create_dummy_logger(self): """로거가 없을 때 사용할 더미 로거""" class DummyLogger: def log(self, msg, level=logging.DEBUG, exc_info=False): print(f"[GPU] {msg}") return DummyLogger() def _setup_directml_environment(self) -> None: """DirectML 환경 설정 (Windows DirectX 12 기반)""" try: if platform.system() == "Windows": # DirectML은 Windows에 내장된 DirectX 12를 사용하므로 별도 설정 불필요 self.logger.log("✅ DirectML 환경 준비 완료 (Windows DirectX 12 기반)", level=logging.DEBUG) else: self.logger.log("⚠️ DirectML은 Windows 전용입니다", level=logging.WARNING) except Exception as e: self.logger.log(f"DirectML 환경 설정 중 오류: {e}", level=logging.WARNING) def initialize_gpu_state(self, toggle_states: Dict[str, Any]) -> None: """ GPU 상태를 초기화하고 전역 변수에 저장 Args: toggle_states: 설정 딕셔너리 """ if self.initialization_attempted: return # 이미 초기화됨 self.initialization_attempted = True # DirectML 환경 설정 self._setup_directml_environment() # 사용자가 GPU 가속을 원하는지 확인 (use_cuda를 GPU 가속 플래그로 사용) use_gpu_requested = toggle_states.get("use_cuda", False) self.logger.log("=== 🚀 DirectML GPU 상태 초기화 시작 🚀 ===", level=logging.DEBUG) self.logger.log(f"🎯 사용자 GPU 가속 요청: {use_gpu_requested}", level=logging.DEBUG) self.logger.log(f"💻 현재 운영체제: {platform.system()}", level=logging.DEBUG) if not use_gpu_requested: self.logger.log("GPU 가속이 비활성화됨 (toggle_states['use_cuda'] = False)", level=logging.DEBUG) self.can_use_cuda = False self._set_safe_cpu_mode(toggle_states) return # Windows 플랫폼 확인 (DirectML 필수) if platform.system() != "Windows": self.logger.log("DirectML은 Windows 전용입니다 - CPU 모드로 전환", level=logging.WARNING) self.can_use_cuda = False self._set_safe_cpu_mode(toggle_states) return # DirectML 지원 확인 (안전하게 시도) try: directml_support = self._check_directml_support() except Exception as e: self.logger.log(f"DirectML 확인 중 예외 발생: {e} - CPU 모드로 안전 전환", level=logging.WARNING) self.can_use_cuda = False self._set_safe_cpu_mode(toggle_states) return if not directml_support: self.logger.log("DirectML 지원을 확인할 수 없음 - CPU 모드로 전환", level=logging.WARNING) self.can_use_cuda = False self._set_safe_cpu_mode(toggle_states) return # 메모리 상태 확인 (안전장치) try: memory_ok = self._check_system_memory() if not memory_ok: self.logger.log("⚠️ 시스템 메모리 부족 감지 - 안전을 위해 CPU 모드로 전환", level=logging.WARNING) self.can_use_cuda = False self._set_safe_cpu_mode(toggle_states) return except Exception as e: self.logger.log(f"메모리 확인 실패: {e} - 안전을 위해 CPU 모드로 전환", level=logging.WARNING) self.can_use_cuda = False self._set_safe_cpu_mode(toggle_states) return # 모든 검사 통과 self.can_use_cuda = True # 하위 호환성을 위해 이 속성명 유지 self.directml_available = True # toggle_states에서 migan_use_cuda를 True로 자동 설정 if 'migan_use_cuda' in toggle_states and not toggle_states['migan_use_cuda']: toggle_states['migan_use_cuda'] = True self.logger.log("🎯 toggle_states의 migan_use_cuda를 True로 자동 설정", level=logging.INFO) self.logger.log("🚀 ✅ DirectML 사용 가능 - GPU 가속 모드로 동작 ✅ 🚀", level=logging.DEBUG) self.logger.log("🎮 DirectML: NVIDIA, AMD, Intel GPU 모두 지원", level=logging.DEBUG) self.logger.log("📊 DirectML 가속 활성화: rembg, MIGAN, OCR 모든 모듈에서 GPU 사용", level=logging.DEBUG) self.logger.log("=== 🎯 DirectML GPU 상태 초기화 완료 🎯 ===", level=logging.DEBUG) def _set_safe_cpu_mode(self, toggle_states: Dict[str, Any]) -> None: """안전한 CPU 모드로 설정""" self.can_use_cuda = False self.directml_available = False # 모든 GPU 관련 설정을 CPU 모드로 강제 변경 gpu_related_keys = [ 'migan_use_cuda', 'use_cuda', 'optionIMGTrans_type', 'detail_IMGTrans_type', 'thumb_trans_type' ] for key in gpu_related_keys: if key in toggle_states: if key.endswith('_type'): toggle_states[key] = 'CPU' else: toggle_states[key] = False self.logger.log("🔒 안전한 CPU 모드로 모든 GPU 설정 강제 비활성화", level=logging.INFO) def _check_system_memory(self) -> bool: """시스템 메모리 상태 확인""" try: import psutil memory = psutil.virtual_memory() available_gb = memory.available / (1024**3) self.logger.log(f"💾 시스템 메모리 - 사용가능: {available_gb:.1f}GB, 사용률: {memory.percent:.1f}%", level=logging.DEBUG) # 사용 가능한 메모리가 2GB 미만이거나 사용률이 90% 이상이면 위험 if available_gb < 2.0 or memory.percent > 90: self.logger.log(f"⚠️ 메모리 부족 위험: 사용가능 {available_gb:.1f}GB, 사용률 {memory.percent:.1f}%", level=logging.WARNING) return False return True except Exception as e: self.logger.log(f"메모리 상태 확인 실패: {e}", level=logging.WARNING) return False # 확인 실패 시 안전하게 False 반환 def _detect_gpu_hardware(self) -> bool: """GPU 하드웨어 감지""" try: self.logger.log("🔍 GPU 하드웨어 감지 시작...", level=logging.DEBUG) if platform.system() != "Windows": self.logger.log("❌ 현재 Windows만 지원됨", level=logging.WARNING) return False self.logger.log("🖥️ Windows 환경 확인됨, nvidia-smi 명령 실행 중...", level=logging.DEBUG) # nvidia-smi 명령어로 GPU 확인 result = subprocess.run( ["nvidia-smi", "--query-gpu=name,memory.total,driver_version", "--format=csv,noheader,nounits"], capture_output=True, text=True, timeout=10, creationflags=subprocess.CREATE_NO_WINDOW if platform.system() == "Windows" else 0 ) self.logger.log(f"📊 nvidia-smi 실행 결과 - 반환코드: {result.returncode}", level=logging.DEBUG) if result.stdout: self.logger.log(f"📄 nvidia-smi 출력: {result.stdout.strip()}", level=logging.DEBUG) if result.stderr: self.logger.log(f"⚠️ nvidia-smi 에러 출력: {result.stderr.strip()}", level=logging.WARNING) if result.returncode == 0 and result.stdout.strip(): gpu_lines = result.stdout.strip().split('\n') for i, line in enumerate(gpu_lines): if line.strip(): parts = [p.strip() for p in line.split(',')] if len(parts) >= 3: self.gpu_info[f'gpu_{i}'] = { 'name': parts[0], 'memory_mb': parts[1], 'driver_version': parts[2] } self.logger.log(f"GPU 하드웨어 감지됨: {len(self.gpu_info)}개", level=logging.DEBUG) for gpu_id, info in self.gpu_info.items(): self.logger.log(f" {gpu_id}: {info['name']} ({info['memory_mb']}MB, 드라이버 {info['driver_version']})", level=logging.DEBUG) return True else: self.logger.log(f"nvidia-smi 실행 실패: {result.stderr}", level=logging.WARNING) return False except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.SubprocessError) as e: self.logger.log(f"GPU 하드웨어 감지 실패: {e}", level=logging.WARNING) return False except Exception as e: self.logger.log(f"GPU 하드웨어 감지 중 예외: {e}", level=logging.ERROR, exc_info=True) return False def _check_cuda_installation(self) -> bool: """CUDA 설치 및 작동 상태 확인""" try: self.logger.log("🔧 CUDA 설치 상태 확인 중...", level=logging.DEBUG) # nvcc 버전 확인 result = subprocess.run( ["nvcc", "--version"], capture_output=True, text=True, timeout=10, creationflags=subprocess.CREATE_NO_WINDOW if platform.system() == "Windows" else 0 ) self.logger.log(f"🛠️ nvcc 명령 실행 결과 - 반환코드: {result.returncode}", level=logging.DEBUG) if result.stdout: self.logger.log(f"📋 nvcc 출력: {result.stdout.strip()}", level=logging.DEBUG) if result.stderr: self.logger.log(f"⚠️ nvcc 에러 출력: {result.stderr.strip()}", level=logging.WARNING) if result.returncode == 0: version_output = result.stdout self.logger.log(f"CUDA 컴파일러 감지됨", level=logging.DEBUG) # 버전 정보 추출 for line in version_output.split('\n'): if 'release' in line.lower(): self.logger.log(f"CUDA 버전: {line.strip()}", level=logging.DEBUG) break return True else: self.logger.log("CUDA 컴파일러(nvcc)를 찾을 수 없음", level=logging.WARNING) return False except (subprocess.TimeoutExpired, FileNotFoundError) as e: self.logger.log(f"CUDA 설치 확인 실패: {e}", level=logging.WARNING) return False except Exception as e: self.logger.log(f"CUDA 설치 확인 중 예외: {e}", level=logging.ERROR, exc_info=True) return False def _check_directml_support(self) -> bool: """DirectML 지원 확인 및 실제 GPU 가속 동작 테스트""" self.logger.log("🧠 DirectML 지원 확인 및 실제 테스트 시작...", level=logging.DEBUG) try: self.logger.log("📦 ONNXRuntime DirectML 확인 중...", level=logging.DEBUG) import onnxruntime as ort providers = ort.get_available_providers() self.logger.log(f"🔍 ONNXRuntime 사용 가능한 providers: {providers}", level=logging.DEBUG) # DirectML provider 존재 확인 if "DmlExecutionProvider" not in providers: self.logger.log("❌ ONNXRuntime DirectML 지원 없음", level=logging.WARNING) self.logger.log("💡 onnxruntime-directml 패키지가 필요할 수 있습니다", level=logging.WARNING) return False self.logger.log("⚡ DirectML ExecutionProvider 지원 확인됨", level=logging.DEBUG) # VM 환경 감지 if self._detect_vm_environment(): self.logger.log("🖥️ VM 환경이 감지됨 - GPU 패스스루 상태 확인 중...", level=logging.DEBUG) # 실제 DirectML 동작 테스트 if not self._test_directml_actual_performance(): self.logger.log("❌ DirectML 실제 동작 테스트 실패 - CPU 모드로 전환", level=logging.WARNING) return False self.logger.log("✅ DirectML 실제 GPU 가속 동작 확인됨", level=logging.DEBUG) return True except ImportError: self.logger.log("ONNXRuntime가 설치되지 않음", level=logging.WARNING) return False except Exception as e: self.logger.log(f"ONNXRuntime DirectML 지원 확인 실패: {e}", level=logging.WARNING) return False def test_directml_comprehensive(self) -> Dict[str, Any]: """종합적인 DirectML 테스트 (GPU 상태 버튼 전용 - 실제 추론 테스트 포함)""" test_results = { 'directml_available': False, 'vm_detected': False, 'inference_test_passed': False, 'test_duration': 0, 'error_message': None, 'performance_ratio': 0 } try: import time start_time = time.time() self.logger.log("🧪 종합적인 DirectML 테스트 시작 (실제 추론 포함)...", level=logging.DEBUG) # 1단계: DirectML provider 확인 import onnxruntime as ort providers = ort.get_available_providers() directml_available = "DmlExecutionProvider" in providers test_results['directml_available'] = directml_available if not directml_available: test_results['error_message'] = "DirectML Provider를 찾을 수 없습니다" return test_results # 2단계: VM 환경 감지 vm_detected = self._detect_vm_environment() test_results['vm_detected'] = vm_detected if vm_detected: self.logger.log("🖥️ VM 환경이 감지됨 - GPU 패스스루 상태 확인 중...", level=logging.DEBUG) # 3단계: 실제 DirectML 추론 테스트 inference_success = self._test_directml_actual_performance() test_results['inference_test_passed'] = inference_success if not inference_success: test_results['error_message'] = "DirectML 추론 테스트 실패 - GPU 가속이 실제로 동작하지 않습니다" return test_results # 4단계: 성능 벤치마크 performance_ratio = self._benchmark_directml_vs_cpu() test_results['performance_ratio'] = performance_ratio test_results['test_duration'] = time.time() - start_time self.logger.log(f"✅ 종합 DirectML 테스트 완료 ({test_results['test_duration']:.2f}초)", level=logging.DEBUG) return test_results except Exception as e: test_results['error_message'] = f"DirectML 테스트 중 예외 발생: {e}" self.logger.log(f"DirectML 테스트 중 예외: {e}", level=logging.ERROR, exc_info=True) return test_results def _detect_vm_environment(self) -> bool: """VM 환경 감지 (Proxmox, VMware, VirtualBox, Hyper-V 등)""" try: self.logger.log("🔍 VM 환경 감지 중...", level=logging.DEBUG) vm_indicators = [] # 시스템 정보를 통한 VM 감지 try: result = subprocess.run( ["wmic", "computersystem", "get", "model"], capture_output=True, text=True, timeout=10, creationflags=subprocess.CREATE_NO_WINDOW ) if result.returncode == 0: output = result.stdout.lower() vm_keywords = ['virtualbox', 'vmware', 'qemu', 'xen', 'kvm', 'hyper-v', 'proxmox'] for keyword in vm_keywords: if keyword in output: vm_indicators.append(f"시스템 모델: {keyword}") except Exception as e: self.logger.log(f"시스템 모델 확인 실패: {e}", level=logging.DEBUG) # CPU 정보를 통한 VM 감지 try: result = subprocess.run( ["wmic", "cpu", "get", "name"], capture_output=True, text=True, timeout=10, creationflags=subprocess.CREATE_NO_WINDOW ) if result.returncode == 0: output = result.stdout.lower() if 'qemu' in output or 'virtual' in output: vm_indicators.append("CPU: 가상화 프로세서 감지") except Exception as e: self.logger.log(f"CPU 정보 확인 실패: {e}", level=logging.DEBUG) # DirectX 정보를 통한 하드웨어 가속 확인 try: result = subprocess.run( ["dxdiag", "/t", "temp_dxdiag.txt"], capture_output=True, timeout=15, creationflags=subprocess.CREATE_NO_WINDOW ) # dxdiag는 파일을 생성하므로 바로 결과를 읽을 수 없음 # 이 부분은 간소화하여 생략 except Exception: pass if vm_indicators: self.logger.log(f"🖥️ VM 환경 감지됨: {', '.join(vm_indicators)}", level=logging.INFO) return True else: self.logger.log("💻 물리적 환경으로 판단됨", level=logging.DEBUG) return False except Exception as e: self.logger.log(f"VM 환경 감지 실패: {e}", level=logging.DEBUG) return False # 실패 시 안전하게 물리 환경으로 가정 def _test_directml_actual_performance(self) -> bool: """실제 DirectML을 사용한 연산 테스트로 GPU 가속 동작 확인""" try: self.logger.log("🧪 DirectML 실제 동작 테스트 시작...", level=logging.DEBUG) import onnxruntime as ort import numpy as np import time # 1단계: DirectML provider 초기화 테스트 start_time = time.time() try: # DirectML provider 설정 dml_options = { 'device_id': 0, 'disable_memory_arena': False, # 메모리 아레나 사용 } providers = [('DmlExecutionProvider', dml_options), 'CPUExecutionProvider'] # 세션 옵션 설정 session_options = ort.SessionOptions() session_options.log_severity_level = 3 # ERROR만 출력 session_options.enable_mem_pattern = False # VM에서 문제가 될 수 있음 session_options.enable_cpu_mem_arena = False # 안정성 향상 # 초기화 시간 확인 init_elapsed = time.time() - start_time if init_elapsed > 5.0: # 5초 이상 걸리면 의심스러움 self.logger.log(f"⚠️ DirectML 초기화가 비정상적으로 오래 걸림 ({init_elapsed:.1f}초)", level=logging.WARNING) # 2단계: 실제 간단한 모델로 추론 테스트 success = self._perform_simple_inference_test(providers, session_options) if not success: return False # 3단계: 성능 벤치마크 (GPU vs CPU 비교) performance_ok = self._benchmark_directml_vs_cpu() if not performance_ok: self.logger.log("⚠️ DirectML 성능이 CPU보다 현저히 느림 - 실제 GPU 가속이 동작하지 않을 수 있음", level=logging.WARNING) return False total_elapsed = time.time() - start_time self.logger.log(f"✅ DirectML 실제 동작 테스트 성공 (총 {total_elapsed:.2f}초)", level=logging.DEBUG) return True except Exception as e: self.logger.log(f"❌ DirectML 세션 생성/테스트 실패: {e}", level=logging.WARNING) return False except ImportError as e: self.logger.log(f"❌ 필요한 패키지 import 실패: {e}", level=logging.WARNING) return False except Exception as e: self.logger.log(f"❌ DirectML 실제 동작 테스트 중 예외: {e}", level=logging.WARNING) return False def _perform_simple_inference_test(self, providers, session_options) -> bool: """간단한 모델로 실제 추론 테스트""" try: import onnxruntime as ort import numpy as np import time # 매우 간단한 ONNX 모델 생성 (Add 연산) from onnx import helper, TensorProto import onnx # 간단한 덧셈 연산 모델 생성 input1 = helper.make_tensor_value_info('input1', TensorProto.FLOAT, [1, 3, 224, 224]) input2 = helper.make_tensor_value_info('input2', TensorProto.FLOAT, [1, 3, 224, 224]) output = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 3, 224, 224]) add_node = helper.make_node('Add', ['input1', 'input2'], ['output']) graph = helper.make_graph([add_node], 'simple_add', [input1, input2], [output]) model = helper.make_model(graph) # 임시 모델 파일로 저장 import tempfile import os with tempfile.NamedTemporaryFile(suffix='.onnx', delete=False) as tmp_file: tmp_path = tmp_file.name onnx.save(model, tmp_path) try: # DirectML로 세션 생성 session = ort.InferenceSession(tmp_path, session_options, providers=providers) # 테스트 입력 데이터 input_data1 = np.random.rand(1, 3, 224, 224).astype(np.float32) input_data2 = np.random.rand(1, 3, 224, 224).astype(np.float32) # 실제 추론 수행 start_time = time.time() results = session.run(None, {'input1': input_data1, 'input2': input_data2}) inference_time = time.time() - start_time # 결과 검증 expected = input_data1 + input_data2 if np.allclose(results[0], expected, rtol=1e-5): self.logger.log(f"✅ 추론 테스트 성공 ({inference_time:.3f}초)", level=logging.DEBUG) return True else: self.logger.log("❌ 추론 결과가 예상과 다름", level=logging.WARNING) return False finally: # 임시 파일 삭제 try: os.unlink(tmp_path) except: pass except Exception as e: self.logger.log(f"❌ 간단한 추론 테스트 실패: {e}", level=logging.WARNING) return False def _benchmark_directml_vs_cpu(self) -> bool: """DirectML과 CPU 성능 비교로 실제 GPU 가속 확인""" try: self.logger.log("⏱️ DirectML vs CPU 성능 벤치마크 시작...", level=logging.DEBUG) # 현재는 간단한 체크만 수행 (더 정교한 벤치마크는 추후 구현) # VM 환경에서는 GPU 가속이 제대로 안 될 가능성이 높으므로 # 여기서는 초기화 시간과 기본 동작만 확인 return True # 일단 통과로 처리 except Exception as e: self.logger.log(f"성능 벤치마크 중 오류: {e}", level=logging.DEBUG) return True # 벤치마크 실패는 허용 def get_cuda_status(self) -> Dict[str, Any]: """현재 GPU 가속 상태 정보 반환 (하위 호환성을 위해 메서드명 유지)""" return { "can_use_cuda": self.can_use_cuda, # DirectML 사용 가능 여부 (호환성) "cuda_available": self.can_use_cuda, # 호환성을 위해 동일한 값 "directml_available": self.directml_available, "gpu_info": self.gpu_info.copy(), "initialization_attempted": self.initialization_attempted } def force_cpu_mode(self) -> None: """강제로 CPU 모드로 전환""" self.can_use_cuda = False self.logger.log("강제로 CPU 모드로 전환됨", level=logging.WARNING) def get_optimal_onnx_providers(self) -> list: """DirectML 기반 최적 ONNXRuntime provider 우선순위 리스트 반환""" providers = [] if self.can_use_cuda: # DirectML 사용 가능 여부 try: import onnxruntime as ort available = ort.get_available_providers() # DirectML Provider (Windows GPU 가속) if 'DmlExecutionProvider' in available: directml_options = { 'device_id': 0, # 기본 GPU 사용 } providers.append(('DmlExecutionProvider', directml_options)) self.logger.log("⚡ DirectML provider 추가 (범용 GPU 가속 - NVIDIA/AMD/Intel 지원)", level=logging.DEBUG) else: self.logger.log("❌ DirectML provider 사용 불가", level=logging.WARNING) except Exception as e: self.logger.log(f"DirectML Provider 확인 실패: {e}", level=logging.WARNING) # 항상 CPU는 폴백으로 추가 providers.append(('CPUExecutionProvider', {})) provider_names = [p[0] if isinstance(p, tuple) else p for p in providers] self.logger.log(f"📊 최종 provider 순서: {provider_names}", level=logging.DEBUG) return providers def log_gpu_memory_usage(self) -> None: """현재 GPU 메모리 사용량 로깅""" if not self.can_use_cuda: return try: result = subprocess.run( ["nvidia-smi", "--query-gpu=memory.used,memory.total", "--format=csv,noheader,nounits"], capture_output=True, text=True, timeout=5, creationflags=subprocess.CREATE_NO_WINDOW if platform.system() == "Windows" else 0 ) if result.returncode == 0 and result.stdout.strip(): lines = result.stdout.strip().split('\n') for i, line in enumerate(lines): if line.strip(): parts = [p.strip() for p in line.split(',')] if len(parts) >= 2: used_mb = int(parts[0]) total_mb = int(parts[1]) usage_percent = (used_mb / total_mb) * 100 self.logger.log( f"GPU {i} 메모리 사용량: {used_mb}MB/{total_mb}MB ({usage_percent:.1f}%)", level=logging.DEBUG ) except Exception as e: self.logger.log(f"GPU 메모리 사용량 확인 실패: {e}", level=logging.DEBUG) # 전역 GPU 관리자 인스턴스 (선택적 사용) _global_gpu_manager = None def get_global_gpu_manager(logger=None) -> GPUManager: """전역 GPU 관리자 인스턴스 반환""" global _global_gpu_manager if _global_gpu_manager is None: _global_gpu_manager = GPUManager(logger) return _global_gpu_manager def check_cuda_simple() -> bool: """간단한 GPU 가속 사용 가능성 확인 (DirectML, 하위 호환성을 위해 함수명 유지)""" try: import onnxruntime as ort providers = ort.get_available_providers() return "DmlExecutionProvider" in providers except: return False def check_directml_simple() -> bool: """간단한 DirectML 사용 가능성 확인 (캐시 없음)""" try: import onnxruntime as ort providers = ort.get_available_providers() return "DmlExecutionProvider" in providers except: return False