Download src/sr_harness/utils/auto_gpu.py from YuMeow/SRHarness: direct link, hf CLI and curl.
- Browser
- Download file 3.26 kB
-
https://huggingface.co/spaces/YuMeow/SRHarness/resolve/main/src/sr_harness/utils/auto_gpu.py
- Command line
-
hf download hf://spaces/YuMeow/SRHarness/src/sr_harness/utils/auto_gpu.py
-
curl -L -o auto_gpu.py https://huggingface.co/spaces/YuMeow/SRHarness/resolve/main/src/sr_harness/utils/auto_gpu.py
3.26 kB
| # Copyright (c) 2024-present, Yumeow. Licensed under the MIT License. | |
| import os | |
| import time | |
| import torch | |
| import logging | |
| import subprocess | |
| __all__ = ["AutoGPU"] | |
| _logger = logging.getLogger(f"sr_harness.{__name__}") | |
| class AutoGPU: | |
| """Automatically choose a GPU with enough free memory""" | |
| def __init__(self): | |
| visible_devices = os.getenv("CUDA_VISIBLE_DEVICES") | |
| if visible_devices: | |
| self.gpu_list = list(map(int, visible_devices.split(","))) | |
| else: | |
| self.gpu_list = [i for i in range(torch.cuda.device_count())] | |
| self.free_memory = { | |
| i: self.query_free_memory(j) for i, j in enumerate(self.gpu_list) | |
| } # cuda:i -> memory of j-th GPU | |
| def update_free_memory(self): | |
| for i, j in enumerate(self.gpu_list): | |
| self.free_memory[i] = self.query_free_memory(j) | |
| def choice_gpu(self, memory_MB, interval=600, force=True): | |
| """Choose a GPU with enough free memory | |
| Arguments: | |
| - memory_MB: int, the required memory in MB | |
| - interval: int, the interval (in second) to check free memory | |
| - force: bool, whether to wait until a GPU is available | |
| """ | |
| waiting = False | |
| while True: | |
| for i, free_memory in self.free_memory.items(): | |
| if free_memory < memory_MB: | |
| continue | |
| try: | |
| device = f"cuda:{i}" | |
| free_memory1 = self.query_free_memory(self.gpu_list[i]) | |
| fuck_cuda = torch.zeros( | |
| int(memory_MB), 1024, 256, dtype=torch.float32, device=device | |
| ) | |
| free_memory2 = self.query_free_memory(self.gpu_list[i]) | |
| if waiting: | |
| _logger.note( | |
| f"SubProcess[{os.getpid()}]: Choose GPU{self.gpu_list[i]} ({device}) with {memory_MB}MB ({free_memory1}MB -> {free_memory2}MB)" | |
| ) | |
| else: | |
| _logger.info( | |
| f"SubProcess[{os.getpid()}]: Choose GPU{self.gpu_list[i]} ({device}) with {memory_MB}MB ({free_memory1}MB -> {free_memory2}MB)" | |
| ) | |
| del fuck_cuda | |
| return device | |
| except Exception as e: | |
| torch.cuda.empty_cache() | |
| continue | |
| else: | |
| if force: | |
| if not waiting: | |
| _logger.warning(f"SubProcess[{os.getpid()}]: Waiting GPU...") | |
| waiting = True | |
| time.sleep(interval) | |
| self.update_free_memory() | |
| else: # not force | |
| _logger.warning(f"SubProcess[{os.getpid()}]: No available GPU!") | |
| return "cpu" | |
| def query_free_memory(self, gpu_id): | |
| try: | |
| cmd = f"nvidia-smi --query-gpu=memory.free --format=csv,noheader,nounits -i {gpu_id}" | |
| return int( | |
| subprocess.check_output(cmd, shell=True).decode().strip().split("\n")[0] | |
| ) | |
| except Exception as e: | |
| _logger.warning(f"Query CUDA (GPU{gpu_id}) Memory Failed! {e}") | |
| return 0 | |