import os import shutil import subprocess import xml.etree.ElementTree as ElementTree from functools import lru_cache from typing import List, Optional import onnxruntime import facefusion.choices from facefusion.filesystem import create_directory, is_directory from facefusion.types import ExecutionDevice, ExecutionProvider, InferenceOptionSet, InferenceProvider, ValueAndUnit onnxruntime.set_default_logger_severity(3) def has_execution_provider(execution_provider : ExecutionProvider) -> bool: return execution_provider in get_available_execution_providers() def get_available_execution_providers() -> List[ExecutionProvider]: inference_session_providers = onnxruntime.get_available_providers() available_execution_providers : List[ExecutionProvider] = [] for execution_provider, execution_provider_value in facefusion.choices.execution_provider_set.items(): if execution_provider_value in inference_session_providers: index = facefusion.choices.execution_providers.index(execution_provider) available_execution_providers.insert(index, execution_provider) return available_execution_providers def create_inference_providers(execution_device_id : int, execution_providers : List[ExecutionProvider]) -> List[InferenceProvider]: inference_providers : List[InferenceProvider] = [] cache_path = resolve_cache_path() for execution_provider in execution_providers: if execution_provider == 'cuda': inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), { 'device_id': execution_device_id, 'cudnn_conv_algo_search': resolve_cudnn_conv_algo_search() })) if execution_provider == 'tensorrt': inference_option_set : InferenceOptionSet =\ { 'device_id': execution_device_id } if is_directory(cache_path) or create_directory(cache_path): inference_option_set.update( { 'trt_engine_cache_enable': True, 'trt_engine_cache_path': cache_path, 'trt_timing_cache_enable': True, 'trt_timing_cache_path': cache_path, 'trt_builder_optimization_level': 4 }) inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), inference_option_set)) if execution_provider in [ 'directml', 'rocm' ]: inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), { 'device_id': execution_device_id })) if execution_provider == 'migraphx': inference_option_set =\ { 'device_id': execution_device_id } if is_directory(cache_path) or create_directory(cache_path): inference_option_set.update( { 'migraphx_model_cache_dir': cache_path }) inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), inference_option_set)) if execution_provider == 'coreml': inference_option_set =\ { 'SpecializationStrategy': 'FastPrediction' } if is_directory(cache_path) or create_directory(cache_path): inference_option_set.update( { 'ModelCacheDirectory': cache_path }) inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), inference_option_set)) if execution_provider == 'openvino': inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), { 'device_type': resolve_openvino_device_type(execution_device_id), 'precision': 'FP32' })) if execution_provider == 'qnn': inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), { 'device_id': execution_device_id, 'backend_type': 'htp' })) if 'cpu' in execution_providers: inference_providers.append(facefusion.choices.execution_provider_set.get('cpu')) return inference_providers def resolve_cache_path() -> str: return os.path.join('.caches', onnxruntime.get_version_string()) def resolve_cudnn_conv_algo_search() -> str: execution_devices = detect_static_execution_devices() product_names = ('GeForce GTX 1630', 'GeForce GTX 1650', 'GeForce GTX 1660') for execution_device in execution_devices: if execution_device.get('product').get('name').startswith(product_names): return 'DEFAULT' return 'EXHAUSTIVE' def resolve_openvino_device_type(execution_device_id : int) -> str: if execution_device_id == 0: return 'GPU' return 'GPU.' + str(execution_device_id) def run_nvidia_smi() -> subprocess.Popen[bytes]: commands = [ shutil.which('nvidia-smi'), '--query', '--xml-format' ] return subprocess.Popen(commands, stdout = subprocess.PIPE) @lru_cache() def detect_static_execution_devices() -> List[ExecutionDevice]: return detect_execution_devices() def detect_execution_devices() -> List[ExecutionDevice]: execution_devices : List[ExecutionDevice] = [] try: output, _ = run_nvidia_smi().communicate() root_element = ElementTree.fromstring(output) except Exception: root_element = ElementTree.Element('xml') for gpu_element in root_element.findall('gpu'): execution_devices.append( { 'driver_version': root_element.findtext('driver_version'), 'framework': { 'name': 'CUDA', 'version': root_element.findtext('cuda_version') }, 'product': { 'vendor': 'NVIDIA', 'name': gpu_element.findtext('product_name').replace('NVIDIA', '').strip() }, 'video_memory': { 'total': create_value_and_unit(gpu_element.findtext('fb_memory_usage/total')), 'free': create_value_and_unit(gpu_element.findtext('fb_memory_usage/free')) }, 'temperature': { 'gpu': create_value_and_unit(gpu_element.findtext('temperature/gpu_temp')), 'memory': create_value_and_unit(gpu_element.findtext('temperature/memory_temp')) }, 'utilization': { 'gpu': create_value_and_unit(gpu_element.findtext('utilization/gpu_util')), 'memory': create_value_and_unit(gpu_element.findtext('utilization/memory_util')) } }) return execution_devices def create_value_and_unit(text : str) -> Optional[ValueAndUnit]: if ' ' in text: value, unit = text.split() return\ { 'value': int(value), 'unit': str(unit) } return None