Actualizaciones de back-end de MSVC en Visual Studio 2019 Preview 2: Nuevas optimizaciones, OpenMP y mejoras de rendimiento de compilación


En Visual Studio 2019 Preview 2, hemos seguido mejorando el backend de C ++ con nuevas características, optimizaciones nuevas y mejoradas, mejoras en el rendimiento de la compilación y cambios en la calidad de vida.


Original en blog

Nuevas características


  • Se agregó un nuevo interruptor de línea de comando en línea: -Ob3. -Ob3 es una versión más agresiva de -Ob2. -O2 (optimizar el binario para la velocidad) todavía implica -Ob2 por defecto, pero esto puede cambiar en el futuro. Si encuentra que el compilador no está alineado, considere pasar -O2 -Ob3.
  • Se agregó soporte básico para la vectorización SIMD de OpenMP, que es la característica OpenMP más utilizada en las bibliotecas de aprendizaje automático (ML). Nuestro estudio de caso es la biblioteca Intel MKL-DNN, que se utiliza como un bloque de construcción para otras bibliotecas ML de código abierto conocidas, incluido Tensor Flow. Esto se puede activar con un nuevo interruptor CL -openmp: experimental. Esto permite que los bucles anotados con "#pragma omp simd" sean potencialmente vectorizados. La vectorización no está garantizada y los bucles anotados pero no vectorizados recibirán una advertencia. No se admiten cláusulas SIMD, simplemente se ignorarán con una advertencia informada.
  • Se agregó un nuevo controlador de excepciones de C ++ __CxxFrameHandler4 que reduce la sobrecarga de metadatos de manejo de excepciones en un 66%. Esto proporciona una mejora del tamaño binario total de hasta un 15% en binarios que usan grandes cantidades de manejo de excepciones de C ++. Actualmente está desactivado por defecto, pruébelo pasando "/ d2FH4" al compilar con cl.exe. Tenga en cuenta que / d2FH4 no está documentado ni es compatible a largo plazo. Actualmente, esto no es compatible con las aplicaciones para UWP ya que el tiempo de ejecución de UWP aún no tiene esta función.
  • Para admitir la vectorización manual de bucles que contienen llamadas a funciones de la biblioteca matemática y ciertas otras operaciones como la división de enteros, MSVC ahora admite funciones intrínsecas de la Biblioteca matemática de vectores cortos (SVML) que calculan los equivalentes del vector. El soporte para vectores de 128 bits, 256 bits y 512 bits está disponible para la mayoría de las funciones, con las excepciones que se enumeran a continuación. Tenga en cuenta que estas funciones no establecen errno. Consulte la Guía intrínseca de Intel para ver las definiciones de las funciones compatibles.
    Las excepciones incluyen:
    • La división y el resto de enteros combinados de vectores solo están disponibles para elementos de 32 bits y longitudes de vector de 128 y 256 bits. Utilice funciones separadas de división y resto para otros tamaños de elementos y longitudes de vectores.
    • La raíz cuadrada de SVML solo está disponible en longitudes de vector de 128 bits y 256 bits. Puede usar las funciones _mm512_sqrt_pd o _mm512_sqrt_ps para vectores de 512 bits.
    • Solo están disponibles las versiones vectoriales de 512 bits de rint y las funciones cercanas deintint . En muchos casos, puede usar funciones redondas en su lugar, por ejemplo, use _mm256_round_ps (x, _MM_FROUND_CUR_DIRECTION) como una versión vectorial de 256 bits de rint , o _mm256_round_ps (x, _MM_FROUND_TO_NEAREST_INT) para nearbyint .
    • Solo se proporciona el recíproco de 512 bits. Puede calcular el equivalente utilizando las funciones set1 y div, por ejemplo, el recíproco de 256 bits podría calcularse como _mm256_div_ps (_mm256_set1_ps (1.0f), (x)) .
    • Hay funciones SVML para raíz cuadrada compleja de precisión simple, logaritmo y exponenciación solo en longitudes de vector de 128 bits y 256 bits.

Optimizaciones nuevas y mejoradas


  • Los conjuntos de memorias desenrollados y las inicializaciones de bloque ahora usarán instrucciones SSE2 (o instrucciones AVX si están permitidas). El umbral de tamaño para lo que se desenrollará ha aumentado en consecuencia (compila el tamaño con SSE2: el umbral de desenrollado se mueve de 31 a 63 bytes, compila la velocidad con SSE2: el umbral se mueve de 79 a 159 bytes).
  • Optimizado el code-gen para pequeños conjuntos de memoria, principalmente dirigido a funciones protegidas por initall .
  • Mejoras en la eliminación de almacenamiento redundante del SSA Optimizer : mejor análisis de escape y manejo de bucles
  • El compilador reconoce memmove () como una función intrínseca y optimiza en consecuencia. Esto mejora la generación de código para operaciones construidas en memmove (), incluyendo std :: copy () y otro código de biblioteca de nivel superior como std :: vector y std :: string construction
  • El optimizador hace un mejor trabajo al optimizar las operaciones cortas, de longitud fija memmove (), memcpy () y memcmp ().
  • Se implementó la optimización de duplicación de conmutadores para un mejor rendimiento de los conmutadores dentro de los lazos activos. Duplicamos los saltos de interruptor para ayudar a mejorar la precisión de predicción de rama y, en consecuencia, el rendimiento del tiempo de ejecución.
  • Se agregaron simplificaciones de plegado constante y aritméticas para expresiones usando SIMD (vector) intrínseco, tanto para formas flotantes como enteras. La mayoría de las optimizaciones de expresiones habituales ahora manejan intrínsecos SSE2 y AVX2, ya sea desde el código de usuario o como resultado de la vectorización automática.
  • Varios nuevos patrones de suma múltiple de fusión escalar (FMA) se identifican con / arch: AVX2 / fp: fast. Estos incluyen las siguientes expresiones comunes: (x + 1.0) * y; (x – 1.0) * y; (1.0 – x) * y; (-1.0 – x) * y (x + 1.0) * y; (x – 1.0) * y; (1.0 – x) * y; (-1.0 – x) * y
  • Las secuencias de código que inicializan un valor __m128 SIMD (vector) elemento por elemento se identifican y reemplazan por un _mm_set_ps intrínseco. Esto permite que las nuevas optimizaciones SIMD consideren el valor como parte de las expresiones, especialmente si el valor solo tiene elementos constantes. Una actualización futura admitirá más tipos de valor.
  • La eliminación de subexpresión común (CSE) es más efectiva en presencia de variables que pueden modificarse de manera indirecta porque se toma su dirección.
  • Las copias de estructura / clase inútiles se eliminan en varios casos más, incluidas las copias para generar parámetros y funciones que devuelven un objeto. Esta optimización es especialmente efectiva en programas C ++ que pasan objetos por valor.
  • Se agregó un análisis más poderoso para extraer información sobre las variables del flujo de control (instrucciones if / else / switch), que se usa para eliminar ramas que siempre pueden ser verdaderas o falsas y para mejorar la estimación del rango de variables. El código que usa gsl :: span ve mejoras, algunas comprobaciones de rango que son innecesarias ahora se eliminan.
  • La optimización de la desvirtualización ahora tendrá oportunidades adicionales, como cuando las clases se definen en espacios de nombres anónimos.

Construir mejoras de rendimiento


  • Filtre la información de depuración durante la compilación basada en símbolos y tipos referenciados para reducir el tamaño de la sección de depuración y mejorar el rendimiento del enlazador. La actualización de 15.9 a 16.0 puede reducir el tamaño de entrada al enlazador hasta en un 40%.
  • Mejoras en el tiempo de enlace en la fusión y creación de tipos PDB.
  • La actualización a 16.0 desde 15.9 puede mejorar los tiempos de enlace en hasta 2 veces la velocidad. Por ejemplo, vincular Chrome resultó en una aceleración de tiempo de enlace de 1.75X al usar / DEBUG: full, y una aceleración de tiempo de enlace de 1.4X cuando se usa / DEBUG: fastlink.

Mejoras de calidad de vida


  • El compilador muestra los nombres y las rutas de los archivos utilizando la carcasa proporcionada por el usuario, donde anteriormente el compilador mostraba los nombres y las rutas de los archivos en minúsculas.
  • El nuevo vinculador ahora informará símbolos potencialmente coincidentes para símbolos no resueltos, como:

 main.obj : error LNK2019: unresolved external symbol _foo referenced in function _main Hint on symbols that are defined and could potentially match: "int __cdecl foo(int)" (?foo@@YAHH@Z) "bool __cdecl foo(double)" (?foo@@YA_NN@Z) @foo@0 foo@@4 main.exe : fatal error LNK1120: 1 unresolved externals 
  • Al generar una biblioteca estática, ya no es necesario pasar el indicador / LTCG a LIB.exe.
  • Se agregó una opción de vinculador / LINKREPROTARGET: [binary_name] para generar solo un repro de enlace para el binario especificado. Esto permite que% LINK_REPRO% o / LINKREPRO: [nombre_directorio] se establezca en una construcción grande con múltiples enlaces, y el enlazador solo generará la reproducción del binario especificado en / linkreprotarget.

Nos encantaría que descargues Visual Studio 2019 y lo pruebes. Como siempre, agradecemos sus comentarios. Nos puede contactar a través de los comentarios a continuación o por correo electrónico ( visualcpp@microsoft.com ). Si tiene problemas con Visual Studio o MSVC, o si tiene una sugerencia para nosotros, infórmenos a través de Ayuda> Enviar comentarios> Informar un problema / Proporcionar una sugerencia en el producto o a través de la Comunidad de desarrolladores . También puede encontrarnos en Twitter ( @VisualC ) y Facebook (msftvisualcpp).

Source: https://habr.com/ru/post/437670/


All Articles