Gerar imagem na sua infraestrutura: o que exige GPU de verdade
Diferente de texto, geração de imagem não tem uma versão razoável em CPU. Onde exatamente está a fronteira, quanto custa cada lado, e quando a API resolve melhor.
Equipe EasyOps Cloud · · 7 min de leitura
Rodar um modelo de linguagem em CPU é desconfortável, mas viável — o artigo sobre LLM na sua VPS mostra em quais tarefas a troca compensa.
Com geração de imagem, essa conversa não existe. A diferença entre GPU e CPU aqui não é de conforto: é entre segundos e vários minutos por imagem, o que inviabiliza qualquer uso interativo e a maior parte dos usos em lote.
Vale entender por quê, porque isso define toda a decisão de arquitetura.
Por que imagem é diferente
Gerar texto é sequencial: um token por vez, cada um dependendo dos anteriores. Isso limita o paralelismo e faz a memória ser o gargalo principal — daí a CPU conseguir participar.
Gerar imagem é o oposto. O processo parte de ruído e o remove em passos sucessivos, e cada passo aplica operações sobre a imagem inteira ao mesmo tempo. É trabalho massivamente paralelo, exatamente o formato para o qual a GPU foi construída.
Uma GPU moderna tem milhares de unidades de execução; uma CPU de servidor tem algumas dezenas. Nessa carga, a diferença aparece inteira.
Números aproximados, para uma imagem comum com vinte e cinco passos:
| Hardware | Tempo por imagem |
|---|---|
| GPU dedicada moderna | 1 a 4 segundos |
| GPU modesta | 8 a 20 segundos |
| CPU de servidor, 8 núcleos | 3 a 10 minutos |
Três minutos por imagem elimina uso interativo, e torna qualquer volume relevante impraticável.
Memória de vídeo é o que decide
Se você for pelo caminho da GPU, o número que manda é a memória dela. O modelo precisa caber, e não há swap que salve.
| Memória | O que roda |
|---|---|
| 6 a 8 GB | Modelos menores, resolução moderada, com otimização |
| 12 GB | Modelos atuais em resolução padrão, com folga |
| 24 GB | Modelos grandes, lote, resolução alta |
| 40 GB+ | Treino e ajuste fino |
Algumas técnicas reduzem o consumo ao custo de velocidade — quantização dos pesos, descarregar partes do modelo para a RAM entre etapas, processar a imagem em pedaços. Elas ampliam o que cabe em placa modesta e não fazem milagre.
E vale ressaltar: mais memória de vídeo não acelera nada. Ela determina o que cabe; a velocidade vem do número de unidades de execução. Uma placa com muita memória e poucos núcleos roda modelos grandes devagar.
A arquitetura, que é a mesma da transcrição
Geração de imagem é assíncrona por natureza — ninguém precisa da resposta no mesmo instante. Isso permite o mesmo desenho descrito no artigo sobre transcrição self-hosted:
Pedido → fila com estado → worker com GPU → imagem no bucket → notificaçãoTrês decisões importam nesse desenho.
Um worker por GPU. Dois processos disputando a mesma placa causam erro de memória insuficiente e desempenho pior que um sozinho. Se quiser mais vazão, some placas, não processos.
Modelo carregado uma vez. Carregar leva dezenas de segundos; fazer isso por requisição desperdiça mais tempo que a geração em si. O worker carrega na partida e mantém.
Imagens no bucket, não no disco da VM. Elas ocupam espaço rápido, e Object Storage é mais barato e serve direto ao navegador por URL — evitando que o tráfego passe pela máquina, com o custo de egress discutido no artigo sobre o tema.
O worker se beneficia dos mesmos cuidados de qualquer serviço: limite de memória, reinício automático e log no journal, com uma unit do systemd.
Comparar com API, honestamente
A conta é diferente da de texto, porque a máquina com GPU tem custo fixo alto.
O ponto de equilíbrio depende de quantas imagens por mês você gera. Divida o custo mensal da máquina pelo preço por imagem da API: o resultado é o volume a partir do qual a infraestrutura própria começa a compensar.
Abaixo disso, a API vence com folga. Acima, a máquina passa a fazer sentido — desde que ela fique ocupada, que é a mesma consideração de formato de carga do artigo sobre API ou modelo próprio.
Uma GPU ociosa vinte horas por dia é o pior dos dois mundos: custo fixo alto sem utilização.
Quando o próprio se justifica sem ser por custo
Alguns motivos independem de volume:
- Conteúdo que não pode sair. Imagem de produto não lançado, material sob acordo de confidencialidade, dado de cliente.
- Modelo ajustado ao seu domínio. Um modelo treinado com o seu catálogo produz resultado que API genérica não produz.
- Controle total sobre filtros. APIs recusam conteúdo por política própria, e a recusa às vezes atinge caso legítimo — imagem médica, conteúdo artístico, produto específico.
- Estabilidade. Modelo próprio não muda de estilo porque o fornecedor atualizou. Para marca com identidade visual definida, isso vale.
Esse último é subestimado. Uma atualização do modelo da API pode alterar o resultado de prompts cuidadosamente ajustados, sem aviso — e o retrabalho recai sobre você.
O que reduz custo dos dois lados
Independentemente da escolha:
- Cache por prompt. O mesmo pedido gera a mesma imagem se a semente for fixa. Em catálogo e conteúdo repetitivo, a taxa de repetição é alta.
- Resolução adequada ao uso. Gerar em alta e reduzir depois desperdiça. Miniatura de catálogo não precisa nascer grande.
- Menos passos. A qualidade satura; passos além do ponto de retorno custam tempo sem melhorar o resultado. Vale testar onde está esse ponto no seu caso.
- Lote quando possível. Gerar várias de uma vez aproveita melhor a GPU que uma de cada vez.
O segundo e o terceiro item costumam render mais que qualquer troca de hardware, e levam uma tarde para calibrar.
Uma decisão em quatro perguntas
- Qual o volume mensal? Abaixo de algumas centenas, use API.
- A GPU ficaria ocupada? Se não, custo fixo trabalha contra você.
- O conteúdo pode sair da sua infraestrutura? Se não, a decisão está tomada.
- Precisa de modelo ajustado ao seu domínio? Se sim, o próprio é o caminho.
Se a resposta apontar para infraestrutura própria, vale começar pelo teste: alugue uma máquina com GPU por algumas horas, rode a sua carga real, e meça imagens por hora e qualidade. Cobrança por hora torna esse experimento barato, e ele responde o que nenhuma estimativa responde.
E se apontar para API, vale manter a camada de geração isolada atrás de uma interface no código. O volume pode crescer, os preços mudam, e a troca deve tocar um arquivo — não a aplicação inteira.
O que a fila precisa ter
Um detalhe operacional que só aparece depois de colocar em produção: geração de imagem falha com mais frequência que outras cargas, e por motivos específicos.
Falta de memória de vídeo é o principal. Um pedido com resolução maior, ou um lote concorrente, estoura a placa — e o processo morre levando o worker junto.
Isso exige três proteções na fila:
- Validar os parâmetros antes de enfileirar. Resolução e quantidade dentro de limites conhecidos, testados na sua placa.
- Reiniciar o worker automaticamente e devolver a tarefa à fila em vez de
perdê-la. Com
Restart=alwaysna unit e o pedido marcado como pendente até a confirmação de sucesso. - Limite de tentativas por tarefa, para que um pedido impossível não fique em laço consumindo a GPU indefinidamente.
Vale acompanhar a memória da placa como métrica de rotina, do mesmo modo que se acompanha memória do sistema:
nvidia-smi --query-gpu=memory.used,memory.total,utilization.gpu \
--format=csv -l 5Utilização consistentemente baixa com fila crescendo significa gargalo em outro lugar — carregamento de modelo repetido, disco lento, ou pré-processamento na CPU. É a mesma investigação de saturação do artigo sobre IO lento, aplicada a um recurso caro o suficiente para que a ociosidade doa.
Um caminho de adoção
Para quem está avaliando agora, a sequência que evita gastar antes da hora:
- Comece pela API, mesmo que o plano seja trazer para dentro. Ela permite validar o produto sem investimento, e revela o volume real — que costuma ser bem diferente do estimado.
- Instrumente desde o início: quantas imagens, quais prompts, taxa de descarte. Esses números são o que decide depois.
- Isole a camada de geração atrás de uma interface, para que a troca seja local.
- Reavalie por semestre. Preço de API cai, hardware muda, e o seu volume evolui.
Se e quando a conta virar, a migração é de baixo risco: os mesmos prompts, a mesma fila, outro executor por trás da mesma interface. E o histórico instrumentado permite dimensionar a máquina com dado em vez de palpite — evitando o erro mais caro dessa categoria, que é comprar capacidade para um volume que nunca chegou.