BookinglyTech News
Inteligencia artificial

Cuatro técnicas para entrenar un LLM de 7B en GPUs de 24 GB

Los pesos en FP16 de un 7B ocupan 14 GB y los estados de AdamW añaden unos 56 GB: la memoria se agota antes del primer paso. Estas son las vías para esquivarlo.

3 min de lecturaKDnuggets0 vistas

Un modelo de 7.000 millones de parámetros en FP16 o BF16 ocupa 14 GB de VRAM solo en pesos. Si se le suman los dos momentos en FP32 que mantiene AdamW por parámetro —8 bytes cada uno, alrededor de 56 GB en un 7B—, los gradientes de la pasada hacia atrás (otros 14 GB en FP16) y la memoria de activaciones, que crece con la longitud de contexto, el entrenamiento se cae por falta de memoria antes de completar el primer paso. Es el escenario habitual en equipos con dos o cuatro GPUs de estación de trabajo, entre 24 y 48 GB por tarjeta y ancho de banda PCIe de consumo.

La salida pasa por separar la memoria estática (pesos, estados del optimizador y gradientes persistentes) de la transitoria (mapas de activación intermedios y buffers), y por identificar si el cuello de botella está en los Tensor Cores o en el tráfico de lectura y escritura contra la VRAM.

Cuantizar la base y entrenar solo el delta

QLoRA congela los pesos en una representación de 4 bits NormalFloat (NF4), ajustada a distribuciones normales, e inyecta matrices de descomposición de bajo rango y precisión completa en las proyecciones de atención y feed-forward. La cuantización doble va un paso más allá y cuantiza también las constantes de cuantización, lo que ahorra 0,37 bits por parámetro. En cada pasada hacia delante los pesos base se desquantizan a BF16, se les suma la actualización ΔW = B·A y se descartan de caché.

DoRA extiende la idea separando magnitud y dirección en la actualización, para acercarse a las trayectorias de gradiente de un ajuste completo. El precio: la desquantización dinámica se come entre un 20% y un 35% del rendimiento medido en tokens por segundo, y fusionar el adaptador con la base para servir sin latencia extra obliga a volver a 16 bits.

Optimizadores de bajo rango y reparto entre VRAM y RAM

GaLore no congela nada: proyecta el gradiente completo en un subespacio de bajo rango con descomposición en valores singulares (SVD) y guarda los momentos solo para esas matrices proyectadas, en lugar de para todos los parámetros. Las proyecciones se recalculan cada T pasos, no en cada iteración, para amortizar el coste del SVD. El problema es doble: esas factorizaciones periódicas introducen pausas que disparan la latencia por paso, y elegir mal T o el rango de corte desestabiliza la optimización hasta hacer divergir la pérdida a mitad de entrenamiento.

FSDP con ZeRO-3 reparte estados del optimizador, gradientes y parámetros entre la VRAM disponible y la RAM del host. Cada GPU guarda 1/N del estado completo y reconstruye los pesos de cada capa con un all-gather justo antes de calcular, liberándolos al pasar a la siguiente. Con offload a host, los fragmentos inactivos viven en RAM fijada y viajan por PCIe mediante streams asíncronos. Ahí está el límite: si el cómputo acaba antes que la transferencia, las SM se quedan esperando y la utilización de GPU cae por debajo del 30%. A eso se suma que la contención del bus compite con los procesos que sirven los lotes desde NVMe. Tiene sentido cuando el modelo no cabe ni sumando toda la VRAM del nodo.

Queda una cuarta vía, el checkpointing selectivo de activaciones, que descarta tensores intermedios durante la pasada hacia delante y los recalcula en la hacia atrás. Las tres anteriores responden a la misma lógica: trasladar el coste de la memoria al cómputo o al bus PCIe. Ninguna sale gratis, y la elección depende de si al equipo le sobran Tensor Cores o le sobra tiempo.