File size: 5,583 Bytes
8fb6272
 
 
 
 
3374810
1ccfc24
534b64d
8fb6272
 
 
 
 
 
 
 
1ccfc24
 
cd2dff3
1ccfc24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cd2dff3
 
1ccfc24
 
 
 
 
 
 
cd2dff3
1ccfc24
 
274148b
1ccfc24
 
 
cd2dff3
 
1ccfc24
 
 
 
 
 
 
 
 
 
 
274148b
 
 
1ccfc24
cd2dff3
1ccfc24
274148b
1ccfc24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cd2dff3
1ccfc24
274148b
1ccfc24
cd2dff3
3374810
8fb6272
 
 
 
 
 
 
 
 
 
1ccfc24
 
 
 
 
 
 
 
 
8fb6272
 
 
cd2dff3
8fb6272
 
 
 
 
 
1ccfc24
 
 
 
8fb6272
1ccfc24
 
8fb6272
cd2dff3
8fb6272
 
1ccfc24
3374810
eb1a752
8fb6272
cd2dff3
 
8fb6272
 
 
3374810
1ccfc24
8fb6272
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import os
from dotenv import load_dotenv
from src.presentation.web.gradio_interface import GradioInterface
import logging
import torch
import gc
import nvidia_smi
from src.domain.factories.detector_factory import force_gpu_init, is_gpu_available

# Configurar logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

def check_gpu_type():
    """Verifica o tipo de GPU disponível no ambiente Hugging Face."""
    try:
        nvidia_smi.nvmlInit()
        handle = nvidia_smi.nvmlDeviceGetHandleByIndex(0)
        info = nvidia_smi.nvmlDeviceGetMemoryInfo(handle)
        gpu_name = nvidia_smi.nvmlDeviceGetName(handle)
        total_memory = info.total / (1024**3)  # Converter para GB
        
        logger.info(f"GPU detectada: {gpu_name}")
        logger.info(f"Memória total: {total_memory:.2f}GB")
        
        # T4 dedicada tem tipicamente 16GB
        if "T4" in gpu_name and total_memory > 14:
            return "t4_dedicated"
        # Zero-GPU compartilhada tem tipicamente menos memória
        elif total_memory < 14:
            return "zero_gpu_shared"
        else:
            return "unknown"
            
    except Exception as e:
        logger.error(f"Erro ao verificar tipo de GPU: {str(e)}")
        return "unknown"
    finally:
        try:
            nvidia_smi.nvmlShutdown()
        except:
            pass

def setup_gpu_environment(gpu_type: str) -> bool:
    """Configura o ambiente GPU com base no tipo detectado."""
    try:
        # Verificar ambiente CUDA
        if not torch.cuda.is_available():
            logger.warning("CUDA não está disponível")
            return False
            
        # Configurações comuns
        os.environ['CUDA_DEVICE_ORDER'] = 'PCI_BUS_ID'
        os.environ['CUDA_VISIBLE_DEVICES'] = '0'
        
        # Limpar memória
        torch.cuda.empty_cache()
        gc.collect()
        
        if gpu_type == "t4_dedicated":
            # Configurações para T4 dedicada
            logger.info("Configurando para T4 dedicada")
            torch.backends.cuda.matmul.allow_tf32 = True
            torch.backends.cudnn.benchmark = True
            torch.backends.cudnn.allow_tf32 = True
            # Usar mais memória pois temos GPU dedicada
            torch.cuda.set_per_process_memory_fraction(0.9)
            os.environ['PYTORCH_CUDA_ALLOC_CONF'] = 'max_split_size_mb:512'
            
        elif gpu_type == "zero_gpu_shared":
            # Configurações para Zero-GPU compartilhada
            logger.info("Configurando para Zero-GPU compartilhada")
            torch.backends.cudnn.benchmark = False
            # Limitar uso de memória
            torch.cuda.set_per_process_memory_fraction(0.6)
            os.environ['PYTORCH_CUDA_ALLOC_CONF'] = 'max_split_size_mb:128'
            
        # Verificar configuração
        try:
            device = torch.device('cuda')
            dummy = torch.zeros(1, device=device)
            del dummy
            logger.info(f"Configurações GPU aplicadas com sucesso para: {gpu_type}")
            return True
        except Exception as e:
            logger.error(f"Erro ao configurar GPU: {str(e)}")
            return False
            
    except Exception as e:
        logger.error(f"Erro ao configurar ambiente GPU: {str(e)}")
        return False

def main():
    """Função principal que inicia a aplicação."""
    try:
        # Verificar se está rodando no Hugging Face
        IS_HUGGINGFACE = os.getenv('SPACE_ID') is not None
        
        # Carregar configurações do ambiente apropriado
        if IS_HUGGINGFACE:
            load_dotenv('.env.huggingface')
            logger.info("Ambiente HuggingFace detectado")
            
            # Identificar e configurar GPU
            gpu_type = check_gpu_type()
            gpu_available = setup_gpu_environment(gpu_type)
            
            if gpu_available:
                logger.info(f"GPU configurada com sucesso: {gpu_type}")
            else:
                logger.warning("GPU não disponível ou não configurada corretamente")
        else:
            load_dotenv('.env')
            logger.info("Ambiente local detectado")
            gpu_available = False
        
        # Criar e configurar interface
        interface = GradioInterface()
        demo = interface.create_interface()
        
        if IS_HUGGINGFACE:
            # Configurar com base no tipo de GPU
            if gpu_type == "t4_dedicated":
                max_concurrent = 2  # T4 pode lidar com mais requisições
                queue_size = 10
            else:
                max_concurrent = 1  # Zero-GPU precisa ser mais conservadora
                queue_size = 5
            
            # Configurar fila
            demo = demo.queue(
                api_open=False,
                max_size=queue_size,
                status_update_rate="auto",
                default_concurrency_limit=max_concurrent
            )
            
            # Launch
            demo.launch(
                server_name="0.0.0.0",
                server_port=7860,
                share=False,
                max_threads=max_concurrent
            )
        else:
            demo.launch(
                server_name="0.0.0.0",
                server_port=7860,
                share=True
            )
            
    except Exception as e:
        logger.error(f"Erro ao iniciar aplicação: {str(e)}")
        raise

if __name__ == "__main__":
    main()