|
import shutil |
|
import subprocess |
|
import xml.etree.ElementTree as ElementTree |
|
from functools import lru_cache |
|
from typing import List, Optional |
|
|
|
from onnxruntime import get_available_providers, set_default_logger_severity |
|
|
|
import facefusion.choices |
|
from facefusion.types import ExecutionDevice, ExecutionProvider, InferenceSessionProvider, ValueAndUnit |
|
|
|
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 = 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_session_providers(execution_device_id : str, execution_providers : List[ExecutionProvider]) -> List[InferenceSessionProvider]: |
|
inference_session_providers : List[InferenceSessionProvider] = [] |
|
|
|
for execution_provider in execution_providers: |
|
if execution_provider == 'cuda': |
|
inference_session_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_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), |
|
{ |
|
'device_id': execution_device_id, |
|
'trt_engine_cache_enable': True, |
|
'trt_engine_cache_path': '.caches', |
|
'trt_timing_cache_enable': True, |
|
'trt_timing_cache_path': '.caches', |
|
'trt_builder_optimization_level': 5 |
|
})) |
|
if execution_provider in [ 'directml', 'rocm' ]: |
|
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), |
|
{ |
|
'device_id': execution_device_id |
|
})) |
|
if execution_provider == 'openvino': |
|
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), |
|
{ |
|
'device_type': resolve_openvino_device_type(execution_device_id), |
|
'precision': 'FP32' |
|
})) |
|
if execution_provider == 'coreml': |
|
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), |
|
{ |
|
'SpecializationStrategy': 'FastPrediction', |
|
'ModelCacheDirectory': '.caches' |
|
})) |
|
|
|
if 'cpu' in execution_providers: |
|
inference_session_providers.append(facefusion.choices.execution_provider_set.get('cpu')) |
|
|
|
return inference_session_providers |
|
|
|
|
|
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 : str) -> str: |
|
if execution_device_id == '0': |
|
return 'GPU' |
|
if execution_device_id == '∞': |
|
return 'MULTI:GPU' |
|
return 'GPU.' + 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(maxsize = None) |
|
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 |
|
|