Modelos y plataformas de IA

OptimizaciÃģn de la memoria para inferencia y ajuste fino de modelos de lenguaje grande

mm
AÃąade Unite.AI a tus fuentes preferidas en Google

Los modelos de lenguaje grande (LLM) como GPT-4, Bloom y LLaMA han logrado capacidades notables al escalar hasta miles de millones de parÃĄmetros. Sin embargo, desplegar estos modelos masivos para inferencia o ajuste fino es un desafío debido a sus enormes requisitos de memoria. En este blog tÃĐcnico, exploraremos tÃĐcnicas para estimar y optimizar el consumo de memoria durante la inferencia y el ajuste fino de LLM en varios entornos de hardware.

ComprensiÃģn de los requisitos de memoria

La memoria necesaria para cargar un LLM se determina principalmente por la cantidad de parÃĄmetros y la precisiÃģn numÃĐrica utilizada para almacenar los parÃĄmetros. Una regla general es:

  • Cargar un modelo con X mil millones de parÃĄmetros requiere aproximadamente 4X GB de VRAM en precisiÃģn de 32 bits float
  • Cargar un modelo con X mil millones de parÃĄmetros requiere aproximadamente 2X GB de VRAM en precisiÃģn de 16 bits bfloat16/float16

Por ejemplo, cargar el modelo GPT-3 de 175 mil millones de parÃĄmetros requeriría aproximadamente 350 GB de VRAM en precisiÃģn bfloat16. Actualmente, las GPU mÃĄs grandes disponibles comercialmente, como la NVIDIA A100 y H100, ofrecen solo 80 GB de VRAM, lo que hace necesarias tÃĐcnicas de paralelismo de tensor y paralelismo de modelo.

Durante la inferencia, la huella de memoria estÃĄ dominada por los parÃĄmetros del modelo y los tensores de activaciÃģn temporales producidos. Una estimaciÃģn de alto nivel para el uso mÃĄximo de memoria durante la inferencia es la suma de la memoria necesaria para cargar los parÃĄmetros del modelo y la memoria para las activaciones.

CuantificaciÃģn de la memoria de inferencia

Veamos los requisitos de memoria para la inferencia utilizando el modelo OctoCode, que tiene alrededor de 15 mil millones de parÃĄmetros en formato bfloat16 (~ 31 GB). Utilizaremos la biblioteca Transformers para cargar el modelo y generar texto:

from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
import torch

<p>model = AutoModelForCausalLM.from_pretrained(&quot;bigcode/octocoder&quot;,
torch_dtype=torch.bfloat16,
device_map=&quot;auto&quot;,
pad_token_id=0)
tokenizer = AutoTokenizer.from_pretrained(&quot;bigcode/octocoder&quot;)
pipe = pipeline(&quot;text-generation&quot;, model=model, tokenizer=tokenizer)</p>

<p>prompt = &quot;Pregunta: Por favor, escriba una funciÃģn de Python para convertir bytes a gigabytes.\n\nRespuesta:&quot;
result = pipe(prompt, max_new_tokens=60)[0][&quot;generated_text&quot;][len(prompt):]</p>

<p>def bytes_to_gigabytes(bytes):
return bytes / 1024 / 1024 / 1024</p>

<p>bytes_to_gigabytes(torch.cuda.max_memory_allocated())

Salida:

29.0260648727417

El uso mÃĄximo de memoria de la GPU es de aproximadamente 29 GB, lo que coincide con nuestra estimaciÃģn de 31 GB para cargar los parÃĄmetros del modelo en formato bfloat16.

OptimizaciÃģn de la memoria de inferencia con cuantizaciÃģn

Si bien bfloat16 es la precisiÃģn comÚn utilizada para entrenar LLM, los investigadores han encontrado que cuantizar los pesos del modelo a tipos de datos de precisiÃģn mÃĄs baja como enteros de 8 bits (int8) o enteros de 4 bits puede reducir significativamente el uso de memoria con una pÃĐrdida mínima de precisiÃģn para tareas de inferencia como la generaciÃģn de texto.

Veamos los ahorros de memoria de la cuantizaciÃģn de 8 bits y 4 bits del modelo OctoCode:

&amp;lt;/div&amp;gt;
# CuantizaciÃģn de 8 bits
model = AutoModelForCausalLM.from_pretrained(&quot;bigcode/octocoder&quot;, load_in_8bit=True,
pad_token_id=0)
pipe = pipeline(&quot;text-generation&quot;, model=model, tokenizer=tokenizer)
result = pipe(prompt, max_new_tokens=60)[0][&quot;generated_text&quot;][len(prompt):]
bytes_to_gigabytes(torch.cuda.max_memory_allocated())&lt;/pre&gt;
Salida:
15.219234466552734
# CuantizaciÃģn de 4 bits
model = AutoModelForCausalLM.from_pretrained(&quot;bigcode/octocoder&quot;, load_in_4bit=True,
low_cpu_mem_usage=True, pad_token_id=0)
pipe = pipeline(&quot;text-generation&quot;, model=model, tokenizer=tokenizer)
result = pipe(prompt, max_new_tokens=60)[0][&quot;generated_text&quot;][len(prompt):]
bytes_to_gigabytes(torch.cuda.max_memory_allocated())

Salida:

9.543574333190918

Con la cuantizaciÃģn de 8 bits, el requisito de memoria disminuye de 31 GB a 15 GB, mientras que la cuantizaciÃģn de 4 bits lo reduce aÚn mÃĄs a solo 9,5 GB. Esto permite ejecutar el modelo OctoCode de 15 mil millones de parÃĄmetros en GPUs de consumo como la RTX 3090 (24 GB de VRAM).

Sin embargo, tenga en cuenta que la cuantizaciÃģn mÃĄs agresiva como la de 4 bits puede llevar a una degradaciÃģn de la precisiÃģn en comparaciÃģn con la precisiÃģn de 8 bits o bfloat16. Hay un equilibrio entre ahorro de memoria y precisiÃģn que los usuarios deben evaluar para su caso de uso.

La cuantizaciÃģn es una tÃĐcnica poderosa que puede permitir el despliegue de LLM en entornos con recursos limitados como instancias en la nube, dispositivos de borde o incluso telÃĐfonos mÃģviles al reducir drÃĄsticamente la huella de memoria.

EstimaciÃģn de la memoria para el ajuste fino

Mientras que la cuantizaciÃģn se utiliza principalmente para la inferencia eficiente, tÃĐcnicas como el paralelismo de tensor y el paralelismo de modelo son cruciales para gestionar los requisitos de memoria durante el entrenamiento o ajuste fino de modelos de lenguaje grande.

El consumo mÃĄximo de memoria durante el ajuste fino es generalmente 3-4 veces mayor que el de la inferencia debido a los requisitos de memoria adicionales para:

  • Gradientes
  • Estados del optimizador
  • Activaciones de la pasada hacia adelante almacenadas para la retropropagaciÃģn

Una estimaciÃģn conservadora es que el ajuste fino de un LLM con X mil millones de parÃĄmetros requiere alrededor de 4 * (2X) = 8X GB de VRAM en precisiÃģn bfloat16.

Por ejemplo, el ajuste fino del modelo LLaMA de 7 mil millones de parÃĄmetros requeriría aproximadamente 7 * 8 = 56 GB de VRAM por GPU en precisiÃģn bfloat16. Esto supera la capacidad de memoria de las GPUs actuales, lo que hace necesarias tÃĐcnicas de ajuste fino distribuido.

TÃĐcnicas de ajuste fino distribuido

Se han propuesto varios mÃĐtodos de ajuste fino distribuido para superar las limitaciones de memoria de la GPU para modelos grandes:

  1. Paralelismo de datos: El enfoque clÃĄsico de paralelismo de datos replica el modelo completo en varias GPUs mientras divide y distribuye los lotes de datos de entrenamiento. Esto reduce el tiempo de entrenamiento linealmente con la cantidad de GPUs, pero no reduce el requisito de memoria mÃĄximo en cada GPU.
  2. ZeRO Stage 3: Una forma avanzada de paralelismo de datos que divide los parÃĄmetros del modelo, los gradientes y los estados del optimizador en las GPUs. Reduce la memoria en comparaciÃģn con el paralelismo de datos clÃĄsico al mantener solo los datos particionados necesarios en cada GPU durante las diferentes fases del entrenamiento.
  3. Paralelismo de tensor: En lugar de replicar el modelo, el paralelismo de tensor divide los parÃĄmetros del modelo en filas o columnas y los distribuye en las GPUs. Cada GPU opera en un conjunto particionado de parÃĄmetros, gradientes y estados del optimizador, lo que lleva a un ahorro de memoria sustancial.
  4. Paralelismo de tubería: Esta tÃĐcnica divide las capas del modelo en diferentes GPUs/trabajadores, con cada dispositivo ejecutando un subconjunto de las capas. Las activaciones se pasan entre los trabajadores, lo que reduce la memoria mÃĄxima pero aumenta la sobrecarga de comunicaciÃģn.

Estimar el uso de memoria para estos mÃĐtodos distribuidos es no trivial, ya que la distribuciÃģn de parÃĄmetros, gradientes, activaciones y estados del optimizador varía entre tÃĐcnicas. AdemÃĄs, diferentes componentes como el cuerpo del transformador y la cabeza de modelado de lenguaje pueden exhibir diferentes comportamientos de asignaciÃģn de memoria.

La soluciÃģn LLMem

Los investigadores han propuesto recientemente LLMem, una soluciÃģn que estima con precisiÃģn el consumo de memoria de la GPU cuando se aplican mÃĐtodos de ajuste fino distribuido a LLM en varias GPUs.

EstimaciÃģn del uso de memoria de la GPU para el ajuste fino de LLM preentrenados

EstimaciÃģn del uso de memoria de la GPU para el ajuste fino de LLM preentrenados

LLMem considera factores como la recombinaciÃģn de parÃĄmetros antes del cÃĄlculo (ZeRO Stage 3), la recopilaciÃģn de salidas en la pasada hacia atrÃĄs (paralelismo de tensor) y las diferentes estrategias de asignaciÃģn de memoria para el cuerpo del transformador y la cabeza de modelado de lenguaje.

Los resultados experimentales muestran que LLMem puede estimar el uso mÃĄximo de memoria de la GPU para el ajuste fino de LLM en una sola GPU con tasas de error de hasta 1,6%, superando la tasa de error promedio de 42,6% de DNNMem. Cuando se aplican mÃĐtodos de ajuste fino distribuido a LLM con mÃĄs de mil millones de parÃĄmetros en varias GPUs, LLMem logra una tasa de error promedio de 3,0%.

Al estimar con precisiÃģn los requisitos de memoria de antemano, LLMem puede ayudar a los usuarios a seleccionar la configuraciÃģn de ajuste fino mÃĄs eficiente que evite problemas de memoria agotada mientras minimiza el tiempo de entrenamiento.

TÃĐcnicas emergentes

Mientras que la cuantizaciÃģn, el paralelismo de tensor y el paralelismo de modelo son tÃĐcnicas establecidas, los investigadores siguen explorando mÃĐtodos novedosos para impulsar la eficiencia en el entrenamiento y despliegue de LLM.

  1. LoRA y QLoRA: Estas tÃĐcnicas implican entrenar un mÃģdulo de adaptador residual mÃĄs pequeÃąo para actualizar el LLM preentrenado con nuevos conocimientos en lugar de ajustar directamente la gran cantidad de parÃĄmetros. Esto puede llevar a un ahorro de memoria sustancial mientras se mantiene la mayoría del rendimiento del modelo.
  2. FlashAttention: El mecanismo de autoatenciÃģn es un cuello de botella de memoria y cÃĄlculo en los modelos de transformador. FlashAttention aproxima la atenciÃģn estÃĄndar con complejidad lineal, reduciendo los requisitos de memoria de cuadrÃĄtica a lineal en la longitud de la secuencia de entrada.
  3. Mixture-of-Experts: Este enfoque enruta condicionalmente cada muestra de datos de entrada a un modelo de experto especializado en lugar de procesarla a travÃĐs de todo el modelo. Esta espacialidad dinÃĄmica puede ahorrar memoria al activar solo un subconjunto de expertos para cada muestra.
  4. Cirugía de modelo revertida: Los investigadores han explorado la compresiÃģn de modelos quirÚrgicos mediante la eliminaciÃģn iterativa de componentes menos importantes como cabezas de atenciÃģn para intercambiar memoria/velocidad por precisiÃģn.
  5. Descarga: Finalmente, las tÃĐcnicas que descargan parÃĄmetros, estados del optimizador o activaciones en la RAM de la CPU o en disco pueden complementar la memoria limitada de la GPU para modelos grandes.

Estos mÃĐtodos de vanguardia ilustran el ecosistema de investigaciÃģn vibrante centrado en democratizar el entrenamiento y despliegue eficientes de LLM en diversos entornos de hardware.

ConclusiÃģn

Los requisitos de memoria de los modelos de lenguaje grande plantean desafíos significativos para su adopciÃģn generalizada en aplicaciones del mundo real. Al comprender las tÃĐcnicas de estimaciÃģn de memoria y aprovechar la cuantizaciÃģn, las estrategias de entrenamiento distribuido y las innovaciones emergentes, podemos optimizar los despliegues de LLM en dispositivos con recursos limitados.

Herramientas como LLMem allanan el camino hacia la estimaciÃģn precisa de la memoria, lo que permite a los usuarios seleccionar la configuraciÃģn de ajuste fino mÃĄs adecuada. A medida que evoluciona el hardware y avanza la investigaciÃģn, podemos anticipar un entrenamiento y una inferencia de LLM mÃĄs eficientes, lo que impulsarÃĄ el progreso en el procesamiento de lenguaje natural y la inteligencia artificial.

Encontrar el equilibrio adecuado entre la capacidad del modelo, la precisiÃģn y la utilizaciÃģn de recursos serÃĄ crucial para desbloquear todo el potencial de los modelos de lenguaje grande en diversos dominios y casos de uso. Al adoptar tÃĐcnicas de optimizaciÃģn de memoria, nos acercamos a un futuro en el que la inteligencia de lenguaje de vanguardia es accesible, escalable y sostenible.

He dedicado los Últimos cinco aÃąos sumergiÃĐndome en el fascinante mundo de Machine Learning y Deep Learning. Mi pasiÃģn y experiencia me han llevado a contribuir a mÃĄs de 50 proyectos de ingeniería de software diversos, con un enfoque particular en AI/ML. Mi curiosidad en curso tambiÃĐn me ha llevado hacia el Procesamiento de Lenguaje Natural, un campo que estoy ansioso por explorar mÃĄs a fondo.