GPU para la investigación ML · Pago cripto sin KYC
IteraGPU
Entrenamiento · Memoria y optimización

Reducir el microbatch sin perder la cuenta de las actualizaciones.

La acumulación suma las contribuciones de varios pasos hacia atrás antes de una actualización de los parámetros. Con microbatches iguales, el batch efectivo cuenta el microbatch por réplica, el número de pasos acumulados y las réplicas de datos participantes. Reducir el microbatch puede aligerar las activaciones conservadas, pero no elimina ni los pesos ni los estados del optimizador y no garantiza un entrenamiento idéntico.

01 /

Separar microbatch, paso hacia atrás y actualización

El microbatch es el grupo de ejemplos procesado por un paso hacia adelante en una réplica. El paso hacia atrás calcula su contribución a los gradientes. La actualización del optimizador usa los gradientes disponibles para modificar los parámetros. Con acumulación, varios pasos hacia adelante/atrás preceden a esa actualización; los parámetros permanecen sin cambios durante el grupo.

En PyTorch, los gradientes se acumulan en los tensores previstos para ello. Borrar los gradientes después de cada microbatch anularía, por tanto, la acumulación deseada. A la inversa, olvidar ponerlos a cero entre dos grupos haría que contribuyeran ejemplos de la actualización anterior.

Define tu unidad de registro: número de microbatch, actualización del optimizador, ejemplos o tokens vistos. La palabra «step» por sí sola es ambigua. Una curva de pérdida no se compara correctamente si el eje representa ocho veces más ejemplos en uno de los experimentos.

Fuentes técnicas: PyTorch — acumulación y puesta a cero de los gradientes

02 /

Calcular el batch efectivo sin contar dos veces las GPU

Denotemos m el número de ejemplos por microbatch y por réplica, A el número de microbatches acumulados, D el número de réplicas de paralelismo de datos. Si estos tamaños son constantes y los ejemplos se reparten correctamente, el número de ejemplos que contribuyen a una actualización global es m × A × D.

El factor D no designa necesariamente todas las tarjetas de la máquina. Unas GPU que comparten un mismo modelo mediante paralelismo tensorial o de pipeline no se convierten en otras tantas réplicas de datos. Inscribe los grupos realmente configurados, no simplemente la cantidad comercial del lote.

Ejemplo aritmético: dos ejemplos por microbatch, ocho acumulaciones y dos réplicas dan 32 ejemplos por actualización global. Cada réplica procesa dieciséis ejemplos en este grupo. La tabla compara recuentos; no clasifica su memoria o su velocidad.

Batch efectivo en ejemplos = microbatch por réplica m × acumulaciones A × réplicas de datos D
Recuentos ilustrativos, sin medida de rendimiento; microbatches completos y ejemplos repartidos.
mADEjemplos por actualización global
28232
116232
44232
28116

Fuentes técnicas: PyTorch — batch efectivo y acumulación en precisión mixta · PyTorch — comportamiento de las réplicas DistributedDataParallel

03 /

Normalizar la pérdida según los elementos realmente evaluados

Para una pérdida media sobre microbatches que contienen el mismo número de elementos pertinentes, dividir cada contribución por A da la media del grupo. Esta regla supone que el framework no hace ya esta normalización. Con una herramienta que gestiona la acumulación, revisa su contrato antes de añadir una división manual.

Para una pérdida media por token, longitudes diferentes cambian el denominador. Hay que referir la suma de las pérdidas a los tokens efectivamente supervisados del grupo, excluyendo padding y posiciones ignoradas. La media de las medias de microbatches no da generalmente el mismo objetivo.

Ejemplo teórico: un microbatch cuenta con 512 tokens supervisados con una pérdida media de 2; otro cuenta con 1536 con una media de 4. La media ponderada vale (512 × 2 + 1536 × 4) ÷ 2048 = 3,5. La media no ponderada vale 3 y sobrepondera el grupo pequeño. Estos valores ilustran únicamente el cálculo.

Fuentes técnicas: Hugging Face Accelerate — acumulación con ejemplos de tamaños variables

04 /

Organizar un grupo completo de acumulación

Prepara primero las fronteras del grupo y su denominador. Para cada microbatch, calcula la salida, la pérdida normalizada y el paso hacia atrás sin actualización intermedia. Libera las salidas que ya no necesites; conservar pérdidas adjuntas a su grafo en una lista puede prolongar la vida de las asignaciones.

Tras la última contribución, aplica las operaciones previstas sobre el gradiente completo, y luego la actualización. Reinicia después los gradientes para el grupo siguiente. Si el recorrido termina con menos de A microbatches, elige explícitamente tratar ese grupo parcial con su verdadero denominador o descartarlo; anota los ejemplos afectados.

Con una precisión mixta que usa GradScaler, el factor de escala permanece constante durante la acumulación. El reescalado real y un posible clipping intervienen tras las contribuciones; la actualización del scaler sigue al intento de paso. Los controles de valores no finitos pueden impedir la modificación de los parámetros.

El scheduler debe seguir la unidad anunciada por tu bucle. Si está definido por actualización del optimizador, llamarlo en cada microbatch cambiaría el calendario. Registra por separado los intentos y las actualizaciones realmente aplicadas cuando tu sistema pueda saltarse algunas.

Fuentes técnicas: PyTorch — grafos autograd y tensores conservados para backward · PyTorch — acumulación, unscale, clipping y GradScaler

05 /

En multi-GPU, verificar reducción y reparto de los ejemplos

DistributedDataParallel sincroniza los gradientes entre réplicas. En su comportamiento habitual, la reducción los promedia; una pérdida sumada y una pérdida promediada localmente no tienen por tanto la misma escala. Con números de tokens diferentes según las réplicas, el denominador global y esa reducción deben considerarse en conjunto.

Verifica los IDs realmente procesados: duplicar involuntariamente los mismos ejemplos en todas las tarjetas no aumenta en esa medida la información del grupo. Para retrasar las comunicaciones intermedias, puede emplearse no_sync en los microbatches anteriores a la sincronización final; su contexto debe cubrir también el paso hacia adelante.

No traslades esta regla a todos los sistemas distribuidos. El sharding de estados, el pipeline, los hooks de comunicación y los frameworks pueden cambiar las operaciones efectivas. Empieza por la configuración soportada por tu herramienta, y luego controla un grupo completo en cada réplica.

Fuentes técnicas: PyTorch — reducción de gradientes y alcance de no_sync en DDP

06 /

Por qué el mismo batch efectivo no garantiza la misma experiencia

La igualdad m × A × D es un conteo. Para recuperar un gradiente de lote grande, se necesitan en particular contribuciones correctamente ponderadas, el mismo estado de los parámetros durante el grupo y operaciones compatibles con esa descomposición. La proximidad numérica se verifica con una tolerancia adecuada; no se deduce del solo producto.

BatchNorm calcula estadísticas a partir de las entradas de su pasada: varios microbatchs pequeños no le presentan los mismos grupos que un lote grande. Las operaciones aleatorias, el orden de los cálculos y los redondeos también pueden variar. No prometas pesos finales idénticos bit a bit.

Un cambio de lote global también puede modificar el número de actualizaciones para un mismo número de ejemplos vistos. Fija de antemano el eje de comparación y tu regla de calidad. No cambies simultáneamente la tasa de aprendizaje, el scheduler y la duración sin documentar esas nuevas hipótesis.

Fuentes técnicas: PyTorch — estadísticas de BatchNorm1d · PyTorch — límites de reproducibilidad

07 /

Controlar la memoria y decidir lo siguiente

Instrumenta un grupo que incluya las pasadas hacia atrás y la primera actualización, y luego los grupos siguientes. Un éxito en el forward no valida los gradientes ni los estados creados por el optimizador. Los contadores deben conservar su alcance por device. El expediente de memoria proporciona el método de lectura de las baselines y los picos.

Si un grupo falla, reduce el microbatch y recalcula A para conservar el lote efectivo objetivo cuando esa elección siga siendo pertinente. Esta modificación no garantiza ni una división proporcional del pico ni una mejor duración. Si los pesos o los estados dominan, la acumulación por sí sola puede ser insuficiente.

Antes de una campaña, controla una actualización sobre un conjunto pequeño y dominado: los mismos ejemplos, pérdida ponderada, gradientes finitos, frontera de grupo y número de pasos. Luego evalúa la calidad con el protocolo elegido. El pequeño MLP de inferencia del expediente descargable no ejecuta esta receta de entrenamiento; no sustituye este control.

Tu ficha final reúne m, A, D, los tokens supervisados, la precisión, la normalización, el tratamiento del último grupo y los picos observados. Vuelve después a la elección de configuración y al presupuesto de experimentos, separando preparación, ensayos y resultados realmente aceptados.

  • Pérdida anormalmente pequeña: busca una doble división por la acumulación.
  • Resultado que varía con el fraccionamiento: verifica tokens ignorados y promedio de promedios.
  • Acumulación sin efecto: controla zero_grad y optimizer.step.
  • Memoria creciente: busca las referencias conservadas entre microbatchs.
  • Calendario desfasado: distingue pasadas hacia atrás y actualizaciones.

Fuentes técnicas: Hugging Face — partidas de memoria de un entrenamiento

Preguntas prácticas

¿Acumular dieciséis microbatchs multiplica la memoria por dieciséis?

No necesariamente: las contribuciones se procesan sucesivamente. Los gradientes persisten, mientras que las activaciones inútiles pueden liberarse. Sin embargo, el pico depende del modelo, de las referencias conservadas y de los estados del optimizador; mide el grupo completo.

¿Dos GPU duplican siempre el lote efectivo?

Solo si esas GPU participan como dos réplicas de datos con el microbatch anunciado. Unas tarjetas que comparten un mismo modelo no constituyen automáticamente dos réplicas. Verifica los grupos distribuidos y los ejemplos procesados.

¿Puedo dividir todas las pérdidas por el número de acumulaciones?

Esa regla simple corresponde a microbatchs de igual peso, sin normalización ya gestionada por el framework. Con números variables de tokens supervisados o un último grupo incompleto, usa el denominador real del objetivo.