A conta de GPU que assusta raramente vem de escolher a placa errada. Vem de deixar a placa certa ligada.
Uma RTX 4090 a R$ 2,78 por hora custa cerca de R$ 2.000 por mês ligada o tempo todo, e R$ 170 se ligar duas horas por dia. É a mesma máquina, o mesmo trabalho entregue — a diferença é só quem lembrou de desligar.
Separe o que precisa estar ligado do que não precisa
A pergunta que resolve: alguém está esperando na frente da tela?
| Carga | Precisa responder em | Formato certo |
|---|---|---|
| Chat, autocompletar, busca do usuário | Segundos | Serviço ligado — ou API por token |
| Relatório noturno, resumo do dia | Horas | Lote |
| Indexar acervo, gerar catálogo, transcrever gravações | Horas ou dias | Lote |
| Treinar ou ajustar modelo | Quando terminar | Lote |
| Processar arquivo que o usuário enviou | Minutos | Fila com máquina que acorda |
Na maioria das empresas, a maior parte da carga de GPU é da metade de baixo dessa tabela — e está rodando numa máquina ligada o tempo todo porque foi assim que começou.
O padrão: subir, processar, desligar
A forma mais confiável de garantir que a máquina desligue é a máquina desligar a si mesma quando acabar. Não depender de ninguém lembrar, nem de um alarme.
#!/usr/bin/env bash
set -euo pipefail
LOG=/var/log/lote.log
exec >> "$LOG" 2>&1
encerrar() {
codigo=$?
echo "[$(date -Is)] terminando com código $codigo"
curl -s -X POST "$WEBHOOK" -H 'content-type: application/json' \
-d "{\"status\": $codigo, \"host\": \"$(hostname)\"}" || true
sleep 10
sudo shutdown -h now # desliga aconteça o que acontecer
}
trap encerrar EXIT # <-- a linha que salva a fatura
echo "[$(date -Is)] iniciando"
python3 /opt/trabalho/processar.py --entrada /dados/fila --saida /dados/pronto
echo "[$(date -Is)] processamento concluído"
trapCom trap ... EXIT, o desligamento acontece se o script terminar bem, se falhar, se o Python estourar exceção ou se alguém matar o processo. Sem ele, um erro na terceira linha deixa a máquina ligada o fim de semana inteiro.
Já vimos conta de mais de mil reais causada por um ImportError numa sexta-feira à noite.
Torne o trabalho retomável
Máquina que desliga sozinha combina mal com processo que precisa começar do zero. Três regras que resolvem:
- Estado no disco, não na memória. Cada item processado grava o resultado antes de seguir.
- Pular o que já existe. Nome de saída determinístico e um
if existe: continue. - Item, não bloco. Processar em blocos de mil e salvar no fim perde mil itens quando cai no 999.
from pathlib import Path
PRONTO = Path("/dados/pronto")
for item in fila:
destino = PRONTO / f"{item.id}.json"
if destino.exists():
continue
try:
resultado = processar(item)
tmp = destino.with_suffix(".tmp")
tmp.write_text(resultado, encoding="utf-8")
tmp.rename(destino) # troca atômica: nunca meio-arquivo
except Exception as e:
(PRONTO / f"{item.id}.erro").write_text(str(e), encoding="utf-8")
O rename depois de escrever num arquivo temporário é o detalhe que evita a pior situação: um arquivo pela metade que o processo seguinte vai considerar pronto.
Dimensionar pelo tempo total, não pela velocidade
Em trabalho de lote, a pergunta certa é quanto custa terminar, não quanto custa a hora. E a resposta muda a escolha da placa.
| Placa | Preço/hora | Tempo do trabalho | Custo total |
|---|---|---|---|
| RTX 4090 | R$ 2,78 | 10 h | R$ 27,80 |
| L40S | R$ 7,08 | 4,5 h | R$ 31,86 |
| A100 80 GB | R$ 11,05 | 3 h | R$ 33,15 |
Preços de agosto de 2026, para uma GPU avulsa, sem interrupção programada. O catálogo muda: confira a vitrine antes de fechar a conta.
Custos praticamente iguais, tempos muito diferentes. Se ninguém está esperando, pegue a mais barata; se o resultado precisa estar pronto às 7h, pague os R$ 5 a mais e durma tranquilo. A placa cara não é desperdício em lote — desde que ela desligue no fim.
A exceção é quando o modelo não cabe na placa pequena: aí não há escolha, e forçar a barra com descarregamento para a memória do sistema deixa o trabalho tão lento que a placa barata sai mais cara no total.
Nem toda carga acelera com placa maior. Transcrição de áudio, por exemplo, tem gargalo em decodificação e leitura de arquivo — uma placa três vezes mais cara entrega menos de 40% de ganho.
Meça com uma amostra pequena nas duas placas antes de comprometer o lote inteiro. Meia hora de teste evita escolher a opção errada por dez horas.
Fila com máquina que acorda
Para carga irregular — o usuário envia um arquivo e espera minutos, não horas — o padrão é uma fila com disparo:
- O pedido entra numa fila persistente (banco, arquivo, serviço de fila).
- Um verificador roda a cada poucos minutos numa máquina barata, sem GPU.
- Se houver itens pendentes acima de um mínimo, ele cria a instância com GPU pela API.
- A instância processa tudo que estiver na fila, avisa por webhook e se desliga.
Dois parâmetros definem a economia: o mínimo para acordar (subir máquina para um item só raramente compensa) e o tempo de espera antes de desligar depois de esvaziar a fila — cinco a dez minutos evitam o ciclo de ligar e desligar seguidamente quando os pedidos chegam espaçados.
O que checar antes de dormir tranquilo
- O
trapestá no script? Teste forçando um erro e veja se desliga. - Existe alarme de máquina viva há mais de N horas? A rede de segurança para quando o desligamento falhar.
- O resultado é gravado fora da máquina? Disco de instância desligada não é lugar de guardar entrega.
- O trabalho é retomável? Se cair em 70%, recomeça de 70% ou de zero?
- Alguém é avisado quando termina? Sem aviso, o resultado fica pronto e ninguém usa.
Pague pelo trabalho, não pelo mês
Suba a máquina, rode a fila e desligue. A cobrança é por hora, em reais, e a instância parada não gasta como a ligada.
Criar conta →Conclusão
Metade da economia em GPU não vem de escolher melhor a placa — vem de reconhecer que a maior parte do seu trabalho não precisa de ninguém esperando. Transforme em fila, escreva o script para ser retomável, ponha o trap de desligamento e meça o custo por trabalho concluído, não por hora.
A pergunta para levar para a próxima reunião: quantas horas de GPU nós pagamos no mês passado e quantas delas tiveram alguém do outro lado?
Continue: transcrição em lote · imagens em lote · quando precisa ficar ligado