Guía GCC para procesadores Ampere — CodesCode

Aprende a utilizar de manera efectiva GCC para optimizar aplicaciones que se ejecutan en procesadores Ampere.

Este artículo fue originalmente publicado por Ampere Computing.

Este artículo describe cómo utilizar de manera efectiva las opciones del GNU Compiler Collection (GCC) para optimizar el rendimiento de las aplicaciones en los procesadores de Ampere.

Cuando se intenta optimizar una aplicación, es esencial medir si una posible optimización mejora el rendimiento. Esto incluye las opciones del compilador. El uso de opciones avanzadas del compilador puede resultar en un mejor rendimiento en tiempo de ejecución, pero potencialmente a costa de un tiempo de compilación más largo, mayores dificultades de depuración y, a menudo, un mayor tamaño binario. Por qué las opciones del compilador afectan el rendimiento está fuera del alcance de este artículo, aunque la respuesta breve es que la generación de código, las arquitecturas de procesadores modernos y cómo interactúan son muy complicados. Otro punto importante es que diferentes procesadores pueden beneficiarse de diferentes opciones del compilador debido a las variaciones en la arquitectura informática y la microarquitectura específica. La experimentación repetida con optimizaciones es clave para el éxito en el rendimiento.

La forma de medir el rendimiento de una aplicación para determinar los factores limitantes, así como las estrategias de optimización, ya se ha cubierto en artículos publicados anteriormente. El artículo, Las primeras 10 preguntas que debes responder al ejecutarse en instancias basadas en Ampere Altra, describe qué datos de rendimiento recopilar para comprender el rendimiento de todo el sistema. Una metodología de análisis de rendimiento para optimizar procesadores de la familia Ampere Altra explica cómo optimizar de manera efectiva y eficiente utilizando un enfoque basado en datos.

Este artículo resume primero las opciones más comunes del GCC, con una descripción de cómo estas opciones afectan a las aplicaciones. La discusión luego se enfoca en presentar casos de estudio utilizando las opciones del GCC para mejorar el rendimiento del software de codificación de video VP9 y de la base de datos MySQL para los procesadores de Ampere. Estrategias similares se han utilizado de manera efectiva para optimizar otros software que se ejecuta en procesadores de Ampere.

Recomendaciones de GCC

El compilador GCC ofrece muchas opciones que pueden mejorar el rendimiento de las aplicaciones. Consulta el sitio web de GCC para obtener más detalles. Para generar código que aproveche todas las funciones de rendimiento disponibles en los procesadores de Ampere, utiliza la opción gcc -mcpu.

Para utilizar la opción gcc -mcpu, establece el modelo de CPU o dile a GCC que utilice el modelo de CPU basado en la máquina en la que se está ejecutando GCC a través de -mcpu=native. Ten en cuenta que en los sistemas heredados basados en x86, gcc -mcpu es un sinónimo obsoleto de -mtune, mientras que gcc -mcpu es totalmente compatible con los sistemas basados en Arm. Consulta la guía de Arm sobre banderas del compilador en diferentes arquitecturas: -march, -mtune y -mcpu para obtener más detalles.

En resumen, siempre que sea posible, utiliza solo -mcpu y evita -march y -mtune al compilar para Arm. A continuación se muestra un caso de estudio que destaca las mejoras de rendimiento al establecer la opción gcc -mcpu con el software de codificación de video VP9.

Estableciendo la opción -mcpu:

  • -mcpu=ampere1: Genera código que se ejecutará en procesadores AmpereOne. AmpereOne es la próxima generación de procesadores nativos de la nube de Ampere, que amplía la familia de procesadores de alto rendimiento a nuevos recuentos líderes en la industria de núcleos. Ten en cuenta que esto puede generar código que no se ejecutará en procesadores Ampere Altra y Altra Max. Esta opción estaba disponible inicialmente en la versión 12.1 de GCC y posteriormente se volvió a compatibilizar con GCC 10.5 y GCC 11.3.

  • -mcpu=neoverse-n1: Genera código que se ejecutará en Ampere Altra, Ampere Altra Max y Ampere AmpereOne. Si bien se admite el uso de esta opción para el código que se ejecutará en Ampere AmpereOne, potencialmente no aprovechará todas las nuevas funciones de rendimiento disponibles. Ten en cuenta que se requiere la versión 9.1 o superior de GCC para habilitar las ajustes específicos del procesador para Ampere Altra y Ampere Altra Max.

  • -mcpu=native: Genera código estableciendo el modelo de CPU en función de la CPU en la que GCC se está ejecutando. Ten en cuenta que se requiere la versión 9.1 o superior de GCC para habilitar las ajustes específicos del procesador para Ampere Altra y Ampere Altra Max.

Usar -mcpu=native es potencialmente más fácil de usar, aunque tiene un problema potencial si el ejecutable, biblioteca compartida o archivo objeto se utilizan en un sistema diferente. Si la compilación se realizó en un procesador Ampere AmpereOne, es posible que el código no se ejecute en un procesador Ampere Altra o Altra Max porque el código generado puede incluir instrucciones Armv8.6+ admitidas en procesadores Ampere AmpereOne. Si la compilación se realizó en un procesador Ampere Altra o Altra Max, GCC no aprovechará las últimas mejoras de rendimiento disponibles en procesadores Ampere AmpereOne. Este es un problema general al compilar código para aprovechar características de rendimiento para cualquier arquitectura.

La siguiente tabla muestra qué versiones de GCC admiten los valores de -mcpu para procesadores Ampere.

Procesador Valor -mcpu GCC 9 GCC 10 GCC 11 GCC 12 GCC 13
Ampere Altra neoverse-n1 ≥ 9.1 TODOS TODOS TODOS TODOS
Ampere Altra Max neoverse-n1 ≥ 9.1 TODOS TODOS TODOS TODOS
AmpereOne ampere1 N/A ≥ 10.5 ≥ 11.3 ≥ 12.1 TODOS

Nuestra recomendación es usar la opción gcc -mcpu con el valor correspondiente mencionado anteriormente (-mcpu=ampere1, -mcpu=neoverse-n1 o -mcpu=native) con -O2 para establecer una base para el rendimiento, y luego explorar opciones adicionales de optimización y medir si las diferentes opciones mejoran el rendimiento en comparación con la base.

Resumen de las opciones comunes de GCC:

  • -mcpu Recomendado al compilar en procesadores Ampere para habilitar ajustes y optimizaciones específicos del procesador. (Consulte la sección “Configuración de la opción -mcpu” anterior para obtener más detalles.)

  • -Os Optimiza para reducir el tamaño del código, potencialmente si su aplicación está limitada por la obtención de instrucciones.

  • -O2 Considerada la opción estándar de optimización de GCC y es buena para usar como base para comparar con otras opciones de GCC.

  • -O3 Agrega optimizaciones adicionales para generar código más eficiente para bucles, útil para probar si el rendimiento de su aplicación está dominado por el tiempo invertido en bucles.

  • Optimización basada en Perfilado (PGO): -fprofile-generate y -fprofile-use. Genera datos de perfil que el compilador utilizará para tomar decisiones potencialmente mejores sobre optimizaciones como la expansión en línea, optimizaciones de bucles y ramas predeterminadas. Esta opción se considera una optimización avanzada ya que requiere cambios en el sistema de compilación, consulte a continuación.

  • Optimización en tiempo de enlace (LTO): -flto. Habilita optimizaciones en tiempo de enlace, lo que permite al compilador optimizar archivos fuente individuales en conjunto. Esto permite que las funciones se expandan en línea en archivos fuente entre otras optimizaciones del compilador. Esta opción también se considera una optimización avanzada y potencialmente requiere cambios en el sistema de compilación. Esta opción aumenta el tiempo total de compilación, lo que puede ser drástico para aplicaciones grandes. Es posible utilizar LTO solo en archivos fuente críticos para el rendimiento para posiblemente reducir los tiempos de compilación.

Estudio de caso de codificación de video VP9 con gcc -mcpu

VP9 es un formato de codificación de video desarrollado por Google. libvpx es la implementación de software de referencia de código abierto para los códecs de video VP8 y VP9 de Google y la Alianza para los Medios Abiertos (AOMedia). libvpx proporciona una mejora significativa en la compresión de video en comparación con x264 a expensas de un mayor tiempo de computación. Se puede encontrar información adicional sobre VP9 y libvpx en Wikipedia.

En este estudio de caso, se configura la construcción de VP9 para usar la opción gcc -mcpu=native para mejorar el rendimiento. Como se mencionó anteriormente, se utiliza la opción -mcpu al compilar en procesadores Ampere para habilitar la optimización y ajuste específicos de la CPU. Inicialmente, se construyó libvpx utilizando la configuración predeterminada y luego se reconstruyó usando -mcpu=native. Para evaluar el rendimiento de VP9, se utilizó un archivo de video de entrada 1080P, original_videos_Sports_1080P_Sports_1080P-0063.mkv del conjunto de datos de contenido generado por el usuario de YouTube. Consulte la guía de afinación de ffmpeg de Ampere y la guía de construcción para obtener más detalles sobre cómo compilar ffmpeg y varios códecs, incluido VP9, para procesadores Ampere.

Construcción predeterminada de libvpx:

$ git clone https://chromium.googlesource.com/webm/libvpx$ cd libvpx/$ export CFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wimplicit-function-declaration -Wmissing-declarations -Wmissing-prototypes -Wuninitialized -Wunused -Wextra -Wundef -Wframe-larger-than=52000 -std=gnu89"$ export CXXFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdisabled-optimization -Wextra-semi -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wno-psabi -Wc++14-extensions -Wc++17-extensions -Wc++20-extensions -std=gnu++11 -std=gnu++11"$ ./configure$ make verbose=1 $ ./vpxenc --codec=vp9 --profile=0 --height=1080 --width=1920 --fps=25/1 --limit=100 -o output.mkv /home/joneill/Videos/original_videos_Sports_1080P_Sports_1080P-0063.mkv --target-bitrate=2073600 --good --passes=1 --threads=1 –debug

Cómo optimizar la construcción de libvpx con -mcpu=native

$ # reconstruir con -mcpu=native$ make clean$ export CFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wimplicit-function-declaration -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wundef -Wframe-larger-than=52000 -std=gnu89"$ export CXXFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdisabled-optimization -Wextra-semi -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wno-psabi -Wc++14-extensions -Wc++17-extensions -Wc++20-extensions -std=gnu++11 -std=gnu++11"$ ./configure $ make verbose=1 # verificar que la construcción use la instrucción de producto de punto sdot:$ objdump -d vpxenc | grep sdot | wc -l128$ ./vpxenc --codec=vp9 --profile=0 --height=1080 --width=1920 --fps=25/1 --limit=100 -o output.mkv /home/joneill/Videos/original_videos_Sports_1080P_Sports_1080P-0063.mkv --target-bitrate=2073600 --good --passes=1 --threads=1 --debug

Una investigación utilizando Linux perf para medir el número de ciclos de CPU en las funciones que tomaron más tiempo incluye las funciones vpx_convolve8_horiz_neon y vpx_convolve8_vert_neon. El repositorio git libvpx muestra que estas funciones fueron optimizadas por Arm para utilizar la instrucción Armv8.6-A USDOT (producto escalar de signo mixto), la cual es compatible con procesadores Ampere.

Los ciclos de CPU gastados en vpx_convolve8_horiz_neon se redujeron de 6.07E+11 a 2.52E+11 utilizando gcc -mcpu=native para habilitar la optimización del producto escalar en un procesador Ampere Altra, reduciendo los ciclos de CPU en un factor de 2.4x.

Para vpx_convolve8_vert_neon, los ciclos de CPU se redujeron de 2.46E+11 a 2.07E+11, lo que representa una reducción del 16%.

En general, al utilizar -mcpu=native para habilitar la instrucción de producto escalar, se aceleró la transcodificación del archivo original_videos_Sports_1080P_Sports_1080P-0063.mkv en un 7% en un procesador Ampere Altra mediante la mejora del rendimiento de la aplicación. La siguiente tabla muestra los datos recopilados utilizando las utilidades perf record y perf report para medir los ciclos de CPU e instrucciones retiradas.

Config. de Compilación Símbolo Ciclos(%) Ciclos Instrucciones(%) Instrucciones
Compilación por Defecto vpx_convolve8_horiz_neon 8.72 6.07E+11 7.52 1.13E+12
vpx_convolve8_vert_neon 3.53 2.46+E11 2.51 3.78E+11
Aplicación Completa 100 6.97E+10 100 1.48E+11
-mcpu=native vpx_convolve8_horiz_neon 3.89 2.52E+11 3.87 5.71E+11
vpx_convolve8_vert_neon 3.19 2.07+E11 3.29 4.86E+11
Aplicación Completa 100 6.48E+10 100 1.48E+11

Optimización Guiada por Perfil de GCC

Esta sección proporciona una descripción general de la Optimización Guiada por Perfil (PGO) de GCC y un caso de estudio de la optimización de MySQL con PGO. Las Optimizaciones de Guía de Perfil permiten a GCC tomar mejores decisiones de optimización, incluyendo la optimización de ramificaciones, la reordenación de bloques de código, la inlinización de funciones y las optimizaciones de bucles mediante el desenrollado de bucles, el despegado de bucles y la vectorización. El uso de PGO requiere modificar el entorno de compilación para realizar una compilación de 3 partes.

  1. Compilar la aplicación con Optimización Guiada por Perfil, gcc -fprofile-generate.
  2. Ejecutar la aplicación en cargas de trabajo representativas para generar los datos de perfil.
  3. Compilar de nuevo la aplicación utilizando los datos de perfil, gcc -fprofile-use.

Un desafío de utilizar PGO es la sobrecarga de rendimiento extremadamente alta en el paso 2 mencionado anteriormente. Debido al bajo rendimiento al ejecutar una aplicación compilada con gcc -fprofile-generate, puede que no sea práctico ejecutarla en sistemas que operan en un entorno de producción. Consulta la sección de Opciones de Instrumentación del Programa del manual de GCC para compilar aplicaciones con instrumentación en tiempo de ejecución y la sección Opciones que Controlan la Optimización para obtener más detalles sobre cómo compilar de nuevo utilizando la información de perfil generada.

Como se describe en el manual de GCC, -fprofile-update=atomic se recomienda para aplicaciones de múltiples hilos, y puede mejorar el rendimiento al recopilar datos de perfil mejorados.

¿Cuándo usar PGO?

Con PGO, GCC puede optimizar mejor las aplicaciones proporcionando información adicional, como medir las ramas tomadas vs. no tomadas y medir los recuentos de viajes de bucle. PGO es una optimización útil para probar y ver si mejora el rendimiento. Firmas de rendimiento donde PGO puede ser útil incluyen aplicaciones con un porcentaje significativo de predicciones de ramas incorrectas, que se pueden medir utilizando la utilidad perf para leer el contador de Unidad de Monitoreo de Rendimiento (PMU) de la CPU BR_MIS_PRED_RETIRED. Un gran número de predicciones de ramas incorrectas conduce a un alto porcentaje de paradas en el frente de ejecución, que se pueden medir mediante el contador PMU STALL_FRONTEND. Las aplicaciones con una alta tasa de fallos de caché de instrucciones L2 también pueden beneficiarse de PGO, posiblemente relacionado con ramas mal predichas. En resumen, un gran porcentaje de predicciones de ramas incorrectas, paradas en el frente de ejecución de la CPU y fallos de caché de instrucciones L2 son firmas de rendimiento donde PGO puede mejorar el rendimiento.

Estudio de caso de MySQL database GCC PGO

MySQL es la base de datos de código abierto más popular del mundo y, debido al enorme tamaño del binario de MySQL, es un candidato ideal para utilizar la optimización de GCC PGO. Sin información de PGO, es imposible que GCC prediga correctamente las diferentes rutas de código ejecutadas. El uso de PGO reduce en gran medida la predicción incorrecta de ramas, la tasa de fallos de caché de instrucciones L2 y las paradas en el frente de ejecución de la CPU en el procesador Ampere Altra Max.

Resumiendo cómo se optimiza MySQL utilizando GCC PGO:

  1. Se utilizó sysbench para evaluar el rendimiento de MySQL
  2. Se entrenó GCC PGO utilizando el conjunto de pruebas de MySQL MTR (mysql-test-run) mysql-test-run
  3. Se utilizaron las pruebas oltp_point_select y oltp_read_only de Sysbench para medir el rendimiento con la compilación de PGO en comparación con la compilación predeterminada
  4. Luego se varió el número de hilos utilizados de 1 a 1024, obteniendo una mejora promedio del 29% para la prueba oltp_point_select y del 20% para la prueba oltp_read_only en un procesador Ampere Altra Max M128-30
  5. Con 64 hilos, PGO mejoró el rendimiento en un 32% al mejorar el rendimiento de MySQL

Se pueden encontrar detalles adicionales en el sitio web de Ampere Developer en la Guía de Ajuste de MySQL.

Resumen

Optimizar aplicaciones requiere experimentar con diferentes estrategias para determinar cuál funciona mejor. Este documento proporciona recomendaciones para diferentes optimizaciones del compilador GCC para generar aplicaciones de alto rendimiento que se ejecuten en procesadores Ampere. Se destaca el uso de la opción -mcpu como la forma más sencilla de generar código que aproveche todas las características compatibles con los procesadores nativos en la nube de Ampere. Se muestran dos casos de estudio, para la base de datos MySQL y el codificador de video VP9, que demuestran el uso de opciones de GCC para optimizar estas aplicaciones donde el rendimiento es crítico.

Diseñados para la computación en la nube sostenible, los primeros procesadores nativos en la nube de Ampere ofrecen un rendimiento alto predecible, una escalabilidad de plataforma y una eficiencia energética sin precedentes en la industria. Te invitamos a obtener más información sobre nuestros esfuerzos para desarrolladores y encontrar las mejores prácticas en developer.amperecomputing.com y unirte a la conversación en community.amperecomputing.com.

Comparte este artículo


Leave a Reply

Your email address will not be published. Required fields are marked *