Onnxruntime Flow 1260x609.jpg

ONNX es un marco de aprendizaje automático (ML) de código abierto que proporciona interoperabilidad en una amplia gama de marcos, sistemas operativos y plataformas de hardware. Tiempo de ejecución de ONNX es el motor de ejecución utilizado para la inferencia de modelos y el entrenamiento con ONNX.

AWS Gravitón3 Los procesadores están optimizados para cargas de trabajo de ML, incluida la compatibilidad con instrucciones bfloat16, Scalable Vector Extension (SVE) y Matrix Multiplication (MMLA). Los kernels SGEMM acelerados por Bfloat16 y los kernels GEMM cuantificados (QGEMM) acelerados por int8 MMLA en ONNX han mejorado el rendimiento de inferencia hasta en un 65% para la inferencia fp32 y hasta un 30% para la inferencia cuantificada int8 para varios modelos de procesamiento de lenguaje natural (NLP) en AWS Graviton3. basado Nube informática elástica de Amazon (Amazon EC2) instancias. Versión inicial v1.17.0ONNX Runtime admite estos núcleos optimizados.

En esta publicación, mostramos cómo ejecutar la inferencia de ONNX Runtime en instancias EC2 basadas en AWS Graviton3 y cómo configurarlas para usar kernels GEMM optimizados. También demostramos la aceleración resultante mediante evaluaciones comparativas.

Núcleos GEMM optimizados

ONNX Runtime admite el backend de subrutina de álgebra lineal (MLAS) de Microsoft como proveedor de ejecución (EP) predeterminado para operadores de aprendizaje profundo. Las instancias EC2 basadas en AWS Graviton3 (instancias c7g, m7g, r7g, c7gn y Hpc7g) admiten el formato bfloat16 e instrucciones MMLA para la aceleración del operador de aprendizaje profundo. Estas instrucciones mejoran la utilización del hardware SIMD y reducen la latencia de inferencia de un extremo a otro hasta 1,65 veces en comparación con los núcleos basados ​​en instrucciones del producto armv8 DOT.

El equipo de AWS implementó núcleos MLAS para matemáticas rápidas bfloat16 y multiplicación de matriz general (GEMM) cuantificada int8 utilizando instrucciones BFMMLA, SMMLA y UMMLA, que tienen un mayor rendimiento de multiplicación de matrices en comparación con las instrucciones DOT. La compatibilidad con bfloat16 permite la implementación eficiente de modelos entrenados con bfloat16, fp32 y precisión mixta automática (AMP) sin necesidad de cuantificación. Como se muestra en los siguientes diagramas, los núcleos GEMM optimizados se integran en el EP de CPU ONNX Runtime como núcleos MLAS.

La primera figura ilustra la pila de software ONNX y resalta (en naranja) los componentes optimizados para mejorar el rendimiento de inferencia en la plataforma AWS Graviton3.

El siguiente diagrama ilustra el flujo de ONNX Runtime EP y resalta (en naranja) los componentes optimizados para mejorar el rendimiento de inferencia en la plataforma AWS Graviton3.

onnxruntime_flow_Graviton_kernels

Habilitar las optimizaciones.

Las optimizaciones son parte de ONNX Runtime. 1.17.0 lanzamiento y están disponibles a partir de onnxruntime-1.17.0 ruedas de Python y paquetes conda-1.17.0. Los kernels int8 optimizados están habilitados de forma predeterminada y se seleccionarán automáticamente para los procesadores AWS Graviton3. Los kernels matemáticos rápidos Bfloat16, por otro lado, no están habilitados de forma predeterminada y necesitan las siguientes opciones de sesión en ONNX Runtime para habilitarlos:

# Para aplicaciones C++

SessionOptions so; 
so.config_options.AddConfigEntry( kOrtSessionOptionsMlasGemmFastMathArm64Bfloat16, "1");

# Para aplicaciones Python

sess_options = onnxruntime.SessionOptions()
sess_options.add_session_config_entry("mlas.enable_gemm_fastmath_arm64_bfloat16", "1")

Resultados de referencia

Comenzamos midiendo el rendimiento de inferencia, en consultas por segundo, para el modelo fp32 sin ninguna de nuestras optimizaciones (usando ONNX Runtime 1.16.0), que está marcado en 1,0 con la línea de puntos roja en el siguiente gráfico. Luego comparamos las mejoras de los núcleos matemáticos rápidos bfloat16 de ONNX Runtime 1.17.1 para la misma inferencia del modelo fp32. Los resultados normalizados se representan en el gráfico. Puede ver que para los modelos BERT, RoBERTa y GPT2, la mejora del rendimiento es de hasta un 65 %. Se observan mejoras similares para la latencia de inferencia.

fp32_perf_improvement_onnx

De manera similar al gráfico de comparación de inferencia de fp32 anterior, comenzamos midiendo el rendimiento de inferencia, en consultas por segundo, para el modelo cuantificado int8 sin ninguna de nuestras optimizaciones (usando ONNX Runtime 1.16.0), que está marcado en 1.0 con el punto rojo. línea en el siguiente gráfico. Luego comparamos las mejoras de los kernels MMLA optimizados de ONNX Runtime 1.17.1 para la misma inferencia de modelo. Los resultados normalizados se representan en el gráfico. Puede ver que para los modelos BERT, RoBERTa y GPT2, la mejora del rendimiento es de hasta un 30 %. Se observan mejoras similares para la latencia de inferencia.

int8_perf_improvement_onnx

Configuración de referencia

Usamos un AWS Graviton3 basado c7g.4xl Instancia EC2 con AMI basada en Ubuntu 22.04 para demostrar las mejoras de rendimiento con los kernels GEMM optimizados de ONNX Runtime. La instancia y los detalles de la AMI se mencionan en el siguiente fragmento:

Instance: c7g.4xl instance
Region: us-west-2
AMI: ami-0a24e6e101933d294 (Ubuntu 22.04/Jammy with 6.5.0-1014-aws kernel)

El repositorio ONNX Runtime proporciona scripts de evaluación comparativa de inferencia para modelos de lenguaje basados ​​en transformadores. Los scripts admiten una amplia gama de modelos, marcos y formatos. Elegimos modelos BERT, RoBERTa y GPT basados ​​en PyTorch para cubrir las tareas de lenguaje común, como clasificación de texto, análisis de sentimientos y predicción de palabras enmascaradas. Los modelos cubren la arquitectura de transformadores codificadores y decodificadores.

El siguiente código enumera los pasos para ejecutar la inferencia para el modelo fp32 con el modo matemático rápido bfloat16 y el modo cuantificado int8 utilizando el script de evaluación comparativa ONNX Runtime. El script descarga los modelos, los exporta al formato ONNX, los cuantifica en int8 para la inferencia int8 y ejecuta la inferencia para diferentes longitudes de secuencia y tamaños de lote. Una vez completado con éxito el script, imprimirá el rendimiento de inferencia en consultas/seg (QPS) y la latencia en mseg junto con la configuración del sistema. Referirse a Script de evaluación comparativa de tiempo de ejecución de ONNX para más detalles.

# Install Python
sudo apt-get update
sudo apt-get install -y python3 python3-pip

# Upgrade pip3 to the latest version
python3 -m pip install --upgrade pip

# Install onnx and onnx runtime
# NOTE: We used 1.17.1 instead of 1.17.0 as it was the latest
# version available while collecting data for this post
python3 -m pip install onnx==1.15.0 onnxruntime==1.17.1

# Install the dependencies
python3 -m pip install transformers==4.38.1 torch==2.2.1 psutil==5.9.8

# Clone onnxruntime repo to get the benchmarking scripts
git clone --recursive https://github.com/microsoft/onnxruntime.git
cd onnxruntime
git checkout 430a086f22684ad0020819dc3e7712f36fe9f016
cd onnxruntime/python/tools/transformers

# To run bert-large fp32 inference with bfloat16 fast math mode
python3 benchmark.py -m bert-large-uncased -p fp32 --enable_arm64_bfloat16_fastmath_mlas_gemm

# To run bert-base  fp32 inference with bfloat16 fast math mode
python3 benchmark.py -m bert-base-cased -p fp32 --enable_arm64_bfloat16_fastmath_mlas_gemm

# To run roberta-base  fp32 inference with bfloat16 fast math mode
python3 benchmark.py -m roberta-base -p fp32 --enable_arm64_bfloat16_fastmath_mlas_gemm

# To run gpt2  fp32 inference with bfloat16 fast math mode
python3 benchmark.py -m gpt2 -p fp32 --enable_arm64_bfloat16_fastmath_mlas_gemm

# To run bert-large int8 quantized inference
python3 benchmark.py -m bert-large-uncased -p int8

# To run bert-base int8 quantized inference
python3 benchmark.py -m bert-base-cased -p int8

# To run roberta-base int8 quantized inference
python3 benchmark.py -m roberta-base -p int8

# To run gpt2 int8 quantized inference
python3 benchmark.py -m gpt2 -p int8

Conclusión

En esta publicación, analizamos cómo ejecutar la inferencia de ONNX Runtime en una instancia EC2 basada en AWS Graviton3 y cómo configurar la instancia para usar kernels GEMM optimizados. También demostramos las aceleraciones resultantes. ¡Esperamos que lo pruebes!

Si encuentra casos de uso en los que no se observan mejoras de rendimiento similares en AWS Graviton, abra un problema en la Guía técnica de AWS Graviton. GitHub para informarnos al respecto.


Sobre el Autor

Sunita Nadampalli es gerente de desarrollo de software en AWS. Dirige las optimizaciones del rendimiento del software Graviton para cargas de trabajo de aprendizaje automático y HPC. Le apasiona el desarrollo de software de código abierto y la entrega de soluciones de software sostenibles y de alto rendimiento con Arm SoC.