caarleexx commited on
Commit
a39bf55
·
verified ·
1 Parent(s): 182e87f

Create GPUManager.py

Browse files
Files changed (1) hide show
  1. api/GPUManager.py +110 -0
api/GPUManager.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # GPUManager.py
2
+ import torch
3
+ from typing import List, Dict
4
+
5
+ class GPUManager:
6
+ """
7
+ Classe singleton para gerenciar e alocar recursos de GPU de forma centralizada.
8
+
9
+ Esta classe detecta as GPUs disponíveis e as aloca para diferentes
10
+ tipos de tarefas com base em uma estratégia predefinida. Ela foi projetada
11
+ para ser extensível a outros modelos e tarefas no futuro.
12
+
13
+ Estratégia Padrão:
14
+ - LTX_PRIMARY: Tarefas pesadas e sequenciais (Transformer, Text Encoder).
15
+ Alocado para a primeira GPU (cuda:0) para maximizar o desempenho.
16
+ - VAE_POOL: Tarefas mais leves e paralelizáveis (decodificação VAE).
17
+ Alocado para as GPUs restantes (cuda:1, cuda:2, ...) em um pool de workers.
18
+
19
+ Em caso de GPU única, todos os modelos compartilham o mesmo dispositivo.
20
+ Em caso de ausência de GPUs, opera em modo CPU.
21
+ """
22
+ def __init__(self):
23
+ self.num_gpus = 0
24
+ self.devices: List[str] = []
25
+ self._allocations: Dict[str, List[str]] = {}
26
+ self._worker_indices: Dict[str, int] = {}
27
+
28
+ if torch.cuda.is_available():
29
+ self.num_gpus = torch.cuda.device_count()
30
+
31
+ self._initialize_allocations()
32
+
33
+ def _initialize_allocations(self):
34
+ """Define a estratégia de alocação de dispositivos com base nas GPUs disponíveis."""
35
+ print("[GPUManager] Inicializando alocação de dispositivos...")
36
+
37
+ if self.num_gpus == 0:
38
+ print("[GPUManager] Nenhuma GPU CUDA detectada. Operando em modo CPU.")
39
+ self.devices = ["cpu"]
40
+ self._allocations['LTX_PRIMARY'] = ["cpu"]
41
+ self._allocations['VAE_POOL'] = ["cpu"]
42
+ elif self.num_gpus == 1:
43
+ print("[GPUManager] Detectada 1 GPU. Todos os modelos compartilharão cuda:0.")
44
+ self.devices = ["cuda:0"]
45
+ self._allocations['LTX_PRIMARY'] = ["cuda:0"]
46
+ self._allocations['VAE_POOL'] = ["cuda:0"]
47
+ else: # Múltiplas GPUs
48
+ print(f"[GPUManager] Detectadas {self.num_gpus} GPUs. Ativando modo Multi-GPU.")
49
+ self.devices = [f"cuda:{i}" for i in range(self.num_gpus)]
50
+
51
+ # Aloca a primeira GPU para os modelos principais
52
+ primary_device = self.devices[0]
53
+ self._allocations['LTX_PRIMARY'] = [primary_device]
54
+ print(f" - Tarefas LTX_PRIMARY (Transformer/TextEncoder) alocadas para: {primary_device}")
55
+
56
+ # Aloca as GPUs restantes para o pool de workers do VAE
57
+ worker_devices = self.devices[1:]
58
+ self._allocations['VAE_POOL'] = worker_devices
59
+ self._worker_indices['VAE_POOL'] = 0
60
+ print(f" - Tarefas VAE_POOL (VAE Decode) alocadas para: {worker_devices}")
61
+
62
+ print("[GPUManager] Alocação concluída.")
63
+
64
+ def get_device_for(self, task_key: str) -> str:
65
+ """
66
+ Retorna o dispositivo principal alocado para uma chave de tarefa.
67
+ Use para modelos que residem em um único dispositivo.
68
+
69
+ Args:
70
+ task_key (str): A chave da tarefa (ex: 'LTX_PRIMARY').
71
+
72
+ Returns:
73
+ str: O nome do dispositivo (ex: 'cuda:0').
74
+ """
75
+ if task_key not in self._allocations:
76
+ raise ValueError(f"Chave de tarefa '{task_key}' não registrada no GPUManager.")
77
+
78
+ # Retorna o primeiro (e geralmente único) dispositivo da lista de alocação
79
+ return self._allocations[task_key][0]
80
+
81
+ def get_next_worker_for(self, pool_key: str) -> str:
82
+ """
83
+ Retorna o próximo dispositivo disponível de um pool de workers em rodízio.
84
+ Use para tarefas que podem ser paralelizadas em várias GPUs.
85
+
86
+ Args:
87
+ pool_key (str): A chave do pool de workers (ex: 'VAE_POOL').
88
+
89
+ Returns:
90
+ str: O nome do próximo dispositivo worker (ex: 'cuda:1').
91
+ """
92
+ if pool_key not in self._allocations or pool_key not in self._worker_indices:
93
+ raise ValueError(f"Pool de workers '{pool_key}' não registrado no GPUManager.")
94
+
95
+ worker_pool = self._allocations[pool_key]
96
+ if not worker_pool:
97
+ raise RuntimeError(f"O pool de workers '{pool_key}' está vazio.")
98
+
99
+ # Obtém o índice atual, calcula o próximo e retorna o dispositivo
100
+ current_idx = self._worker_indices[pool_key]
101
+ device = worker_pool[current_idx]
102
+
103
+ # Avança o índice para o próximo worker (com wrap-around)
104
+ self._worker_indices[pool_key] = (current_idx + 1) % len(worker_pool)
105
+
106
+ return device
107
+
108
+ # --- Instância Singleton ---
109
+ # Importe esta instância em outros arquivos para garantir um único ponto de gerenciamento.
110
+ gpu_manager = GPUManager()