Logotipo de Zephyrnet

Implemente modelos de lenguaje grandes en AWS Inferentia2 utilizando contenedores de inferencia de modelos grandes

Fecha:

No es necesario ser un experto en aprendizaje automático (ML) para apreciar el valor de los modelos de lenguaje extenso (LLM). Mejores resultados de búsqueda, reconocimiento de imágenes para personas con discapacidad visual, creación de diseños novedosos a partir de texto y chatbots inteligentes son solo algunos ejemplos de cómo estos modelos facilitan diversas aplicaciones y tareas.

Los profesionales de ML siguen mejorando la precisión y las capacidades de estos modelos. Como resultado, estos modelos crecen en tamaño y se generalizan mejor, como en la evolución de los modelos de transformadores. Te explicamos en un anterior post cómo puedes usar Amazon SageMaker contenedores de aprendizaje profundo (DLC) para implementar este tipo de modelos grandes mediante una instancia basada en GPU.

En esta publicación, adoptamos el mismo enfoque pero alojamos el modelo en Inferencia de AWS2. Utilizamos el AWS neurona kit de desarrollo de software (SDK) para acceder al dispositivo Inferentia y beneficiarse de su alto rendimiento. Luego usamos un contenedor de inferencia de modelo grande impulsado por Biblioteca profunda de Java (DJLServing) como nuestra solución de servicio modelo. Demostramos cómo estas tres capas trabajan juntas al implementar un OPT-13B modelo en un Nube informática elástica de Amazon (Amazon EC2) inf2.48xgrande ejemplo.

Los tres pilares

La siguiente imagen representa las capas de hardware y software que funcionan para ayudarlo a obtener el mejor precio y rendimiento de sus modelos de idiomas grandes. AWS neurona y tranformers-neuronx son los SDK que se utilizan para ejecutar cargas de trabajo de aprendizaje profundo en AWS Inferentia. Por último, DJLServing es la solución de servicio que se integra en el contenedor.

Hardware: Inferencia

AWS Inferentia, diseñado específicamente para la inferencia por AWS, es un acelerador de inferencias de aprendizaje automático de alto rendimiento y bajo costo. En esta publicación, utilizamos AWS Inferentia2 (disponible a través de instancias Inf2), el acelerador de inferencias de ML especialmente diseñado de segunda generación.

Cada instancia EC2 Inf2 funciona con hasta 12 Dispositivos Inferentia2y le permite elegir entre cuatro tamaños de instancia.

Amazon EC2 Inf2 es compatible con NeuronLink v2, una interconexión de chip a chip de baja latencia y alto ancho de banda, que permite operaciones de comunicación colectiva de alto rendimiento, como AllReduce y AllGather. Esto fragmenta de manera eficiente los modelos en los dispositivos de AWS Inferentia2 (como a través del paralelismo de tensor) y, por lo tanto, optimiza la latencia y el rendimiento. Esto es particularmente útil para modelos de lenguaje grandes. Para obtener cifras de rendimiento de referencia, consulte AWS Rendimiento de las neuronas.

En el corazón de la instancia Amazon EC2 Inf2 se encuentran los dispositivos AWS Inferentia2, cada uno con dos NeuronCores-v2. Cada NeuronCore-v2 es una unidad de computación independiente y heterogénea, con cuatro motores principales: Tensor, Vector, Escalar y GPSIMD. Incluye una memoria SRAM administrada por software en el chip para maximizar la ubicación de los datos. El siguiente diagrama muestra el funcionamiento interno de la arquitectura del dispositivo AWS Inferentia2.

Neuron y transformadores-neuronx

Por encima de la capa de hardware se encuentran las capas de software que se utilizan para interactuar con AWS Inferentia. AWS Neuron es el SDK que se utiliza para ejecutar cargas de trabajo de aprendizaje profundo en AWS Inferentia y tren de AWS instancias basadas Permite el ciclo de vida de desarrollo de ML de extremo a extremo para crear nuevos modelos, entrenar y optimizar estos modelos e implementarlos para la producción. AWS Neuron incluye un aprendizaje profundo compilador, tiempo de ejecucióny que se integran de forma nativa con marcos populares como TensorFlow y PyTorch.

transformers-neuronx es un código abierto bibliotecas creado por el equipo de AWS Neuron que ayuda a ejecutar flujos de trabajo de inferencia de decodificadores de transformadores mediante el SDK de AWS Neuron. Actualmente, tiene ejemplos para los tipos de modelos GPT2, GPT-J y OPT, y diferentes tamaños de modelos que tienen sus funciones directas reimplementadas en un lenguaje compilado para análisis y optimizaciones de código extensos. Los clientes pueden implementar otra arquitectura modelo basada en la misma biblioteca. Las clases de decodificadores de transformadores optimizados para AWS Neuron se han vuelto a implementar en XLA HLO (Operaciones de alto nivel) mediante una sintaxis llamada PyHLO. La biblioteca también implementa el paralelismo de tensores para fragmentar los pesos del modelo en múltiples NeuronCores.

El paralelismo tensorial es necesario porque los modelos son tan grandes que no caben en una memoria HBM de un solo acelerador. El soporte para el paralelismo de tensores por el tiempo de ejecución de AWS Neuron en transformers-neuronx hace un uso intensivo de las operaciones colectivas tales como AllReduce. Los siguientes son algunos principios para establecer el grado de paralelismo del tensor (número de NeuronCores que participan en operaciones de multiplicación de matrices fragmentadas) para modelos de decodificadores de transformadores optimizados para AWS Neuron:

  • El número de cabezas de atención debe ser divisible por el grado de paralelismo tensorial
  • El tamaño total de los datos de los pesos del modelo y las cachés de valores clave debe ser inferior a 16 GB multiplicado por el grado de paralelismo del tensor.
  • Actualmente, el tiempo de ejecución de Neuron admite los grados de paralelismo tensorial 1, 2, 8 y 32 en trn1 y admite los grados de paralelismo tensorial 1, 2, 4, 8 y 24 en Inf2

DJLSirviendo

DJLServing es un servidor modelo de alto rendimiento que agregó soporte para AWS Inferentia2 en marzo de 2023. El equipo de AWS Model Server ofrece un imagen del contenedor que puede ayudar a los casos de uso de LLM/AIGC. DJL también es parte del soporte de Rubikon para Neuron que incluye la integración entre DJLServing y transformers-neuronx. El servidor modelo DJLServing y transformers-neuronx La biblioteca son los componentes principales del contenedor creado para servir a los LLM admitidos a través de la biblioteca de transformadores. Este contenedor y los DLC posteriores podrán cargar los modelos en los chips de AWS Inferentia en un host Amazon EC2 Inf2 junto con los controladores y el kit de herramientas de AWSInferentia instalados. En esta publicación, explicamos dos formas de ejecutar el contenedor.

La primera forma es ejecutar el contenedor sin escribir ningún código adicional. Puedes usar el controlador predeterminado para una experiencia de usuario perfecta y pase uno de los nombres de modelo admitidos y cualquier parámetro configurable de tiempo de carga. Esto compilará y servirá un LLM en una instancia de Inf2. El siguiente código muestra un ejemplo:

engine=Python
option.entryPoint=djl_python.transformers_neuronx
option.task=text-generation
option.model_id=facebook/opt-1.3b
option.tensor_parallel_degree=2

Alternativamente, puede escribir su propia model.py archivo, pero eso requiere implementar los métodos de inferencia y carga del modelo para servir como un puente entre las API de DJLServing y, en este caso, el transformers-neuronx API. También puede proporcionar parámetros configurables en un serving.properties archivo que se recogerá durante la carga del modelo. Para obtener la lista completa de parámetros configurables, consulte Todas las opciones de configuración de DJL.

El siguiente código es una muestra. model.py archivo. los serving.properties El archivo es similar al que se muestra anteriormente.

def load_model(properties): """ Load a model based from the framework provided APIs :param: properties configurable properties for model loading specified in serving.properties :return: model and other artifacts required for inference """ batch_size = int(properties.get("batch_size", 2)) tp_degree = int(properties.get("tensor_parallel_degree", 2)) amp = properties.get("dtype", "f16") model_id = "facebook/opt-13b" model = OPTForCausalLM.from_pretrained(model_id, low_cpu_mem_usage=True) ... tokenizer = AutoTokenizer.from_pretrained(model_id) model = OPTForSampling.from_pretrained(load_path, batch_size=batch_size, amp=amp, tp_degree=tp_degree) model.to_neuron() return model, tokenizer, batch_size

Veamos cómo se ve todo esto en una instancia de Inf2.

Inicie el hardware de Inferentia

Primero debemos lanzar una instancia inf.42xlarge para alojar nuestro modelo OPT-13b. usamos el Aprendizaje profundo AMI Neuron PyTorch 1.13.0 (Ubuntu 20.04) 20230226 Imagen de máquina de Amazon (AMI) porque ya incluye la imagen de Docker y los controladores necesarios para el tiempo de ejecución de AWS Neuron.

Aumentamos el almacenamiento de la instancia a 512 GB para adaptarse a modelos de idiomas grandes.

Instale las dependencias necesarias y cree el modelo.

We configurar un servidor de cuadernos Jupyter con nuestra AMI para facilitar la visualización y gestión de nuestros directorios y archivos. Cuando estamos en el directorio deseado, establecemos subdirectorios para logs y models Y crear un serving.properties archivo.

Podemos utilizar el modelo independiente proporcionado por el Servicio DJL envase. Esto significa que no tenemos que definir un modelo, pero sí necesitamos proporcionar un serving.properties archivo. Ver el siguiente código:

option.model_id=facebook/opt-1.3b
option.batch_size=2
option.tensor_parallel_degree=2
option.n_positions=256
option.dtype=fp16
option.model_loading_timeout=600
engine=Python
option.entryPoint=djl_python.transformers-neuronx
#option.s3url=s3://djl-llm/opt-1.3b/ #can also specify which device to load on.
#engine=Python ---because the handles are implement in python.

Esto le indica al servidor modelo DJL que use el modelo OPT-13B. Establecemos el tamaño del lote en 2 y dtype=f16 para que el modelo encaje en el dispositivo neuronal. El servicio DJL admite el procesamiento por lotes dinámico y al configurar un tensor_parallel_degree valor, podemos aumentar el rendimiento de las solicitudes de inferencia porque distribuimos la inferencia a través de múltiples NeuronCores. también establecemos n_positions=256 porque esto informa la longitud máxima que esperamos que tenga el modelo.

Nuestra instancia tiene 12 dispositivos AWS Neuron, o 24 NeuronCores, mientras que nuestro modelo OPT-13B requiere 40 cabezales de atención. Por ejemplo, establecer tensor_parallel_degree=8 significa que cada 8 NeuronCores albergará una instancia de modelo. Si divide los cabezales de atención requeridos (40) por la cantidad de NeuronCores (8), obtiene 5 cabezales de atención asignados a cada NeuronCore, o 10 en cada dispositivo AWS Neuron.

Puede usar la siguiente muestra model.py archivo, que define el modelo y crea la función de controlador. Puede editarlo para satisfacer sus necesidades, pero asegúrese de que sea compatible con transformers-neuronx.

cat serving.properties
option.tensor_parallel_degree=2 option.batch_size=2 option.dtype=f16 engine=Python
cat model.py
import torch
import tempfile
import os from transformers.models.opt import OPTForCausalLM
from transformers import AutoTokenizer
from transformers_neuronx import dtypes
from transformers_neuronx.module import save_pretrained_split
from transformers_neuronx.opt.model import OPTForSampling
from djl_python import Input, Output model = None def load_model(properties): batch_size = int(properties.get("batch_size", 2)) tp_degree = int(properties.get("tensor_parallel_degree", 2)) amp = properties.get("dtype", "f16") model_id = "facebook/opt-13b" load_path = os.path.join(tempfile.gettempdir(), model_id) model = OPTForCausalLM.from_pretrained(model_id, low_cpu_mem_usage=True) dtype = dtypes.to_torch_dtype(amp) for block in model.model.decoder.layers: block.self_attn.to(dtype) block.fc1.to(dtype) block.fc2.to(dtype) model.lm_head.to(dtype) save_pretrained_split(model, load_path) tokenizer = AutoTokenizer.from_pretrained(model_id) model = OPTForSampling.from_pretrained(load_path, batch_size=batch_size, amp=amp, tp_degree=tp_degree) model.to_neuron() return model, tokenizer, batch_size def infer(seq_length, prompt): with torch.inference_mode(): input_ids = torch.as_tensor([tokenizer.encode(text) for text in prompt]) generated_sequence = model.sample(input_ids, sequence_length=seq_length) outputs = [tokenizer.decode(gen_seq) for gen_seq in generated_sequence] return outputs def handle(inputs: Input): global model, tokenizer, batch_size if not model: model, tokenizer, batch_size = load_model(inputs.get_properties()) if inputs.is_empty(): # Model server makes an empty call to warmup the model on startup return None data = inputs.get_as_json() seq_length = data["seq_length"] prompt = data["text"] outputs = infer(seq_length, prompt) result = {"outputs": outputs} return Output().add_as_json(result)
mkdir -p models/opt13b logs
mv serving.properties model.py models/opt13b

Ejecute el contenedor de servicio

Los últimos pasos antes de la inferencia son extraer la imagen de Docker para el contenedor de servicio DJL y ejecutarla en nuestra instancia:

docker pull deepjavalibrary/djl-serving:0.21.0-pytorch-inf2

Después de extraer la imagen del contenedor, ejecute el siguiente comando para implementar su modelo. Asegúrese de estar en el directorio correcto que contiene el logs y models subdirectorio porque el comando los asignará al contenedor /opt/directorios.

docker run -it --rm --network=host -v `pwd`/models:/opt/ml/model -v `pwd`/logs:/opt/djl/logs -u djl --device /dev/neuron0 --device /dev/neuron10 --device /dev/neuron2 --device /dev/neuron4 --device /dev/neuron6 --device /dev/neuron8 --device /dev/neuron1 --device /dev/neuron11 -e MODEL_LOADING_TIMEOUT=7200 -e PREDICT_TIMEOUT=360 deepjavalibrary/djl-serving:0.21.0-pytorch-inf2 serve

Ejecutar inferencia

Ahora que implementamos el modelo, probémoslo con un simple comando CURL para pasar algunos datos JSON a nuestro punto final. Debido a que establecemos un tamaño de lote de 2, pasamos el número correspondiente de entradas:

curl -X POST "http://127.0.0.1:8080/predictions/opt13b" -H 'Content-Type: application/json' -d '{"seq_length":2048, "text":[ "Hello, I am a language model,", "Welcome to Amazon Elastic Compute Cloud," ] }'


El comando anterior genera una respuesta en la línea de comandos. El modelo es bastante hablador pero su respuesta valida nuestro modelo. ¡Pudimos ejecutar inferencias en nuestro LLM gracias a Inferentia!

Limpiar

No olvide eliminar su instancia EC2 una vez que haya terminado para ahorrar costos.

Conclusión

En esta publicación, implementamos una instancia Inf2 de Amazon EC2 para alojar un LLM y ejecutamos la inferencia utilizando un contenedor de inferencia de modelo grande. Aprendió cómo interactúan AWS Inferentia y AWS Neuron SDK para permitirle implementar fácilmente LLM para la inferencia con una relación precio-rendimiento óptima. Estén atentos para recibir actualizaciones sobre más capacidades y nuevas innovaciones con Inferentia. Para obtener más ejemplos sobre Neuron, consulte aws-neuron-muestras.


Acerca de los autores

qingweili es un especialista en aprendizaje automático en Amazon Web Services. Recibió su Ph.D. en Investigación de Operaciones después de que rompió la cuenta de subvenciones de investigación de su asesor y no pudo entregar el Premio Nobel que prometió. Actualmente, ayuda a los clientes de la industria de seguros y servicios financieros a crear soluciones de aprendizaje automático en AWS. En su tiempo libre le gusta leer y enseñar.

Pedro Chung es un arquitecto de soluciones para AWS y le apasiona ayudar a los clientes a descubrir información de sus datos. Ha estado creando soluciones para ayudar a las organizaciones a tomar decisiones basadas en datos tanto en el sector público como en el privado. Posee todas las certificaciones de AWS, así como dos certificaciones de GCP. Le gusta el café, cocinar, mantenerse activo y pasar tiempo con su familia.

Aaqib Ansari es ingeniero de desarrollo de software en el equipo de inferencia de Amazon SageMaker. Se centra en ayudar a los clientes de SageMaker a acelerar la inferencia e implementación de modelos. En su tiempo libre le gusta hacer caminatas, correr, fotografiar y dibujar.

qing-lan es ingeniero de desarrollo de software en AWS. Ha estado trabajando en varios productos desafiantes en Amazon, incluidas soluciones de inferencia ML de alto rendimiento y un sistema de registro de alto rendimiento. El equipo de Qing lanzó con éxito el primer modelo de mil millones de parámetros en Amazon Advertising con una latencia muy baja requerida. Qing tiene un conocimiento profundo sobre la optimización de la infraestructura y la aceleración del aprendizaje profundo.

franco liu es un ingeniero de software para AWS Deep Learning. Se centra en la creación de herramientas innovadoras de aprendizaje profundo para ingenieros de software y científicos. En su tiempo libre, le gusta ir de excursión con amigos y familiares.

punto_img

Información más reciente

punto_img