Checkpointing estilo Unsloth¶
Resumen corto: úsalo cuando el job casi cabe, y prueba FFN-only primero si el modelo lo soporta.
El backend unsloth descarga activaciones guardadas a CPU. El backend torch las descarta y las recalcula en backward. Unsloth puede comprar los últimos GiB para subir batch, resolución o frames. No es velocidad gratis. Si el run ya cabe con torch, normalmente torch sigue siendo el mejor default.
Controles¶
gradient_checkpointing_backend tiene cuatro valores útiles:
| Valor | Scope | Ruta | Cuándo usarlo |
|---|---|---|---|
torch |
bloque completo | recompute | Necesitas el mayor ahorro integrado antes de CPU offload. |
torch-ffn |
feed-forward | recompute | Quieres el win barato después de que Flash Attention ya cubrió attention memory. |
unsloth |
bloque completo | CPU offload | Torch layer checkpointing aún no cabe. |
unsloth-ffn |
feed-forward | CPU offload | FFN-only con torch casi cabe y CPU offload puede comprar el resto. |
En familias compatibles también puedes checkpointar menos bloques:
{
"gradient_checkpointing": true,
"gradient_checkpointing_backend": "torch-ffn",
"gradient_checkpointing_interval": 2
}
gradient_checkpointing_interval: 2 checkpointa chunks contiguos de dos bloques en rutas de bloque completo compatibles. Valores más altos recomputan menos y dejan más activaciones en VRAM.
En esas rutas segmentadas, gradient_checkpointing_segment_stride también funciona con unsloth. Trátalo como una palanca para caber, no para acelerar: los bloques saltados se quedan en GPU, mientras los bloques checkpointed siguen usando CPU offload para tensores guardados. Para el resumen con torch y benchmarks por modelo, consulta Segmented Checkpointing.
gradient_checkpointing_offload_attention es independiente del backend. En bloques compatibles con separación attention/FFN, descarga las activaciones guardadas del lado attention. Puede ejecutarse solo o combinarse con torch, torch-ffn, unsloth o unsloth-ffn cuando el modelo soporte ese backend.
gradient_checkpointing_offload_pin_memory_max_buckets controla el pooling de CPU pinned para tensores guardados offloaded. El valor predeterminado es 12 buckets de tensor distintos; usa 0 para usar solo memoria CPU normal.
torch-ffn y unsloth-ffn soportan actualmente Chroma, Flux, Krea 2, LTXVideo2, MageFlow, Wan y Z-Image. Otras familias fallan claramente hasta que sus bloques expongan el mismo límite seguro.
Qué intercambia¶
torch: descarta activaciones intermedias y las recalcula en backward.unsloth: guarda parte de esos tensores en CPU y los copia de vuelta para backward.*-ffn: checkpointa solo el lado feed-forward en modelos con un límite FFN limpio.- Flash Attention ya evita materializar la matriz grande de atención. Esa idea de "checkpointing gratis" aplica sobre todo a atención, no a todo el bloque transformer.
- CPU offload ayuda más cuando las activaciones son grandes y el pico no viene de parámetros u optimizer.
Requiere CUDA y suficiente RAM de CPU. El ancho de banda PCIe importa. Si las copias CPU-GPU quedan expuestas, el step se vuelve más lento.
Nuestro sweep¶
Bloque transformer sintético, bf16, flash SDPA, pesos base congelados, batch 1. No son garantías de modelo; enseñan la forma del tradeoff.
Latents de imagen empaquetados¶
Con empaquetado 2x2, 64x64, 128x128 y 256x256 pasan a 1024, 4096 y 16384 tokens.
| GPU | Tokens | Sin checkpoint | Torch FFN | Unsloth FFN | Torch layer | Unsloth layer |
|---|---|---|---|---|---|---|
| H100 80GB | 1024 | 0.0166s / 4.43 GiB | 0.0191s / 4.08 GiB | 0.0233s / 4.00 GiB | 0.0231s / 3.64 GiB | 0.0265s / 3.56 GiB |
| H100 80GB | 4096 | 0.0948s / 7.43 GiB | 0.1029s / 6.02 GiB | 0.1157s / 5.67 GiB | 0.1233s / 4.26 GiB | 0.1358s / 3.93 GiB |
| H100 80GB | 16384 | 0.8781s / 19.39 GiB | 0.9117s / 13.77 GiB | 0.9632s / 12.36 GiB | 1.1157s / 6.72 GiB | 1.1662s / 5.41 GiB |
| L40S | 1024 | 0.0500s / 4.39 GiB | 0.0575s / 4.04 GiB | 0.0627s / 3.95 GiB | 0.0666s / 3.60 GiB | 0.0725s / 3.51 GiB |
| L40S | 4096 | 0.2461s / 7.38 GiB | 0.2729s / 5.97 GiB | 0.2933s / 5.62 GiB | 0.3169s / 4.21 GiB | 0.3369s / 3.88 GiB |
| L40S | 16384 | 1.8153s / 19.35 GiB | 1.9639s / 13.72 GiB | 2.0250s / 12.31 GiB | 2.3360s / 6.67 GiB | 2.4218s / 5.36 GiB |
En 1024 tokens, el offload extra casi no importa salvo que ya estés al límite. En 16384 tokens, torch-ffn es el paso barato y whole-layer checkpointing es la palanca grande para caber. unsloth compra alrededor de 1.3 GiB más que torch layer checkpointing.
Transformer más grande¶
32 capas congeladas, ancho 4096, 3072 tokens:
| GPU | Sin checkpoint | Torch FFN | Unsloth FFN | Torch layer | Unsloth layer |
|---|---|---|---|---|---|
| H100 80GB | 0.1943s / 14.56 GiB | 0.2138s / 11.65 GiB | 0.2317s / 10.92 GiB | 0.2527s / 8.01 GiB | 0.2722s / 7.30 GiB |
| L40S | 0.5045s / 14.51 GiB | 0.5640s / 11.60 GiB | 0.5932s / 10.88 GiB | 0.6491s / 7.96 GiB | 0.6864s / 7.26 GiB |
Con pesos completos entrenables, gradientes y optimizer dominaron el pico, así que unsloth no ahorró más que torch en ese run sintético. PEFT se parece más al caso de pesos congelados.
Regla práctica¶
- Si cabe sin checkpointing, déjalo apagado.
- Si no cabe, prueba
gradient_checkpointing_backend: torch-ffn. - Si sigue muy justo, prueba
torch. - Si torch layer checkpointing aún no cabe, prueba
unsloth-ffny luegounsloth. - Si el modelo soporta
gradient_checkpointing_interval, usa2o más solo después de que el run ya quepa y quieras recuperar velocidad.
Vale la pena cuando permite usar el batch, resolución, frames o rank que querías. No vale mucho para tokens pequeños ni cuando el pico viene de pesos entrenables, gradientes, optimizer, caché VAE o validación.
Notas¶
- Con FSDP activation checkpointing, SimpleTuner desactiva el checkpointing de modelo para evitar conflictos.
torch-ffnyunsloth-ffnrequieren soporte del modelo. SimpleTuner falla de forma explícita en vez de ejecutar otro scope en silencio.gradient_checkpointing_interval: 1equivale al checkpointing normal de cada bloque.- Algunas familias no tienen interval checkpointing. SimpleTuner avisa e ignora el intervalo.
torch.compileno rescató el camino de offload en nuestro sweep.