CoolFace
Apppublic

lenML/ChatTTS-Forge

sourceHugging Faceagpl-3.0updated 2y agoView on Hugging Face
301likes
devices.py182 linesDownload Raw Back to devices
1import logging2import sys3from functools import lru_cache4 5import torch6 7from modules import config8 9logger = logging.getLogger(__name__)10 11if sys.platform == "darwin":12    from modules.devices import mac_devices13 14 15def has_mps() -> bool:16    if sys.platform != "darwin":17        return False18    else:19        return mac_devices.has_mps20 21 22def get_cuda_device_id():23    return (24        int(config.runtime_env_vars.device_id)25        if config.runtime_env_vars.device_id is not None26        and config.runtime_env_vars.device_id.isdigit()27        else 028    ) or torch.cuda.current_device()29 30 31def get_cuda_device_string():32    if config.runtime_env_vars.device_id is not None:33        return f"cuda:{config.runtime_env_vars.device_id}"34 35    return "cuda"36 37 38def get_available_gpus() -> list[tuple[int, int]]:39    """40    Get the list of available GPUs and their free memory.41 42    :return: A list of tuples where each tuple contains (GPU index, free memory in bytes).43    """44    available_gpus = []45    for i in range(torch.cuda.device_count()):46        props = torch.cuda.get_device_properties(i)47        free_memory = props.total_memory - torch.cuda.memory_reserved(i)48        available_gpus.append((i, free_memory))49    return available_gpus50 51 52def get_memory_available_gpus(min_memory=2048):53    available_gpus = get_available_gpus()54    memory_available_gpus = [55        gpu for gpu, free_memory in available_gpus if free_memory > min_memory56    ]57    return memory_available_gpus58 59 60def get_target_device_id_or_memory_available_gpu():61    memory_available_gpus = get_memory_available_gpus()62    device_id = get_cuda_device_id()63    if device_id not in memory_available_gpus:64        if len(memory_available_gpus) != 0:65            logger.warning(66                f"Device {device_id} is not available or does not have enough memory. will try to use {memory_available_gpus}"67            )68            config.runtime_env_vars.device_id = str(memory_available_gpus[0])69        else:70            logger.warning(71                f"Device {device_id} is not available or does not have enough memory. Using CPU instead."72            )73            return "cpu"74    return get_cuda_device_string()75 76 77def get_optimal_device_name():78    if config.runtime_env_vars.use_cpu == "all":79        return "cpu"80 81    if torch.cuda.is_available():82        return get_target_device_id_or_memory_available_gpu()83 84    if has_mps():85        return "mps"86 87    return "cpu"88 89 90def get_optimal_device():91    return torch.device(get_optimal_device_name())92 93 94def get_device_for(task):95    if (96        task in config.runtime_env_vars.use_cpu97        or "all" in config.runtime_env_vars.use_cpu98    ):99        return cpu100 101    return get_optimal_device()102 103 104def torch_gc():105    try:106        if torch.cuda.is_available():107            with torch.cuda.device(get_cuda_device_string()):108                torch.cuda.empty_cache()109                torch.cuda.ipc_collect()110 111        if has_mps():112            mac_devices.torch_mps_gc()113    except Exception as e:114        logger.error(f"Error in torch_gc", exc_info=True)115 116 117cpu: torch.device = torch.device("cpu")118device: torch.device = None119dtype: torch.dtype = torch.float32120dtype_dvae: torch.dtype = torch.float32121dtype_vocos: torch.dtype = torch.float32122dtype_gpt: torch.dtype = torch.float32123dtype_decoder: torch.dtype = torch.float32124 125 126def reset_device():127    global device128    global dtype129    global dtype_dvae130    global dtype_vocos131    global dtype_gpt132    global dtype_decoder133 134    if config.runtime_env_vars.use_cpu is None:135        config.runtime_env_vars.use_cpu = []136 137    if "all" in config.runtime_env_vars.use_cpu and not config.runtime_env_vars.no_half:138        logger.warning(139            "Cannot use half precision with CPU, using full precision instead"140        )141        config.runtime_env_vars.no_half = True142 143    if not config.runtime_env_vars.no_half:144        dtype = torch.float16145        dtype_dvae = torch.float16146        dtype_vocos = torch.float16147        dtype_gpt = torch.float16148        dtype_decoder = torch.float16149 150        logger.info("Using half precision: torch.float16")151    else:152        dtype = torch.float32153        dtype_dvae = torch.float32154        dtype_vocos = torch.float32155        dtype_gpt = torch.float32156        dtype_decoder = torch.float32157 158        logger.info("Using full precision: torch.float32")159 160    if "all" in config.runtime_env_vars.use_cpu:161        device = cpu162    else:163        device = get_optimal_device()164 165    logger.info(f"Using device: {device}")166 167 168@lru_cache169def first_time_calculation():170    """171    just do any calculation with pytorch layers - the first time this is done it allocaltes about 700MB of memory and172    spends about 2.7 seconds doing that, at least wih NVidia.173    """174 175    x = torch.zeros((1, 1)).to(device, dtype)176    linear = torch.nn.Linear(1, 1).to(device, dtype)177    linear(x)178 179    x = torch.zeros((1, 1, 3, 3)).to(device, dtype)180    conv2d = torch.nn.Conv2d(1, 1, (3, 3)).to(device, dtype)181    conv2d(x)182