Capítulo 2: Requisitos Computacionales
Cálculo de Memoria de GPU y Costos de Entrenamiento
Comprender los requisitos computacionales para el fine-tuning es crucial para planificar sus proyectos y elegir el enfoque adecuado.
Componentes de Memoria de GPU
Durante el entrenamiento, la memoria de la GPU es consumida por cuatro componentes principales:
1. Pesos del Modelo
Los parámetros del propio modelo.
2. Gradientes
Mismo tamaño que los pesos—almacena el gradiente para cada parámetro.
3. Estados del Optimizador
AdamW almacena 2 estados (momento, varianza) por parámetro.
4. Activaciones
Valores intermedios necesarios para la retropropagación.
Fórmula de Cálculo de Memoria
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)
Tamaños de Precisión
| Precisión | Bytes por Parámetro |
|---|---|
| float32 | 4 |
| bfloat16 | 2 |
| float16 | 2 |
| int8 | 1 |
| int4 | 0.5 |
Requisitos de Memoria para Fine-Tuning Completo
Ejemplo: Modelo de 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
Tabla de Requisitos de Memoria
| Tamaño del Modelo | Full FT (fp32) | Full FT (bf16) | Con 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 |
Reducción de Requisitos de Memoria
1. Entrenamiento con Precisión Mixta
training_args = TrainingArguments(
bf16=True, # Use bfloat16
)
Reduce la memoria de pesos y gradientes en ~50%.
2. Gradient Checkpointing
training_args = TrainingArguments(
gradient_checkpointing=True,
)
# OR
model.gradient_checkpointing_enable()
Intercambia cómputo por memoria—recalcula activaciones durante la pasada hacia atrás.
3. Acumulación de Gradientes
training_args = TrainingArguments(
per_device_train_batch_size=1,
gradient_accumulation_steps=16,
# Effective batch size = 1 * 16 = 16
)
Lotes más pequeños usan menos memoria; acumule gradientes para simular lotes más grandes.
4. Optimizadores Eficientes en Memoria
# 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",
)
Etapas de ZeRO:
- Stage 1: Particiona los estados del optimizador
- Stage 2: + Particiona los gradientes
- Stage 3: + Particiona los pesos del modelo (permite entrenar modelos más grandes que la memoria de la GPU)
Recomendaciones Prácticas de GPU
Entrenamiento en una Sola GPU
| GPU | VRAM | Modelo Máx. (Full FT) | Modelo Máx. (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 |
Entrenamiento Multi-GPU
# Automatic distribution with accelerate
from accelerate import Accelerator
accelerator = Accelerator()
model, optimizer, dataloader = accelerator.prepare(
model, optimizer, dataloader
)
| Configuración | VRAM Combinada | Modelo Máx. (Eficiente) |
|---|---|---|
| 2× A100-40GB | 80 GB | 7-13B |
| 4× A100-80GB | 320 GB | 30-40B |
| 8× H100 | 640 GB | 70B |
Estimación del Tiempo de Entrenamiento
Factores que Afectan el Tiempo de Entrenamiento
Training Time = (Dataset Size × Epochs) / (Batch Size × Throughput)
Ejemplos 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 |
Ejemplo de Cálculo de Tiempo
# 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
Estimación de Costos en la Nube
Precios 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 |
Ejemplo de Cálculo de Costos
# 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)
Perfilado de Memoria
Verificar el Uso Actual de Memoria
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()
Estimar Antes de Entrenar
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
Lista de Verificación de Optimización
□ Habilite precisión mixta (bf16/fp16)
□ Habilite gradient checkpointing
□ Use acumulación de gradientes para lotes efectivos más grandes
□ Considere optimizadores de 8 bits
□ Use DeepSpeed para multi-GPU
□ Monitoree la memoria con perfilado
□ Use instancias spot para ahorrar costos
Puntos Clave
✅ El fine-tuning completo requiere ~4-6x el tamaño del modelo en memoria de GPU
✅ Un modelo de 7B necesita 60-80GB para fine-tuning completo
✅ La precisión mixta y el gradient checkpointing reducen significativamente la memoria
✅ El entrenamiento multi-GPU permite modelos más grandes
✅ Los costos en la nube pueden reducirse 60-70% usando instancias spot
✅ Siempre perfile la memoria antes de comprometerse a entrenamientos largos
Próximos Pasos
Continúe a Capítulo 3: Olvido Catastrófico para aprender sobre la retención de conocimiento durante el fine-tuning.
Verificación Rápida
Antes de continuar, asegúrese de poder responder:
- ¿Cuáles son los cuatro componentes principales que consumen memoria de GPU durante el entrenamiento?
- ¿Cuánta memoria requiere un modelo de 7B para fine-tuning completo con bf16?
- ¿Cuál es el propósito de la acumulación de gradientes?