SRHarness / src /sr_harness /utils /auto_gpu.py
yuzihan@SIM1
Deploy SRHarness Docker Space
d06fa57
Raw History Blame Contribute Delete
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