talón Acelerar la inferencia de modelos de lenguaje grande: técnicas para una implementación eficiente - Unite.AI
Contáctanos

Ingeniería rápida

Acelerar la inferencia de modelos de lenguaje grande: técnicas para una implementación eficiente

mm

Publicado

 on

Acelerar la inferencia de LLM

Modelos de lenguajes grandes (LLM) como GPT-4, Llamay PaLM están superando los límites de lo que es posible con el procesamiento del lenguaje natural. Sin embargo, implementar estos modelos masivos en entornos de producción presenta desafíos importantes en términos de requisitos computacionales, uso de memoria, latencia y costo. A medida que los LLM continúan creciendo y adquiriendo más capacidades, optimizar su rendimiento de inferencia es fundamental para las aplicaciones del mundo real.

En esta inmersión técnica profunda, exploraremos técnicas de vanguardia para acelerar la inferencia LLM, lo que permite tiempos de respuesta más rápidos, mayor rendimiento y una utilización más eficiente de los recursos de hardware. Cubriremos métodos que van desde técnicas de precisión numérica y mecanismos de atención novedosos hasta innovaciones arquitectónicas diseñadas explícitamente para la generación de texto eficiente.

Comencemos por comprender por qué la inferencia LLM es tan desafiante en comparación con los modelos tradicionales de PNL.

El desafío de la inferencia con modelos de lenguaje grandes

Antes de la llegada de los LLM, el procesamiento del lenguaje natural se basaba en modelos más pequeños centrados en tareas específicas como clasificación de texto, reconocimiento de entidades con nombre y análisis de sentimientos. Si bien todavía requieren una gran cantidad de computación, estos modelos podrían implementarse en hardware modesto y seguir procesos de inferencia relativamente sencillos.

Los LLM, por otro lado, representan un cambio de paradigma. Estos modelos se entrenan en vastos conjuntos de datos utilizando miles de millones de parámetros, lo que les permite realizar una amplia gama de tareas lingüísticas con un dominio notable. Sin embargo, este poder tiene un costo: demandas computacionales dramáticamente incrementadas durante el entrenamiento y la inferencia.

Un desafío clave es la naturaleza autorregresiva de la generación de texto con los LLM. Para producir texto similar al humano, estos modelos predicen un token (palabra o subpalabra) a la vez, y cada nuevo token depende de la salida generada previamente. Esta dependencia secuencial impide la paralelización eficiente y da como resultado requisitos computacionales que escalan polinomialmente con la longitud de la secuencia.

Además, los LLM a menudo requieren largas secuencias de entrada (indicaciones) para establecer el contexto necesario para la generación de texto de alta calidad. Las longitudes de entrada más largas exigen más memoria para almacenar estados intermedios y matrices de atención, lo que agota aún más los recursos de hardware.

Con estos desafíos únicos, las técnicas de optimización tradicionales, como la cuantificación y los gráficos de cálculo estático, pueden quedarse cortas y tener dificultades para mantener el rendimiento del LLM y, al mismo tiempo, ofrecer aceleraciones significativas. Profundicemos en algunas de las estrategias clave diseñadas explícitamente para acelerar la inferencia LLM.

Técnicas de precisión numérica

De precisión de 32 bits a 16 bits

De precisión de 32 bits a 16 bits

Una vía para acelerar LLM La inferencia es aprovechar la precisión numérica reducida para los pesos y activaciones del modelo. Los marcos modernos de aprendizaje profundo como PyTorch y TensorFlow suelen emplear precisión de punto flotante de 32 bits (FP32) de forma predeterminada. Sin embargo, las investigaciones han demostrado que los LLM a menudo pueden mantener una alta precisión incluso cuando operan con precisiones más bajas, como 16 bits (FP16), enteros de 8 bits (INT8) o incluso enteros de 4 bits (INT4).

Reducir la precisión numérica ofrece varios beneficios:

  • Huella de memoria reducida: Las representaciones de menor precisión requieren menos memoria, lo que permite que modelos o tamaños de lotes más grandes se ajusten a las mismas limitaciones de hardware.
  • Computación más rápida: Muchas CPU y GPU modernas proporcionan instrucciones especializadas y aceleración de hardware para aritmética de menor precisión, lo que permite aceleraciones significativas.
  • Eficiencia Energética Mejorada: Con menores requisitos de memoria y cálculos más rápidos, una inferencia de menor precisión puede traducirse en un menor consumo de energía, una ventaja crucial para las implementaciones móviles y de borde.

Si bien son potentes, las técnicas de precisión numérica introducen cierta pérdida de precisión en comparación con el funcionamiento del FP32. La clave es evaluar cuidadosamente esta compensación entre ganancias computacionales y una posible degradación del rendimiento para su caso de uso específico.

Hay dos enfoques principales para la cuantificación con LLM:

Cuantización post-entrenamiento (PTQ): En este método, primero se entrena un LLM utilizando la precisión estándar FP32. Después del entrenamiento, los pesos del modelo se cuantifican (convierten) a un formato de menor precisión como INT8 o INT4. PTQ es sencillo de implementar, pero puede provocar mayores caídas de precisión.

Entrenamiento consciente de la cuantificación (QAT): Con QAT, el proceso de cuantificación se simula durante la propia fase de entrenamiento. Esto permite que el modelo aprenda a compensar los errores de cuantificación, minimizando la degradación de la precisión cuando se implementa el modelo cuantificado final. QAT es más complicado pero a menudo produce mejores resultados en comparación con PTQ.

Para una aplicación práctica, se podrían aprovechar los modelos precuantizados disponibles en plataformas como Abrazando la cara, que alberga una variedad de modelos optimizados mediante diferentes métodos de cuantificación. Por ejemplo, si se desea un modelo cuantificado usando Auto-GPTQ, los usuarios pueden cargarlo fácilmente usando la biblioteca de transformadores de Hugging Face. Además, para cuantificar un modelo, se pueden utilizar herramientas como AutoGPTQ, que se integran perfectamente con las bibliotecas existentes para comprimir el modelo de manera eficiente.

A continuación se muestra un ejemplo de carga de un modelo Llama-2-7b precuantizado utilizando la biblioteca de transformadores Hugging Face:

from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "TheBloke/Llama-2-7b-Chat-GPTQ"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)
And for custom quantization, one might follow these steps using the AutoGPTQ toolkit:
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "llama-2-7b-original"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = GPTQConfig(bits=4, dataset="your-dataset", tokenizer=tokenizer)
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=quantization_config)

Recuerde que la cuantificación puede requerir un ajuste posterior a la cuantificación o una ingeniería rápida para mantener la calidad del modelo. Para una nueva cuantificación, puede contribuir a la comunidad enviando sus modelos cuantificados a plataformas como Hugging Face.

Asegúrese siempre de equilibrar el tamaño del modelo, los requisitos computacionales y el rendimiento al seleccionar la estrategia de cuantificación para su caso de uso específico.

 

El algoritmo de atención flash

El mecanismo de atención de múltiples cabezales es un componente central de los LLM basados ​​en transformadores, lo que permite que el modelo capture dependencias de largo alcance y representaciones contextualizadas. Sin embargo, esta operación de atención es computacionalmente ineficiente para la generación de texto autorregresivo, ya que requiere volver a calcular muchos de los mismos valores para cada nuevo token.

El Algoritmo de atención flash, presentado en el artículo FlashAttention, proporciona un enfoque más eficiente en memoria y fácil de paralelizar para la operación de atención. En lugar de volver a calcular los valores de atención para cada token, Flash Attention almacena en caché y reutiliza matrices clave/valor intermedias, evitando cálculos redundantes.

Esta optimización no solo reduce la sobrecarga computacional sino que también mejora los patrones de acceso a la memoria, lo que lleva a una mejor utilización del ancho de banda y el paralelismo de la memoria de la GPU.

Si bien los detalles de Flash Attention son bastante complicados, la idea de alto nivel es descomponer la operación de atención en dos fases:

  1. Incrustación de suma de prefijo: esta fase calcula y almacena en caché las incrustaciones de clave/valor para todos los tokens de entrada, lo que permite una reutilización eficiente durante la generación.
  2. Atención causal: La operación de atención real, ahora optimizada para aprovechar las incrustaciones de clave/valor almacenadas en caché de la primera fase.

Al separar estas fases, Flash Attention puede aprovechar operaciones de GPU altamente paralelas, lo que acelera significativamente el cuello de botella de atención en la inferencia LLM.

Aquí hay una breve ilustración conceptual de la implementación de Flash Attention con un LLM:

from transformers import AutoModelForCausalLM
import torch
from flash_attention import flash_attention
# Load an LLM like OctoCoder
model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder")
# Sample system prompt that guides the model towards being a better coding assistant
system_prompt = """... (system prompt details) ..."""
# Preparing a longer input with the system prompt
long_prompt = system_prompt + "Question: Please write a function in Python that transforms bytes to Gigabytes."
# Converting the model for Flash Attention optimization
model.to_bettertransformer()
# Running the model with Flash Attention
start_time = time.time()
with torch.backends.cuda.sdp_kernel(enable_flash=True):
result = model.generate(long_prompt, max_new_tokens=60)
print(f"Generated in {time.time() - start_time} seconds.")

Si bien Flash Attention ofrece mejoras de rendimiento impresionantes, funciona dentro de la arquitectura de transformador existente. Para liberar completamente el potencial de la inferencia LLM acelerada, necesitamos explorar innovaciones arquitectónicas diseñadas específicamente para esta tarea.

Poda de LLM

La poda de LLM es una técnica para reducir el tamaño del modelo manteniendo la funcionalidad. Utiliza un estimador dependiente de datos para la importancia del peso basado en aproximaciones de matrices de Hesse. En la poda, se eliminan los grupos de peso menos importantes y luego el modelo se ajusta para recuperar la precisión. El paquete LLM-Pruner ofrece scripts para podar con varias estrategias compatibles. La poda incluye descubrir dependencias, estimar las contribuciones del grupo y una etapa de recuperación que implica un breve post-entrenamiento.

Aquí hay un ejemplo de código Python simplificado que demuestra el uso de LLM-Podadora para un modelo LLaMa:

from transformers import AutoModelForSequenceClassification
from pruning import LLMPruner
# Load pre-trained LLaMa model
model = AutoModelForSequenceClassification.from_pretrained("llama-base")
# Initialize the pruner with desired configuration
pruner = LLMPruner(
model,
pruning_ratio=0.25,
block_mlp_layers=(4, 30),
block_attention_layers=(4, 30),
pruner_type='taylor'
)
# Execute pruning
pruned_model = pruner.prune()
# Fine-tune the pruned model
pruned_model.fine_tune(training_data)

Este boceto de código representa cargar un modelo LLaMa previamente entrenado, configurar el podador con configuraciones específicas (como qué capas podar y el tipo de podador), ejecutar el proceso de poda y, finalmente, ajustar el modelo podado.

Tenga en cuenta que para una implementación real, deberá completar detalles como el nombre del modelo específico, las rutas a los datos y parámetros adicionales para el proceso de ajuste. Además, tenga en cuenta que este código es una representación conceptual y la sintaxis real puede variar según la biblioteca y las versiones utilizadas.

Innovaciones arquitectónicas para una generación de texto eficiente

La arquitectura del transformador, si bien es muy eficaz para tareas de modelado de lenguaje, se diseñó como un modelo secuencia a secuencia de propósito general. Al implementar LLM para tareas de generación de texto con contextos de entrada largos, los investigadores han descubierto que arquitecturas más especializadas pueden mejorar significativamente la eficiencia de la inferencia sin sacrificar la calidad.

Estas son algunas de las innovaciones arquitectónicas clave que permiten una inferencia LLM más rápida:

coartada: La arquitectura Alibi, introducida en el documento PAL-Instruction, separa el modelado del contexto de entrada largo del proceso de generación de texto en sí. Utiliza una representación comprimida del contexto de entrada (la "coartada") para inicializar el proceso de generación, evitando la necesidad de procesar la secuencia de entrada completa repetidamente durante la generación autorregresiva.

Incrustaciones rotativas: En lugar de utilizar incrustaciones posicionales estándar, la técnica de incrustación rotativa emplea matrices de rotación para codificar información posicional de manera más eficiente. Se ha demostrado que este enfoque mejora el rendimiento y permite el procesamiento de secuencias de entrada más largas.

Atención de consultas múltiples (MQA): En la atención tradicional, cada token de salida atiende a toda la secuencia de entrada, lo que resulta en un cálculo redundante. MQA Reformula la operación de atención para compartir cálculos entre múltiples tokens de salida, lo que reduce la complejidad general.

Atención multiconsulta

Atención multiconsulta

Atención de consultas agrupadas (GQA): basándose en MQA, GQA agrupa los tokens de salida en grupos y calcula la atención de forma conjunta para cada grupo. Este enfoque reduce aún más los requisitos computacionales y al mismo tiempo mantiene la generación de texto de alta calidad.

Si bien aún se encuentran en investigación y desarrollo activos, estas innovaciones arquitectónicas han demostrado aceleraciones impresionantes para las tareas de inferencia LLM, especialmente cuando se combinan con técnicas como Flash Attention y optimización de precisión numérica.

Consideraciones de implementación en el mundo real

Más allá de los algoritmos y arquitecturas centrales, existen varias consideraciones prácticas y compensaciones que se deben tener en cuenta al implementar LLM en entornos de producción:

Aceleración de hardware: Si bien las CPU pueden manejar la inferencia LLM, las GPU y otros aceleradores como las TPU de Google son esenciales para lograr un alto rendimiento y una baja latencia. Elegir el hardware adecuado y optimizar el uso de la memoria es fundamental.

Procesamiento por lotes y paralelismo: Para aprovechar al máximo el paralelismo del hardware, estrategias como la inferencia por lotes (procesar múltiples entradas simultáneamente) y el paralelismo de modelos (distribuir un LLM entre múltiples dispositivos) pueden aumentar significativamente el rendimiento.

Compensación entre cuantización y calidad: El grado de cuantificación (8 bits, 4 bits, etc.) afectará directamente la velocidad de inferencia y el uso de memoria, pero también afectará la calidad de salida. Esta compensación debe evaluarse cuidadosamente para cada caso de uso.

Modelo de destilación: Una alternativa a la cuantificación, las técnicas de destilación de modelos pueden comprimir grandes LLM en modelos de estudiantes más pequeños y más eficientes, manteniendo al mismo tiempo una alta precisión.

Almacenamiento en caché y tiempos de ejecución optimizados: Los tiempos de ejecución de aprendizaje profundo optimizados como TensorRT de NVIDIA y los marcos diseñados para el servicio LLM (por ejemplo, Composable Inference Suite de MosaicML) pueden proporcionar mejoras significativas en el rendimiento a través de técnicas como la fusión de operadores, la optimización del kernel y las estrategias de almacenamiento en caché inteligentes.

El camino hacia una implementación óptima de LLM a menudo implica combinar múltiples técnicas y al mismo tiempo considerar cuidadosamente los requisitos específicos de su aplicación, las limitaciones de la infraestructura y los objetivos de rendimiento.

Conclusión

A medida que los grandes modelos de lenguaje continúan su rápida evolución, acelerar su rendimiento de inferencia se vuelve cada vez más crucial para permitir aplicaciones del mundo real y democratizar el acceso a estas poderosas capacidades de IA.

En esta guía técnica, exploramos técnicas de vanguardia que abarcan la optimización de la precisión numérica, algoritmos de atención novedosos como Flash Attention e innovaciones arquitectónicas diseñadas para una generación de texto eficiente. Si bien cada enfoque ofrece sus propias ventajas, el verdadero poder a menudo radica en combinar múltiples estrategias mientras se navega por las intrincadas compensaciones entre velocidad, uso de memoria y calidad de salida.

De cara al futuro, podemos esperar una investigación y un desarrollo continuos en este ámbito, impulsados ​​por la demanda insaciable de LLM más capaces y accesibles. Desde la aceleración de hardware y la compresión de modelos hasta arquitecturas completamente nuevas, la búsqueda de una inferencia LLM eficiente sigue siendo una frontera apasionante en el mundo del procesamiento del lenguaje natural y la inteligencia artificial.

He pasado los últimos cinco años sumergiéndome en el fascinante mundo del aprendizaje automático y el aprendizaje profundo. Mi pasión y experiencia me han llevado a contribuir en más de 50 proyectos diversos de ingeniería de software, con un enfoque particular en AI/ML. Mi curiosidad constante también me ha atraído hacia el procesamiento del lenguaje natural, un campo que estoy ansioso por explorar más a fondo.