Optimiza la utilización de AWS Inferentia con modelos FastAPI y PyTorch en las instancias Amazon EC2 Inf1 e Inf2
Optimize AWS Inferentia usage with FastAPI and PyTorch models on Amazon EC2 Inf1 and Inf2 instances.
Cuando implementamos modelos de Deep Learning a gran escala, es crucial utilizar de manera efectiva el hardware subyacente para maximizar el rendimiento y los beneficios en costos. Para cargas de trabajo de producción que requieren un alto rendimiento y baja latencia, la selección de la instancia de Amazon Elastic Compute Cloud (EC2), la pila de servidores de modelos y la arquitectura de implementación es muy importante. Una arquitectura ineficiente puede llevar a una utilización subóptima de los aceleradores y costos de producción innecesariamente altos.
En esta publicación te guiaremos a través del proceso de implementación de servidores de modelos FastAPI en dispositivos AWS Inferentia (que se encuentran en las instancias Amazon EC2 Inf1 y Amazon EC2 Inf2). También demostraremos cómo alojar un modelo de ejemplo que se implementa en paralelo en todos los NeuronCores para maximizar la utilización del hardware.
Resumen de la solución
FastAPI es un marco de desarrollo web de código abierto para servir aplicaciones Python que es mucho más rápido que los marcos tradicionales como Flask y Django. Utiliza una interfaz de puerta de enlace de servidor asincrónica (ASGI) en lugar de la interfaz de puerta de enlace de servidor web (WSGI) ampliamente utilizada. ASGI procesa las solicitudes entrantes de manera asíncrona en lugar de procesar las solicitudes secuencialmente como lo hace WSGI. Esto hace que FastAPI sea la opción ideal para manejar solicitudes sensibles a la latencia. Puedes usar FastAPI para implementar un servidor que aloje un punto de conexión en instancias Inferentia (Inf1/Inf2) que escuche las solicitudes de los clientes a través de un puerto designado.
Nuestro objetivo es lograr el máximo rendimiento al menor costo a través de la utilización máxima del hardware. Esto nos permite manejar más solicitudes de inferencia con menos aceleradores. Cada dispositivo AWS Inferentia1 contiene cuatro NeuronCores-v1 y cada dispositivo AWS Inferentia2 contiene dos NeuronCores-v2. El SDK de Neuron de AWS nos permite utilizar cada uno de los NeuronCores en paralelo, lo que nos brinda más control para cargar e inferir cuatro o más modelos en paralelo sin sacrificar el rendimiento.
Con FastAPI, puedes elegir entre varios servidores web en Python (Gunicorn, Uvicorn, Hypercorn, Daphne). Estos servidores web proporcionan una capa de abstracción sobre el modelo de aprendizaje automático (ML) subyacente. El cliente solicitante se beneficia al no tener que conocer el nombre o la versión del modelo que se ha implementado en el servidor; el nombre del punto de conexión ahora es solo un proxy a una función que carga y ejecuta el modelo. En cambio, en una herramienta de implementación específica del marco, como TensorFlow Serving, el nombre y la versión del modelo forman parte del nombre del punto de conexión. Si el modelo cambia en el lado del servidor, el cliente debe conocer y cambiar su llamada API al nuevo punto de conexión correspondiente. Por lo tanto, si estás evolucionando continuamente las versiones de los modelos, como en el caso de las pruebas A/B, utilizar un servidor web genérico en Python con FastAPI es una forma conveniente de servir modelos, porque el nombre del punto de conexión es estático.
- Equipo de investigación avanza un paso en la computación neuromórfica
- Los peligros de compartir en las redes sociales el lado oscuro de c...
- Cambiando la perspectiva de tus datos en Power BI
El papel de un servidor ASGI es generar un número especificado de trabajadores que escuchan las solicitudes de los clientes y ejecutan el código de inferencia. Una capacidad importante del servidor es asegurarse de que el número solicitado de trabajadores estén disponibles y activos. En caso de que un trabajador sea eliminado, el servidor debe lanzar un nuevo trabajador. En este contexto, el servidor y los trabajadores pueden ser identificados por su ID de proceso Unix (PID). Para esta publicación, utilizamos un servidor Hypercorn, que es una opción popular para servidores web en Python.
En esta publicación, compartimos las mejores prácticas para implementar modelos de aprendizaje profundo con FastAPI en AWS Inferentia NeuronCores. Mostramos que puedes implementar varios modelos en NeuronCores separados que se pueden llamar simultáneamente. Esta configuración aumenta el rendimiento porque varios modelos se pueden inferir de manera concurrente y la utilización de NeuronCore está completamente optimizada. El código se puede encontrar en el repositorio de GitHub. La siguiente figura muestra la arquitectura de cómo configurar la solución en una instancia EC2 Inf2.
La misma arquitectura se aplica a un tipo de instancia EC2 Inf1, excepto que tiene cuatro núcleos. Por lo tanto, eso cambia un poco el diagrama de arquitectura.
NeuronCores de AWS Inferentia
Vamos a profundizar un poco más en las herramientas proporcionadas por AWS Neuron para interactuar con los NeuronCores. Las siguientes tablas muestran el número de NeuronCores en cada tipo de instancia Inf1 e Inf2. Las vCPUs del host y la memoria del sistema se comparten en todos los NeuronCores disponibles.
Tamaño de la instancia | # Aceleradores Inferentia | # NeuronCores-v1 | vCPUs | Memoria (GiB) |
Inf1.xlarge | 1 | 4 | 4 | 8 |
Inf1.2xlarge | 1 | 4 | 8 | 16 |
Inf1.6xlarge | 4 | 16 | 24 | 48 |
Inf1.24xlarge | 16 | 64 | 96 | 192 |
Tamaño de la instancia | # Aceleradores Inferentia | # NeuronCores-v2 | vCPUs | Memoria (GiB) |
Inf2.xlarge | 1 | 2 | 4 | 32 |
Inf2.8xlarge | 1 | 2 | 32 | 32 |
Inf2.24xlarge | 6 | 12 | 96 | 192 |
Inf2.48xlarge | 12 | 24 | 192 | 384 |
Las instancias Inf2 contienen los nuevos NeuronCores-v2 en comparación con los NeuronCore-v1 en las instancias Inf1. A pesar de tener menos núcleos, son capaces de ofrecer un rendimiento 4 veces mayor y una latencia 10 veces menor que las instancias Inf1. Las instancias Inf2 son ideales para cargas de trabajo de Aprendizaje Profundo como AI Generativa, Modelos de Lenguaje Grandes (LLM) en la familia OPT/GPT y transformadores de visión como Diffusion Estable.
El tiempo de ejecución de Neuron es responsable de ejecutar modelos en dispositivos Neuron. El tiempo de ejecución de Neuron determina qué NeuronCore ejecutará qué modelo y cómo se ejecutará. La configuración del tiempo de ejecución de Neuron se controla mediante el uso de variables de entorno a nivel de proceso. Por defecto, las extensiones del marco de trabajo de Neuron se encargarán de la configuración del tiempo de ejecución de Neuron en nombre del usuario; sin embargo, también son posibles configuraciones explícitas para lograr un comportamiento más optimizado.
Dos variables de entorno populares son NEURON_RT_NUM_CORES
y NEURON_RT_VISIBLE_CORES
. Con estas variables de entorno, los procesos de Python pueden estar asociados a un NeuronCore. Con NEURON_RT_NUM_CORES
, se pueden reservar un número especificado de núcleos para un proceso, y con NEURON_RT_VISIBLE_CORES
, se pueden reservar un rango de NeuronCores. Por ejemplo, NEURON_RT_NUM_CORES=2 myapp.py
reservará dos núcleos y NEURON_RT_VISIBLE_CORES=’0-2’ myapp.py
reservará cero, uno y dos núcleos para myapp.py
. También se pueden reservar NeuronCores en varios dispositivos (chips AWS Inferentia). Entonces, NEURON_RT_VISIBLE_CORES=’0-5’ myapp.py
reservará los primeros cuatro núcleos en device1
y un núcleo en device2
en un tipo de instancia Ec2 Inf1. Del mismo modo, en un tipo de instancia EC2 Inf2, esta configuración reservará dos núcleos en device1
y device2
y un núcleo en device3
. La siguiente tabla resume la configuración de estas variables.
Nombre | Descripción | Tipo | Valores Esperados | Valor por Defecto | Versión de RT |
NEURON_RT_VISIBLE_CORES |
Rango de NeuronCores específicos necesarios por el proceso | Rango de enteros (como 1-3) | Cualquier valor o rango entre 0 y el máximo de NeuronCore en el sistema | Ninguno | 2.0+ |
NEURON_RT_NUM_CORES |
Número de NeuronCores requeridos por el proceso | Entero | Un valor de 1 al máximo de NeuronCore en el sistema | 0, que se interpreta como “todos” | 2.0+ |
Para obtener una lista de todas las variables de entorno, consulte la Configuración de Neuron Runtime.
De forma predeterminada, al cargar modelos, los modelos se cargan en NeuronCore 0 y luego en NeuronCore 1 a menos que se indique explícitamente en las variables de entorno anteriores. Como se especificó anteriormente, los NeuronCores comparten los vCPUs disponibles del host y la memoria del sistema. Por lo tanto, los modelos desplegados en cada NeuronCore competirán por los recursos disponibles. Esto no será un problema si el modelo está utilizando los NeuronCores en gran medida. Pero si un modelo se ejecuta solo parcialmente en los NeuronCores y el resto en los vCPUs del host, entonces es importante tener en cuenta la disponibilidad de la CPU por NeuronCore. Esto también afecta la elección de la instancia.
La siguiente tabla muestra el número de vCPUs del host y la memoria del sistema disponibles por modelo si se desplegara un modelo en cada NeuronCore. Dependiendo del uso de NeuronCore de su aplicación, el uso de vCPUs y memoria, se recomienda realizar pruebas para averiguar qué configuración es más eficiente para su aplicación. La herramienta Neuron Top puede ayudar a visualizar la utilización de los núcleos y la utilización de la memoria del dispositivo y del host. En función de estas métricas, se puede tomar una decisión informada. Demostramos el uso de Neuron Top al final de este blog.
Tamaño de la Instancia | # Aceleradores Inferentia | # Modelos | vCPUs/Modelo | Memoria/Modelo (GiB) |
Inf1.xlarge | 1 | 4 | 1 | 2 |
Inf1.2xlarge | 1 | 4 | 2 | 4 |
Inf1.6xlarge | 4 | 16 | 1.5 | 3 |
Inf1.24xlarge | 16 | 64 | 1.5 | 3 |
Tamaño de la instancia | # Aceleradores Inferentia | # Modelos | vCPUs/Modelo | Memoria/Modelo (GiB) |
Inf2.xlarge | 1 | 2 | 2 | 8 |
Inf2.8xlarge | 1 | 2 | 16 | 64 |
Inf2.24xlarge | 6 | 12 | 8 | 32 |
Inf2.48xlarge | 12 | 24 | 8 | 32 |
Para probar las características del SDK de Neuron tú mismo, revisa las últimas capacidades de Neuron para PyTorch.
Configuración del sistema
La siguiente es la configuración del sistema utilizada para esta solución:
- Tamaño de la instancia – 6xlarge (si se utiliza Inf1), Inf2.xlarge (si se utiliza Inf2)
- Imagen para la instancia – Deep Learning AMI Neuron PyTorch 1.11.0 (Ubuntu 20.04) 20230125
- Modelo – https://huggingface.co/twmkn9/bert-base-uncased-squad2
- Framework – PyTorch
Configurar la solución
Hay algunas cosas que debemos hacer para configurar la solución. Comienza creando un rol IAM que tu instancia EC2 va a asumir y que le permitirá empujar y jalar desde Amazon Elastic Container Registry.
Paso 1: Configurar el rol IAM
- Comienza iniciando sesión en la consola y accediendo a IAM > Roles > Crear rol
- Selecciona el tipo de entidad confiable
AWS Service
- Selecciona EC2 como el servicio para el caso de uso
- Haz clic en Siguiente y podrás ver todas las políticas disponibles
- Para el propósito de esta solución, vamos a darle a nuestra instancia EC2 acceso completo a ECR. Filtra por AmazonEC2ContainerRegistryFullAccess y selecciónalo.
- Presiona siguiente y nombra el rol
inf-ecr-access
Nota: la política que adjuntamos le da a la instancia EC2 acceso completo a Amazon ECR. Recomendamos encarecidamente seguir el principio de privilegio mínimo para cargas de trabajo de producción.
Paso 2: Configurar AWS CLI
Si estás utilizando la AMI de Aprendizaje Profundo prescrita mencionada anteriormente, ya viene con AWS CLI instalado. Si estás utilizando una AMI diferente (Amazon Linux 2023, Base Ubuntu, etc.), instala las herramientas de CLI siguiendo esta guía.
Una vez que tengas las herramientas de CLI instaladas, configura la CLI usando el comando aws configure
. Si tienes claves de acceso, puedes agregarlas aquí, pero no necesariamente las necesitas para interactuar con los servicios de AWS. Estamos confiando en los roles de IAM para hacer eso.
Nota: Necesitamos ingresar al menos un valor (región predeterminada o formato predeterminado) para crear el perfil predeterminado. Para este ejemplo, vamos con us-east-2
como la región y json
como la salida predeterminada.
Clonar el repositorio de Github
El repositorio de GitHub proporciona todos los scripts necesarios para implementar modelos utilizando FastAPI en NeuronCores en instancias AWS Inferentia. Este ejemplo utiliza contenedores Docker para asegurarse de que podamos crear soluciones reutilizables. Incluido en este ejemplo se encuentra el siguiente archivo config.properties para que los usuarios proporcionen entradas.
# Nombre de la imagen y contenedor de Docker
docker_image_name_prefix=<Nombre de la imagen de Docker>
docker_container_name_prefix=<Nombre del contenedor de Docker>
# Configuración de implementación
path_to_traced_models=<Ruta al modelo rastreado>
compiled_model=<Nombre del archivo del modelo compilado>
num_cores=<Número de NeuronCores para implementar un servidor de modelos>
num_models_per_server=<Número de modelos para cargar por servidor>
El archivo de configuración necesita prefijos de nombres definidos por el usuario para la imagen de Docker y los contenedores de Docker. El script build.sh
en las carpetas fastapi
y trace-model
utiliza esto para crear imágenes de Docker.
Compilar un modelo en AWS Inferentia
Comenzaremos rastreando el modelo y produciendo un archivo PyTorch Torchscript .pt. Comience accediendo al directorio trace-model
y modificando el archivo .env. Dependiendo del tipo de instancia que elija, modifique el CHIP_TYPE
dentro del archivo .env
. Como ejemplo, elegiremos Inf2 como guía. Los mismos pasos se aplican al proceso de implementación para Inf1.
A continuación, establezca la región predeterminada en el mismo archivo. Esta región se utilizará para crear un repositorio ECR y las imágenes de Docker se enviarán a este repositorio. También en esta carpeta, proporcionamos todos los scripts necesarios para rastrear un modelo bert-base-uncased
en AWS Inferentia. Este script se puede utilizar para la mayoría de los modelos disponibles en Hugging Face. El archivo Dockerfile tiene todas las dependencias para ejecutar modelos con Neuron y ejecuta el código trace-model.py como punto de entrada.
Explicación de la compilación de Neuron
La API del SDK de Neuron se parece mucho a la API de Python de PyTorch. El torch.jit.trace()
de PyTorch toma el modelo y el tensor de entrada de ejemplo como argumentos. Las entradas de ejemplo se alimentan al modelo y se registran las operaciones que se invocan a medida que esa entrada atraviesa las capas del modelo como TorchScript. Para obtener más información sobre la traza JIT en PyTorch, consulte la siguiente documentación.
Al igual que torch.jit.trace()
, puede verificar si su modelo se puede compilar en AWS Inferentia con el siguiente código para instancias inf1.
import torch_neuron
model_traced = torch.neuron.trace(model,
example_inputs,
compiler_args =
[‘--fast-math’, ‘fp32-cast-matmul’,
‘--neuron-core-pipeline-cores’,’1’],
optimizations=[torch_neuron.Optimization.FLOAT32_TO_FLOAT16])
Para inf2, la biblioteca se llama torch_neuronx
. Así es como puedes probar la compilación de tu modelo en instancias inf2.
import torch
import torch_neuronx
model_traced = torch.neuronx.trace(model,
example_inputs,
compiler_args =
[‘--fast-math’, ‘fp32-cast-matmul’,
‘--neuron-core-pipeline-cores’,’1’],
optimizations=[torch_neuronx.Optimization.FLOAT32_TO_FLOAT16])
Después de crear la instancia de traza, podemos pasar la entrada del tensor de ejemplo de la siguiente manera:
answer_logits = model_traced(*example_inputs)
Y finalmente guardar la salida TorchScript resultante en el disco local
model_traced.save('./compiled-model-bs-{batch_size}.pt')
Como se muestra en el código anterior, puedes usar compiler_args
y optimizations
para optimizar la implementación. Para obtener una lista detallada de argumentos para la API torch.neuron.trace
, consulta la documentación de la API de Python de traza de PyTorch-Neuron.
Ten en cuenta los siguientes puntos importantes:
- El SDK de Neuron no admite formas de tensor dinámicas en el momento de escribir esto. Por lo tanto, un modelo deberá compilarse por separado para diferentes formas de entrada. Para obtener más información sobre la ejecución de inferencia en formas de entrada variable con agrupamiento, consulta la ejecución de inferencia en formas de entrada variable con agrupamiento.
- Si te enfrentas a problemas de falta de memoria al compilar un modelo, intenta compilar el modelo en una instancia AWS Inferentia con más vCPUs o memoria, o incluso una instancia c6i o r6i grande, ya que la compilación solo utiliza CPUs. Una vez compilado, es probable que el modelo rastreado se pueda ejecutar en tamaños de instancia AWS Inferentia más pequeños.
Explicación del proceso de construcción
Ahora construiremos este contenedor ejecutando build.sh. El archivo de script de construcción simplemente crea la imagen de Docker descargando una imagen base de contenedor de aprendizaje profundo y instalando el paquete HuggingFace transformers
. Basado en el CHIP_TYPE
especificado en el archivo .env
, el archivo docker.properties
decide la BASE_IMAGE
apropiada. Esta BASE_IMAGE
apunta a una imagen de contenedor de aprendizaje profundo para Neuron Runtime proporcionada por AWS.
Está disponible a través de un repositorio privado de ECR. Antes de poder descargar la imagen, necesitamos iniciar sesión y obtener credenciales temporales de AWS.
aws ecr get-login-password --region <región> | docker login --username AWS --password-stdin 763104351884.dkr.ecr.<región>.amazonaws.com
Nota: necesitamos reemplazar la región que aparece en el comando especificado por la bandera de región y dentro de la URI del repositorio con la región que colocamos en el archivo .env.
Con el fin de facilitar este proceso, podemos usar el archivo fetch-credentials.sh
. La región se tomará automáticamente del archivo .env.
A continuación, vamos a empujar la imagen usando el script push.sh. El script de empuje crea un repositorio en Amazon ECR para ti y empuja la imagen del contenedor.
Finalmente, cuando la imagen esté construida y empujada, podemos ejecutarla como un contenedor ejecutando run.sh y ver los registros en ejecución con logs.sh. En los registros del compilador (ver la siguiente captura de pantalla), verás el porcentaje de operadores aritméticos compilados en Neuron y el porcentaje de subgrafos de modelo compilados con éxito en Neuron. La captura de pantalla muestra los registros del compilador para el modelo bert-base-uncased-squad2
. Los registros muestran que se compiló el 95.64% de los operadores aritméticos, y también da una lista de los operadores que se compilaron en Neuron y los que no son compatibles.
Aquí tienes una lista de todos los operadores compatibles en la última versión del paquete PyTorch Neuron. De manera similar, aquí tienes la lista de todos los operadores compatibles en la última versión del paquete PyTorch Neuronx.
Desplegar modelos con FastAPI
Después de que los modelos estén compilados, el modelo trazado estará presente en la carpeta trace-model
. En este ejemplo, hemos colocado el modelo trazado para un tamaño de lote de 1. Consideramos un tamaño de lote de 1 aquí para tener en cuenta aquellos casos de uso donde un tamaño de lote más alto no es factible o necesario. Para casos de uso que requieren tamaños de lote más altos, la API torch.neuron.DataParallel (para Inf1) o torch.neuronx.DataParallel (para Inf2) también pueden ser útiles.
La carpeta fast-api proporciona todos los scripts necesarios para desplegar modelos con FastAPI. Para desplegar los modelos sin ningún cambio, simplemente ejecuta el script deploy.sh y construirá una imagen de contenedor de FastAPI, ejecutará contenedores en el número especificado de núcleos y desplegará el número especificado de modelos por servidor en cada servidor de modelo FastAPI. Esta carpeta también contiene un archivo .env
, modifícalo para reflejar el CHIP_TYPE
y el AWS_DEFAULT_REGION
correctos.
Nota: Los scripts de FastAPI dependen de las mismas variables de entorno utilizadas para construir, empujar y ejecutar las imágenes como contenedores. Los scripts de despliegue de FastAPI utilizarán los últimos valores conocidos de estas variables. Por lo tanto, si trazaste el modelo para el tipo de instancia Inf1 por última vez, ese modelo se desplegará a través de estos scripts.
El archivo fastapi-server.py, que es responsable de alojar el servidor y enviar las solicitudes al modelo, hace lo siguiente:
- Lee el número de modelos por servidor y la ubicación del modelo compilado desde el archivo de propiedades
- Establece las NeuronCores visibles como variables de entorno para el contenedor de Docker y lee las variables de entorno para especificar qué NeuronCores usar
- Proporciona una API de inferencia para el modelo
bert-base-uncased-squad2
- Con
jit.load()
, carga el número de modelos por servidor según lo especificado en la configuración y almacena los modelos y los tokenizadores requeridos en diccionarios globales
Con esta configuración, sería relativamente fácil configurar APIs que enumeren qué modelos y cuántos modelos se almacenan en cada NeuronCore. De manera similar, se podrían escribir APIs para eliminar modelos de NeuronCores específicos.
El Dockerfile para construir contenedores FastAPI se basa en la imagen de Docker que construimos para rastrear los modelos. Es por eso que el archivo docker.properties especifica la ruta ECR a la imagen de Docker para rastrear los modelos. En nuestra configuración, los contenedores de Docker en todos los NeuronCores son similares, por lo que podemos construir una sola imagen y ejecutar múltiples contenedores desde una imagen. Para evitar cualquier error de punto de entrada, especificamos ENTRYPOINT ["/usr/bin/env"]
en el Dockerfile antes de ejecutar el script startup.sh
, que se ve como hypercorn fastapi-server:app -b 0.0.0.0:8080
. Este script de inicio es el mismo para todos los contenedores. Si estás utilizando la misma imagen base que para rastrear modelos, puedes construir este contenedor simplemente ejecutando el script build.sh. El script push.sh
permanece igual que antes para rastrear modelos. La imagen modificada de Docker y el nombre del contenedor son proporcionados por el archivo docker.properties
.
El archivo run.sh
hace lo siguiente:
- Lee la imagen de Docker y el nombre del contenedor desde el archivo de propiedades, que a su vez lee el archivo
config.properties
, que tiene una configuración de usuarionum_cores
- Inicia un bucle desde 0 hasta
num_cores
y para cada núcleo:- Establece el número de puerto y el número de dispositivo
- Establece la variable de entorno
NEURON_RT_VISIBLE_CORES
- Especifica el montaje del volumen
- Ejecuta un contenedor de Docker
Para mayor claridad, el comando de ejecución de Docker para implementar en NeuronCore 0 para Inf1 se vería como el siguiente código:
docker run -t -d \
--name $ bert-inf-fastapi-nc-0 \
--env NEURON_RT_VISIBLE_CORES="0-0" \
--env CHIP_TYPE="inf1" \
-p ${port_num}:8080 --device=/dev/neuron0 ${registry}/ bert-inf-fastapi
El comando de ejecución para implementar en NeuronCore 5 se vería como el siguiente código:
docker run -t -d \
--name $ bert-inf-fastapi-nc-5 \
--env NEURON_RT_VISIBLE_CORES="5-5" \
--env CHIP_TYPE="inf1" \
-p ${port_num}:8080 --device=/dev/neuron0 ${registry}/ bert-inf-fastapi
Después de que los contenedores se implementen, usamos el script run_apis.py, que llama a las APIs en hilos paralelos. El código está configurado para llamar a seis modelos implementados, uno en cada NeuronCore, pero se puede cambiar fácilmente a una configuración diferente. Llamamos a las APIs desde el lado del cliente de la siguiente manera:
import requests
url_template = http://localhost:%i/predictions_neuron_core_%i/model_%i
# NeuronCore 0
response = requests.get(url_template % (8081,0,0))
# NeuronCore 5
response = requests.get(url_template % (8086,5,0))
Monitorear NeuronCore
Después de que los servidores de modelos se implementen, para monitorear la utilización de NeuronCore, podemos usar neuron-top
para observar en tiempo real el porcentaje de utilización de cada NeuronCore. neuron-top es una herramienta de línea de comandos en el SDK de Neuron que proporciona información como NeuronCore, vCPU y utilización de memoria. En una terminal separada, ingresa el siguiente comando:
neuron-top
La salida debería ser similar a la siguiente figura. En este escenario, hemos especificado usar dos NeuronCores y dos modelos por servidor en una instancia Inf2.xlarge. La siguiente captura de pantalla muestra que se cargan dos modelos de tamaño 287.8MB cada uno en dos NeuronCores. Con un total de 4 modelos cargados, se puede ver que se utiliza 1.3 GB de memoria del dispositivo. Usa las teclas de flecha para moverte entre los NeuronCores en diferentes dispositivos
De manera similar, en un tipo de instancia Inf1.16xlarge vemos un total de 12 modelos (2 modelos por núcleo sobre 6 núcleos) cargados. Se consume un total de 2.1 GB de memoria y cada modelo tiene un tamaño de 177.2 MB.
Después de ejecutar el script run_apis.py, puedes ver el porcentaje de utilización de cada uno de los seis NeuronCores (ver la siguiente captura de pantalla). También puedes ver el uso de vCPU del sistema y el uso de vCPU en tiempo de ejecución.
La siguiente captura de pantalla muestra el porcentaje de uso del núcleo de la instancia Inf2.
De manera similar, esta captura de pantalla muestra la utilización del núcleo en un tipo de instancia inf1.6xlarge.
Limpieza
Para limpiar todos los contenedores de Docker que has creado, proporcionamos un script cleanup.sh que elimina todos los contenedores en ejecución y detenidos. Este script eliminará todos los contenedores, así que no lo uses si quieres mantener algunos contenedores en ejecución.
Conclusión
Las cargas de trabajo de producción a menudo tienen altos volúmenes de datos, baja latencia y requisitos de costo. Las arquitecturas ineficientes que utilizan subóptimamente aceleradores podrían generar costos de producción innecesariamente altos. En esta publicación, mostramos cómo utilizar de manera óptima los NeuronCores con FastAPI para maximizar el volumen de datos con una latencia mínima. Hemos publicado las instrucciones en nuestro repositorio de GitHub. Con esta arquitectura de solución, puedes implementar múltiples modelos en cada NeuronCore y operar múltiples modelos en paralelo en diferentes NeuronCores sin perder rendimiento. Para obtener más información sobre cómo implementar modelos a gran escala con servicios como Amazon Elastic Kubernetes Service (Amazon EKS), consulta Serve 3,000 deep learning models on Amazon EKS with AWS Inferentia for under $50 an hour.