Entre em contato

Acelerando a inferência de modelos de linguagem grande: técnicas para implantação eficiente

Engenharia imediata

Acelerando a inferência de modelos de linguagem grande: técnicas para implantação eficiente

mm
Aceleração de inferência LLM

Modelos de linguagem grande (LLMs) como GPT-4, chamadase PaLM estão expandindo os limites do que é possível com o processamento de linguagem natural. No entanto, a implantação desses modelos massivos em ambientes de produção apresenta desafios significativos em termos de requisitos computacionais, uso de memória, latência e custo. À medida que os LLMs continuam a crescer e se tornar mais capazes, otimizar seu desempenho de inferência é fundamental para aplicações do mundo real.

Nesta análise técnica aprofundada, exploraremos técnicas de ponta para acelerar a inferência de LLM, permitindo tempos de resposta mais rápidos, maior rendimento e utilização mais eficiente dos recursos de hardware. Abordaremos métodos que vão desde técnicas de precisão numérica e novos mecanismos de atenção até inovações arquitetônicas especificamente adaptadas para a geração eficiente de texto.

Vamos começar entendendo por que a inferência de LLM é tão desafiadora em comparação aos modelos tradicionais de PNL.

O desafio da inferência com grandes modelos de linguagem

Antes do advento dos LLMs, o processamento de linguagem natural dependia de modelos menores focados em tarefas específicas, como classificação de texto, reconhecimento de entidade nomeada e análise de sentimento. Embora ainda sejam computacionalmente intensivos, esses modelos poderiam ser implantados em hardware modesto e seguir processos de inferência relativamente simples.

Os LLMs, por outro lado, representam uma mudança de paradigma. Esses modelos são treinados em vastos conjuntos de dados usando bilhões de parâmetros, permitindo-lhes executar uma ampla gama de tarefas linguísticas com notável proficiência. No entanto, esse poder tem um custo – demandas computacionais dramaticamente aumentadas durante o treinamento e a inferência.

Um desafio importante é a natureza autoregressiva da geração de texto com LLMs. Para produzir texto semelhante ao humano, esses modelos prevêem um token (palavra ou subpalavra) por vez, com cada novo token dependendo da saída gerada anteriormente. Essa dependência sequencial impede a paralelização eficiente e resulta em requisitos computacionais que escalam polinomialmente com o comprimento da sequência.

Além disso, os LLMs geralmente exigem longas sequências de entrada (prompts) para estabelecer o contexto necessário para a geração de texto de alta qualidade. Comprimentos de entrada mais longos exigem mais memória para armazenar estados intermediários e matrizes de atenção, sobrecarregando ainda mais os recursos de hardware.

Com esses desafios únicos, técnicas tradicionais de otimização, como quantização e gráficos de computação estática, podem falhar, dificultando a manutenção do desempenho do LLM e, ao mesmo tempo, a obtenção de acelerações significativas. Vamos analisar algumas das principais estratégias desenvolvidas especificamente para acelerar a inferência do LLM.

Técnicas de precisão numérica

De precisão de 32 a 16 bits

De precisão de 32 a 16 bits

Um caminho para acelerar LLM inferência é aproveitar a precisão numérica reduzida para pesos e ativações de modelos. Estruturas modernas de aprendizado profundo, como PyTorch e TensorFlow, normalmente empregam precisão de ponto flutuante de 32 bits (FP32) por padrão. No entanto, a pesquisa mostrou que os LLMs muitas vezes podem manter alta precisão mesmo quando operam com precisões mais baixas, como números inteiros de 16 bits (FP16), números inteiros de 8 bits (INT8) ou mesmo números inteiros de 4 bits (INT4).

A redução da precisão numérica oferece vários benefícios:

  • Pegada de memória reduzida: representações de menor precisão requerem menos memória, permitindo que modelos maiores ou tamanhos de lote se ajustem às mesmas restrições de hardware.
  • Computação mais rápida: muitas CPUs e GPUs modernas fornecem instruções especializadas e aceleração de hardware para aritmética de menor precisão, permitindo acelerações significativas.
  • Eficiência energética melhorada: Com requisitos de memória menores e cálculos mais rápidos, a inferência de menor precisão pode se traduzir em consumo de energia reduzido – uma vantagem crucial para implantações móveis e de borda.

Embora poderosas, as técnicas de precisão numérica introduzem alguma perda de precisão em comparação com a operação FP32. O segredo é avaliar cuidadosamente essa compensação entre ganhos computacionais e possível degradação de desempenho para seu caso de uso específico.

Existem duas abordagens principais para quantização com LLMs:

Quantização Pós-Treinamento (PTQ): Neste método, um LLM é primeiro treinado usando a precisão FP32 padrão. Após o treinamento, os pesos do modelo são quantizados (convertidos) para um formato de menor precisão, como INT8 ou INT4. O PTQ é simples de implementar, mas pode levar a maiores quedas de precisão.

Treinamento Consciente de Quantização (QAT): Com o QAT, o processo de quantização é simulado durante a própria fase de treinamento. Isso permite que o modelo aprenda a compensar erros de quantização, minimizando a degradação da precisão quando o modelo quantizado final for implantado. O QAT está mais envolvido, mas muitas vezes produz melhores resultados em comparação com o PTQ.

Para aplicação prática, pode-se aproveitar modelos pré-quantizados disponíveis em plataformas como Abraçando o rosto, que hospeda uma variedade de modelos otimizados por meio de diferentes métodos de quantização. Por exemplo, se desejar um modelo quantizado usando o Auto-GPTQ, os usuários podem carregá-lo facilmente usando a biblioteca de transformadores do Hugging Face. Além disso, para quantizar um modelo, ferramentas como o AutoGPTQ podem ser utilizadas, as quais se integram perfeitamente às bibliotecas existentes para compactar o modelo de forma eficiente.

Aqui está um exemplo de carregamento de um modelo Llama-2-7b pré-quantizado usando a 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)

Lembre-se de que a quantização pode exigir ajuste fino pós-quantização ou engenharia imediata para manter a qualidade do modelo. Para uma nova quantização, você pode contribuir com a comunidade enviando seus modelos quantizados para plataformas como Hugging Face.

Certifique-se sempre de equilibrar o tamanho do modelo, os requisitos computacionais e o desempenho ao selecionar a estratégia de quantização para seu caso de uso específico.

 

O Algoritmo de Atenção Flash

O mecanismo de atenção multicabeças é um componente central dos LLMs baseados em transformadores, permitindo que o modelo capture dependências de longo alcance e representações contextualizadas. No entanto, esta operação de atenção é computacionalmente ineficiente para geração de texto autorregressivo, pois requer o recálculo de muitos dos mesmos valores para cada novo token.

O processo de Algoritmo de atenção flash, apresentado no artigo FlashAttention, fornece uma abordagem mais eficiente em termos de memória e fácil de paralelização para a operação de atenção. Em vez de recalcular valores de atenção para cada token, o Flash Attention armazena em cache e reutiliza matrizes de chave/valor intermediárias, evitando cálculos redundantes.

Essa otimização não apenas reduz a sobrecarga computacional, mas também melhora os padrões de acesso à memória, levando a uma melhor utilização da largura de banda da memória da GPU e ao paralelismo.

Embora os detalhes do Flash Attention sejam bastante complexos, a ideia geral é decompor a operação de atenção em duas fases:

  1. Incorporação de soma de prefixo: esta fase calcula e armazena em cache incorporações de chave/valor para todos os tokens de entrada, permitindo a reutilização eficiente durante a geração.
  2. Atenção Causal: a operação de atenção real, agora otimizada para aproveitar os embeddings de chave/valor armazenados em cache da primeira fase.

Ao separar essas fases, o Flash Attention pode tirar vantagem de operações de GPU altamente paralelas, acelerando significativamente o gargalo de atenção na inferência LLM.

Aqui está uma breve ilustração conceitual da implementação do Flash Attention com um 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.")

Embora o Flash Attention ofereça ganhos de desempenho impressionantes, ele funciona dentro da arquitetura de transformador existente. Para liberar totalmente o potencial da inferência LLM acelerada, precisamos explorar inovações arquitetônicas adaptadas especificamente para esta tarefa.

Poda LLMs

A poda de LLMs é uma técnica para reduzir o tamanho do modelo enquanto mantém a funcionalidade. Ele usa um estimador dependente de dados para importância do peso com base em aproximações da matriz Hessiana. Na poda, os grupos de peso menos importantes são removidos e o modelo é ajustado para recuperar a precisão. O pacote LLM-Pruner oferece scripts para poda com diversas estratégias suportadas. A poda inclui a descoberta de dependências, a estimativa das contribuições do grupo e um estágio de recuperação envolvendo um breve pós-treinamento.

Aqui está um exemplo de código Python simplificado que demonstra o uso de LLM-Podador para um 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 esboço de código representa o carregamento de um modelo LLaMa pré-treinado, a configuração do podador com configurações específicas (como quais camadas podar e o tipo de podador), a execução do processo de poda e, por fim, o ajuste fino do modelo podado.

Observe que, para uma implementação real, você precisaria preencher detalhes como o nome do modelo específico, caminhos para os dados e parâmetros adicionais para o processo de ajuste fino. Além disso, esteja ciente de que este código é uma representação conceitual e a sintaxe real pode variar dependendo da biblioteca e das versões utilizadas.

Inovações arquitetônicas para geração eficiente de texto

A arquitetura do transformador, embora altamente eficaz para tarefas de modelagem de linguagem, foi projetada como um modelo de uso geral sequência a sequência. Ao implantar LLMs para tarefas de geração de texto com contextos de entrada longos, os pesquisadores descobriram que arquiteturas mais especializadas podem melhorar significativamente a eficiência da inferência sem sacrificar a qualidade.

Aqui estão algumas das principais inovações arquitetônicas que permitem inferência LLM mais rápida:

Álibi: A arquitetura Alibi, introduzida no artigo PAL-Instruction, separa a modelagem do contexto de entrada longo do próprio processo de geração de texto. Ele usa uma representação compactada do contexto de entrada (o “álibi”) para inicializar o processo de geração, evitando a necessidade de processar repetidamente a sequência de entrada completa durante a geração autorregressiva.

Incorporações Rotativas: em vez de usar incorporações posicionais padrão, a técnica de incorporação rotativa emprega matrizes de rotação para codificar informações posicionais com mais eficiência. Foi demonstrado que esta abordagem melhora o desempenho e permite o processamento de sequências de entrada mais longas.

Atenção multiconsulta (MQA): Na atenção tradicional, cada token de saída atende a toda a sequência de entrada, resultando em computação redundante. MQA reformula a operação de atenção para compartilhar cálculos entre vários tokens de saída, reduzindo a complexidade geral.

Atenção multiconsulta

Atenção multiconsulta

Atenção à consulta agrupada (GQA): Com base no MQA, o GQA agrupa tokens de saída em clusters e calcula a atenção conjuntamente para cada cluster. Esta abordagem reduz ainda mais os requisitos computacionais, mantendo a geração de texto de alta qualidade.

Embora ainda estejam em pesquisa e desenvolvimento ativos, essas inovações arquitetônicas demonstraram acelerações impressionantes para tarefas de inferência LLM, especialmente quando combinadas com técnicas como Flash Attention e otimização de precisão numérica.

Considerações de implantação no mundo real

Além dos algoritmos e arquiteturas principais, há diversas considerações práticas e compensações a serem feitas ao implantar LLMs em ambientes de produção:

Aceleraçao do hardware: Embora CPUs possam lidar com inferência LLM, GPUs e outros aceleradores, como as TPUs do Google, são essenciais para alcançar alto rendimento e baixa latência. Escolher o hardware certo e otimizar o uso da memória é crucial.

Lote e paralelismo: para aproveitar totalmente o paralelismo de hardware, estratégias como inferência em lote (processamento de múltiplas entradas simultaneamente) e paralelismo de modelo (distribuição de um LLM em vários dispositivos) podem aumentar significativamente o rendimento.

Quantização vs. Compensação de Qualidade: O grau de quantização (8 bits, 4 bits, etc.) afetará diretamente a velocidade de inferência e o uso de memória, mas também afetará a qualidade da saída. Essa compensação deve ser avaliada cuidadosamente para cada caso de uso.

Destilação Modelo: Uma alternativa à quantização, as técnicas de destilação de modelo podem compactar grandes LLMs em modelos de estudante menores e mais eficientes, mantendo alta precisão.

Cache e tempos de execução otimizados: Tempos de execução de aprendizado profundo otimizados, como o TensorRT da NVIDIA e estruturas projetadas para atender LLM (por exemplo, o Composable Inference Suite da MosaicML), podem fornecer melhorias significativas de desempenho por meio de técnicas como fusão de operadores, otimização de kernel e estratégias de cache inteligentes.

O caminho para a implantação ideal do LLM geralmente envolve a combinação de diversas técnicas e, ao mesmo tempo, considerar cuidadosamente os requisitos específicos da sua aplicação, as restrições de infraestrutura e as metas de desempenho.

Conclusão

À medida que os grandes modelos de linguagem continuam a sua rápida evolução, acelerar o seu desempenho de inferência torna-se cada vez mais crucial para permitir aplicações do mundo real e democratizar o acesso a estas poderosas capacidades de IA.

Neste guia técnico, exploramos técnicas de ponta que abrangem otimização de precisão numérica, novos algoritmos de atenção, como Flash Attention, e inovações arquitetônicas personalizadas para geração eficiente de texto. Embora cada abordagem ofereça suas próprias vantagens, o verdadeiro poder geralmente reside na combinação de diversas estratégias enquanto se navega pelas intrincadas compensações entre velocidade, uso de memória e qualidade de saída.

Olhando para o futuro, podemos esperar investigação e desenvolvimento contínuos neste domínio, alimentados pela procura insaciável de LLMs mais capazes e acessíveis. Da aceleração de hardware e compactação de modelos a arquiteturas inteiramente novas, a busca por inferência LLM eficiente continua sendo uma fronteira interessante no mundo do processamento de linguagem natural e da inteligência artificial.

Passei os últimos cinco anos mergulhando no fascinante mundo do Machine Learning e Deep Learning. Minha paixão e experiência me levaram a contribuir para mais de 50 projetos diversos de engenharia de software, com foco particular em AI/ML. Minha curiosidade contínua também me atraiu para o Processamento de Linguagem Natural, um campo que estou ansioso para explorar mais.