Ingeniería de prompts
Acelerando la inferencia de grandes modelos de lenguaje: Técnicas para una implementación eficiente

By
Aayush Mittal Mittal
Los grandes modelos de lenguaje (LLM) como GPT-4, LLaMA, y PaLM están empujando los límites de lo que es posible con el procesamiento de lenguaje natural. Sin embargo, implementar estos modelos masivos en entornos de producción presenta desafíos significativos en términos de requisitos computacionales, uso de memoria, latencia y costo. A medida que los LLM siguen creciendo en tamaño y capacidad, optimizar su rendimiento de inferencia es fundamental para aplicaciones del mundo real.
En esta inmersión técnica, exploraremos técnicas de vanguardia para acelerar la inferencia de LLM, permitiendo tiempos de respuesta más rápidos, un 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 una generación de texto eficiente.
Comencemos entendiendo por qué la inferencia de LLM es tan desafiante en comparación con los modelos de NLP tradicionales.
El desafío de la inferencia con grandes modelos de lenguaje
Antes del advenimiento de los LLM, el procesamiento de lenguaje natural se basaba en modelos más pequeños centrados en tareas específicas como la clasificación de texto, el reconocimiento de entidades nombradas y el análisis de sentimiento. Si bien aún eran computacionalmente intensivos, estos modelos podían implementarse en hardware modesto y seguir procesos de inferencia relativamente directos.
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 de lenguaje con una notable habilidad. Sin embargo, este poder conlleva un costo – una demanda computacional dramáticamente aumentada durante tanto el entrenamiento como la inferencia.
Un desafío clave es la naturaleza autorregresiva de la generación de texto con LLM. Para producir texto similar al humano, estos modelos predicen un token (palabra o subpalabra) a la vez, con cada nuevo token dependiendo de la salida generada previamente. Esta dependencia secuencial evita la paralelización eficiente y resulta en requisitos computacionales que escalan polinomialmente con la longitud de la secuencia.
Además, los LLM a menudo requieren secuencias de entrada largas (prompt) para establecer el contexto necesario para una generación de texto de alta calidad. Longitudes de entrada más largas demandan más memoria para almacenar estados intermedios y matrices de atención, lo que somete 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 computación estáticos pueden ser insuficientes, luchando por mantener el rendimiento de los LLM mientras entregan aceleraciones significativas. Sumérjase en algunas de las estrategias clave diseñadas explícitamente para acelerar la inferencia de LLM.
Técnicas de precisión numérica
Una vía para acelerar la inferencia de LLM es aprovechar la precisión numérica reducida para los pesos del modelo y las activaciones. Los marcos de aprendizaje profundo modernos como PyTorch y TensorFlow emplean por defecto una precisión de punto flotante de 32 bits (FP32). Sin embargo, la investigación ha demostrado que los LLM pueden mantener una alta precisión incluso cuando operan a precisiones más bajas, como 16 bits (FP16), 8 bits enteros (INT8) o incluso 4 bits enteros (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 lote más grandes quepan dentro de las mismas restricciones de hardware.
- Cómputo más rápido: Muchos CPUs y GPUs modernos proporcionan instrucciones especializadas y aceleración de hardware para aritmética de menor precisión, lo que permite aceleraciones significativas.
- Mejora de la eficiencia energética: Con requisitos de memoria más pequeños y cálculos más rápidos, la inferencia de menor precisión puede traducirse en un consumo de energía reducido – una ventaja crucial para implementaciones de borde y móviles.
Si bien es poderosa, la técnica de precisión numérica introduce alguna pérdida de precisión en comparación con la operación FP32. La clave es evaluar cuidadosamente este intercambio entre ganancias computacionales y posible degradación del rendimiento para su caso de uso específico.
Hay dos enfoques principales para la cuantificación con LLM:
Cuantificación después del entrenamiento (PTQ): En este método, un LLM se entrena primero usando 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 llevar a una mayor caída de precisión.
Entrenamiento con conciencia de cuantificación (QAT): Con QAT, el proceso de cuantificación se simula durante la fase de entrenamiento en sí. 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 involucrado pero a menudo produce mejores resultados en comparación con PTQ.
Para la aplicación práctica, uno podría aprovechar modelos pre-cuantificados disponibles en plataformas como Hugging Face, que alberga una variedad de modelos optimizados a través de 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 bibliotecas existentes para comprimir el modelo de manera eficiente.
Aquí hay un ejemplo conceptual de carga de un modelo Llama-2-7b pre-cuantificado usando la biblioteca de transformadores de 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) Y para la cuantificación personalizada, uno podría seguir estos pasos usando la herramienta AutoGPTQ: 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 necesitar un ajuste fino posterior o ingeniería de prompts para mantener la calidad del modelo. Para una nueva cuantificación, usted puede contribuir devolviendo a la comunidad empujando sus modelos cuantificados a plataformas como Hugging Face.
Asegúrese de equilibrar entre 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 multi-cabeza es un componente central de los LLM basados en transformadores, lo que permite al modelo capturar dependencias de largo alcance y representaciones contextualizadas. Sin embargo, esta operación de atención es computacionalmente ineficiente para la generación de texto autorregresiva, ya que requiere volver a calcular muchos de los mismos valores para cada nuevo token.
El algoritmo de atención Flash, introducido en el papel FlashAttention, proporciona un enfoque más eficiente en términos de memoria y más amigable con la paralelización para la operación de atención. En lugar de volver a calcular los valores de atención para cada token, la atención Flash 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 conduce a una mejor utilización de la banda de memoria de la GPU y el paralelismo.
Si bien los detalles de la atención Flash son bastante involucrados, la idea general es descomponer la operación de atención en dos fases:
- Incrustación de suma de prefijo: Esta fase calcula y almacena en caché incrustaciones clave/valor para todos los tokens de entrada, permitiendo un reuso eficiente durante la generación.
- Atención causal: La operación de atención real, ahora optimizada para aprovechar las incrustaciones clave/valor almacenadas en caché de la primera fase.
Al separar estas fases, la atención Flash puede aprovechar operaciones paralelas de GPU altamente paralelas, acelerando significativamente el cuello de botella de la atención en la inferencia de LLM.
Aquí hay una breve ilustración conceptual de la implementación de la atención Flash con un LLM:
from transformers import AutoModelForCausalLM
import torch
from flash_attention import flash_attention
# Cargar un LLM como OctoCoder
model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder")
# Prompt del sistema de ejemplo que guía al modelo hacia ser un mejor asistente de codificación
system_prompt = "``... (detalles del prompt del sistema) ...``";
# Preparar una entrada más larga con el prompt del sistema
long_prompt = system_prompt + "Pregunta: Por favor, escriba una función en Python que transforme bytes en gigabytes.";
# Convertir el modelo para la optimización de la atención Flash
model.to_bettertransformer()
# Ejecutar el modelo con la atención Flash
start_time = time.time()
with torch.backends.cuda.sdp_kernel(enable_flash=True):
result = model.generate(long_prompt, max_new_tokens=60)
print(f"Generado en {time.time() - start_time} segundos.")
Si bien la atención Flash ofrece ganancias de rendimiento impresionantes, funciona dentro de la arquitectura de transformadores existente. Para desbloquear completamente el potencial de la inferencia de LLM acelerada, necesitamos explorar innovaciones arquitectónicas diseñadas específicamente para esta tarea.
Podar LLM
Podar LLM es una técnica para reducir el tamaño del modelo mientras mantiene la funcionalidad. Utiliza un estimador dependiente de datos para la importancia del peso basado en aproximaciones de la matriz de Hessian. En el podado, se eliminan los grupos de pesos menos importantes, luego el modelo se ajusta para recuperar la precisión. El paquete LLM-Pruner ofrece scripts para el podado con varias estrategias admitidas. El podado incluye descubrir dependencias, estimar contribuciones de grupo y una etapa de recuperación que involucra un ajuste fino posterior.
Aquí hay un ejemplo simplificado de código en Python que demuestra el uso de LLM-Pruner para un modelo LLaMa:
from transformers import AutoModelForSequenceClassification
from pruning import LLMPruner
# Cargar el modelo LLaMa pre-entrenado
model = AutoModelForSequenceClassification.from_pretrained("llama-base")
# Inicializar el podador con la configuración deseada
pruner = LLMPruner(
model,
pruning_ratio=0.25,
block_mlp_layers=(4, 30),
block_attention_layers=(4, 30),
pruner_type='taylor'
)
# Ejecutar el podado
pruned_model = pruner.prune()
# Ajustar el modelo podado
pruned_model.fine_tune(training_data)
Este esbozo de código representa la carga de un modelo LLaMa pre-entrenado, la configuración del podador con configuraciones específicas (como qué capas podar y el tipo de podador), la ejecución del proceso de podado y, finalmente, el ajuste fino del modelo podado.
Tenga en cuenta que para una implementación real, necesitaría llenar detalles como el nombre específico del modelo, rutas a los datos y parámetros adicionales para el proceso de ajuste fino. Además, tenga en cuenta que este código es una representación conceptual, y la sintaxis real puede variar dependiendo de la biblioteca y las versiones utilizadas.
Innovaciones arquitectónicas para una generación de texto eficiente
La arquitectura de transformadores, aunque altamente efectiva para tareas de modelado de lenguaje, se diseñó como un modelo de secuencia a secuencia de propósito general. Cuando se implementan LLM para tareas de generación de texto con contextos de entrada largos, los investigadores han encontrado que arquitecturas más especializadas pueden mejorar significativamente la eficiencia de la inferencia sin sacrificar la calidad.
Aquí hay algunas de las innovaciones arquitectónicas clave que permiten una inferencia de LLM más rápida:
Alibi: La arquitectura Alibi, introducida en el papel PAL-Instruction, separa la modelización del contexto de entrada largo de la generación de texto en sí. Utiliza una representación comprimida del contexto de entrada (el “alibi”) 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 de posición estándar, la técnica de incrustaciones rotativas emplea matrices de rotación para codificar información de posición de manera más eficiente. Este enfoque ha demostrado mejorar el rendimiento y permitir el procesamiento de secuencias de entrada más largas.
Atención multi-consulta (MQA): En la atención tradicional, cada token de salida atiende a toda la secuencia de entrada, lo que resulta en cálculos redundantes. MQA reformula la operación de atención para compartir cálculos a través de múltiples tokens de salida, reduciendo la complejidad general.
Atención de consulta agrupada (GQA): Basándose en MQA, GQA agrupa los tokens de salida en clusters y computa la atención conjuntamente para cada cluster. Este enfoque reduce aún más los requisitos computacionales mientras mantiene la generación de texto de alta calidad.
Si bien aún se encuentra en investigación y desarrollo activos, estas innovaciones arquitectónicas han demostrado aceleraciones impresionantes para tareas de inferencia de LLM, especialmente cuando se combinan con técnicas como la atención Flash y la optimización de precisión numérica.
Consideraciones de implementación en el mundo real
Más allá de los algoritmos y arquitecturas centrales, hay varias consideraciones prácticas y compensaciones que navegar cuando se implementan LLM en entornos de producción:
Aceleración de hardware: Si bien las CPUs pueden manejar la inferencia de LLM, las GPUs y otros aceleradores como los TPUs de Google son esenciales para lograr un alto rendimiento y una baja latencia. La elección del hardware adecuado y la optimización del uso de la memoria son cruciales.
Batching y paralelismo: Para aprovechar al máximo el paralelismo de hardware, estrategias como la inferencia por lotes (procesar múltiples entradas simultáneamente) y el paralelismo de modelo (distribuir un LLM a través de múltiples dispositivos) pueden aumentar significativamente el rendimiento.
Compensación entre cuantificación y calidad: El grado de cuantificación (8 bits, 4 bits, etc.) impactará directamente la velocidad de inferencia y el uso de memoria, pero también afecta la calidad de salida. Esta compensación debe evaluarse cuidadosamente para cada caso de uso.
Destilación de modelos: Como alternativa a la cuantificación, las técnicas de destilación de modelos pueden comprimir LLM grandes en modelos de estudiante más pequeños y eficientes mientras retienen una alta precisión.
Caché y tiempos de ejecución optimizados: Tiempos de ejecución de aprendizaje profundo optimizados como NVIDIA’s TensorRT y marcos diseñados para el servicio de LLM (por ejemplo, MosaicML’s Composable Inference Suite) pueden proporcionar aumentos de rendimiento significativos a través de técnicas como la fusión de operadores, la optimización del kernel y estrategias de caché inteligentes.
El camino hacia la implementación óptima de LLM a menudo implica combinar múltiples técnicas mientras se consideran cuidadosamente los requisitos específicos de su aplicación, las restricciones de infraestructura y los objetivos de rendimiento.
Conclusión
A medida que los grandes modelos de lenguaje continúan su evolución rápida, acelerar su rendimiento de inferencia se está volviendo cada vez más crucial para habilitar 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 precisión numérica, algoritmos de atención novedosos como la atención Flash y innovaciones arquitectónicas diseñadas específicamente para una generación de texto eficiente. Si bien cada enfoque ofrece sus propias ventajas, el verdadero poder a menudo reside en combinar múltiples estrategias mientras se navegan las compensaciones intrincadas entre velocidad, uso de memoria y calidad de salida.
Mirando hacia adelante, podemos esperar una investigación y desarrollo continuos en este dominio, impulsados por la insaciable demanda 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 de LLM eficiente sigue siendo una frontera emocionante en el mundo del procesamiento de 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 a más de 50 proyectos de ingeniería de software diversos, con un enfoque particular en AI/ML. Mi curiosidad continua también me ha llevado hacia el Procesamiento de Lenguaje Natural, un campo que estoy ansioso por explorar más a fondo.
You may like


Lumai Presenta Servidor de Inteligencia Artificial Óptica para Potenciar la Próxima Era de Inferencia


124 veces más lento: ¿Qué hace realmente PyTorch DataLoader a nivel de kernel


La Fundación PyTorch integra Ray, un marco de computación distribuida, para construir una pila de infraestructura de IA unificada


La Nueva Brecha Digital en IA: Por Qué los Modelos Listos para el Borde y con CPU como Primera Opción Ganarán la Guerra de Costos


Por qué los Grandes Modelos de Lenguaje Olvidan el Medio: Descubriendo el Punto Ciego Oculto de la IA


Mejorando la inferencia de IA: Técnicas avanzadas y mejores prácticas

