Capítulo 2: Requisitos Computacionais
Calculando Memória de GPU e Custos de Treinamento
Compreender os requisitos computacionais para fine-tuning é fundamental para planejar seus projetos e escolher a abordagem correta.
Componentes de Memória da GPU
Durante o treinamento, a memória da GPU é consumida por quatro componentes principais:
1. Pesos do Modelo
Os parâmetros do próprio modelo.
2. Gradientes
Mesmo tamanho dos pesos—armazena o gradiente para cada parâmetro.
3. Estados do Otimizador
AdamW armazena 2 estados (momento, variância) por parâmetro.
4. Ativações
Valores intermediários necessários para o backpropagation.
Fórmula de Cálculo de Memória
Fórmula Básica
Memory (bytes) = Parameters × Precision × Multiplier
Where Multiplier for training:
- Inference: 1
- AdamW training: 4-6 (weights + gradients + 2 optimizer states + activations)
Tamanhos de Precisão
| Precisão | Bytes por Parâmetro |
|---|---|
| float32 | 4 |
| bfloat16 | 2 |
| float16 | 2 |
| int8 | 1 |
| int4 | 0.5 |
Requisitos de Memória para Fine-Tuning Completo
Exemplo: Modelo com 7B Parâmetros
# Parameters: 7 billion
parameters = 7_000_000_000
# With float32 (full precision)
weights_fp32 = parameters * 4 # 28 GB
gradients_fp32 = parameters * 4 # 28 GB
optimizer_fp32 = parameters * 4 * 2 # 56 GB (2 states)
# Total: ~112 GB ❌ Too much for most GPUs
# With bfloat16 + mixed precision
weights_bf16 = parameters * 2 # 14 GB
gradients_bf16 = parameters * 2 # 14 GB
optimizer_fp32 = parameters * 4 * 2 # 56 GB (kept in fp32)
# Total: ~84 GB ⚠️ Still requires A100-80GB
# With gradient checkpointing + bf16
# Activations reduced by ~30%
# Total: ~60-70 GB
Tabela de Requisitos de Memória
| Tamanho do Modelo | Full FT (fp32) | Full FT (bf16) | Com Grad Ckpt |
|---|---|---|---|
| 1B | ~16 GB | ~12 GB | ~8 GB |
| 7B | ~112 GB | ~84 GB | ~60 GB |
| 13B | ~208 GB | ~156 GB | ~110 GB |
| 70B | ~1.1 TB | ~840 GB | ~600 GB |
Reduzindo os Requisitos de Memória
1. Treinamento com Precisão Mista
training_args = TrainingArguments(
bf16=True, # Use bfloat16
)
Reduz a memória dos pesos e gradientes em ~50%.
2. Gradient Checkpointing
training_args = TrainingArguments(
gradient_checkpointing=True,
)
# OR
model.gradient_checkpointing_enable()
Troca computação por memória—recalcula ativações durante o backward pass.
3. Acumulação de Gradientes
training_args = TrainingArguments(
per_device_train_batch_size=1,
gradient_accumulation_steps=16,
# Effective batch size = 1 * 16 = 16
)
Lotes menores usam menos memória; acumule gradientes para simular lotes maiores.
4. Otimizadores Eficientes em Memória
# 8-bit Adam (requires bitsandbytes)
training_args = TrainingArguments(
optim="adamw_8bit",
)
# OR Adafactor (no momentum)
training_args = TrainingArguments(
optim="adafactor",
)
5. DeepSpeed ZeRO
# deepspeed_config.json
{
"zero_optimization": {
"stage": 2, # Partition gradients and optimizer states
}
}
# In training
training_args = TrainingArguments(
deepspeed="deepspeed_config.json",
)
Estágios do ZeRO:
- Stage 1: Particiona estados do otimizador
- Stage 2: + Particiona gradientes
- Stage 3: + Particiona pesos do modelo (permite treinar modelos maiores que a memória da GPU)
Recomendações Práticas de GPU
Treinamento em GPU Única
| GPU | VRAM | Máx. Modelo (Full FT) | Máx. Modelo (Eficiente) |
|---|---|---|---|
| RTX 3090 | 24 GB | 1B | 3B |
| RTX 4090 | 24 GB | 1B | 3B |
| A100-40GB | 40 GB | 3B | 7B |
| A100-80GB | 80 GB | 7B | 13B |
| H100 | 80 GB | 7B | 13B |
Treinamento Multi-GPU
# Automatic distribution with accelerate
from accelerate import Accelerator
accelerator = Accelerator()
model, optimizer, dataloader = accelerator.prepare(
model, optimizer, dataloader
)
| Setup | VRAM Combinada | Máx. Modelo (Eficiente) |
|---|---|---|
| 2× A100-40GB | 80 GB | 7-13B |
| 4× A100-80GB | 320 GB | 30-40B |
| 8× H100 | 640 GB | 70B |
Estimativa de Tempo de Treinamento
Fatores que Afetam o Tempo de Treinamento
Training Time = (Dataset Size × Epochs) / (Batch Size × Throughput)
Exemplos de Throughput (tokens/segundo)
| Modelo | GPU | Throughput |
|---|---|---|
| 7B | A100-40GB | ~1.000 tokens/s |
| 7B | H100 | ~2.000 tokens/s |
| 13B | A100-80GB | ~500 tokens/s |
| 70B | 8× H100 | ~800 tokens/s |
Exemplo de Cálculo de Tempo
# Dataset: 10,000 examples, 512 tokens each
total_tokens = 10_000 * 512 = 5_120_000
# Training: 3 epochs
total_training_tokens = 5_120_000 * 3 = 15_360_000
# Throughput: 1,000 tokens/second
training_time_seconds = 15_360_000 / 1_000 = 15,360 seconds
training_time_hours = 15_360 / 3_600 = 4.3 hours
Estimativa de Custos em Nuvem
Preços de GPU (Aproximados)
| GPU | On-Demand ($/hr) | Spot ($/hr) |
|---|---|---|
| T4 | $0.50 | $0.15 |
| A10G | $1.50 | $0.45 |
| A100-40GB | $4.00 | $1.20 |
| A100-80GB | $6.00 | $1.80 |
| H100 | $8.00 | $2.40 |
Exemplo de Cálculo de Custo
# Training a 7B model
# Time: 4 hours on A100-40GB
# Cost: 4 × $4.00 = $16 (on-demand)
# Cost: 4 × $1.20 = $4.80 (spot)
# With experimentation (5 runs)
# Total: $80 (on-demand) or $24 (spot)
Profiling de Memória
Verifique o Uso Atual de Memória
import torch
# Current allocated memory
allocated = torch.cuda.memory_allocated() / 1024**3
print(f"Allocated: {allocated:.2f} GB")
# Peak memory usage
peak = torch.cuda.max_memory_allocated() / 1024**3
print(f"Peak: {peak:.2f} GB")
# Reset peak stats
torch.cuda.reset_peak_memory_stats()
Estime Antes do Treinamento
def estimate_memory(model, batch_size, seq_len, precision="bf16"):
"""Estimate training memory requirements."""
param_count = sum(p.numel() for p in model.parameters())
# Bytes per parameter based on precision
bytes_per_param = 2 if precision == "bf16" else 4
# Model weights
weights_gb = (param_count * bytes_per_param) / 1024**3
# Gradients (same as weights)
gradients_gb = weights_gb
# Optimizer states (AdamW: 2 states in fp32)
optimizer_gb = (param_count * 4 * 2) / 1024**3
# Activations (rough estimate)
activation_gb = (batch_size * seq_len * 4096 * 4) / 1024**3 # Approximate
total_gb = weights_gb + gradients_gb + optimizer_gb + activation_gb
print(f"Weights: {weights_gb:.2f} GB")
print(f"Gradients: {gradients_gb:.2f} GB")
print(f"Optimizer: {optimizer_gb:.2f} GB")
print(f"Activations: ~{activation_gb:.2f} GB")
print(f"Total: ~{total_gb:.2f} GB")
return total_gb
Checklist de Otimização
□ Ative precisão mista (bf16/fp16)
□ Ative gradient checkpointing
□ Use acumulação de gradientes para lotes efetivos maiores
□ Considere otimizadores 8-bit
□ Use DeepSpeed para multi-GPU
□ Monitore a memória com profiling
□ Use instâncias spot para economizar custos
Principais Pontos
✅ O fine-tuning completo requer ~4-6x o tamanho do modelo em memória de GPU
✅ Um modelo de 7B precisa de 60-80GB para fine-tuning completo
✅ Precisão mista e gradient checkpointing reduzem significativamente a memória
✅ Treinamento multi-GPU permite modelos maiores
✅ Custos em nuvem podem ser reduzidos em 60-70% com instâncias spot
✅ Sempre faça profiling de memória antes de iniciar longos treinamentos
Próximos Passos
Continue para Capítulo 3: Esquecimento Catastrófico para aprender sobre retenção de conhecimento durante o fine-tuning.
Verificação Rápida
Antes de avançar, certifique-se de que você consegue responder:
- Quais são os quatro principais componentes que consomem memória de GPU durante o treinamento?
- Quanta memória um modelo de 7B requer para fine-tuning completo com bf16?
- Qual é o objetivo da acumulação de gradientes?