Mejoras de C ++ Inliner: el Zipliner

Las versiones 16.3 y 16.4 de Visual Studio 2019 incluyen mejoras en el inliner C ++. Entre ellas está la capacidad de incorporar algunas rutinas después de que se hayan optimizado, lo que se conoce como "Zipliner". Dependiendo de su aplicación, puede ver algunas mejoras menores en la calidad del código y / o mejoras importantes en el tiempo de compilación (rendimiento del compilador).


C2 interior


Terry Mahaffey ha proporcionado una visión general de las decisiones de Visual Studio . Esto detalla algunas de las restricciones y áreas de mejora del inliner, algunas de las cuales son particularmente relevantes aquí:

  1. El inliner es recursivo y a menudo puede volver a hacer el trabajo que ya ha hecho. Las decisiones en línea son sensibles al contexto y no siempre es rentable reproducir su toma de decisiones para la misma función.
  2. El interior es muy consciente del presupuesto. Tiene el difícil trabajo de equilibrar el tamaño ejecutable con el rendimiento en tiempo de ejecución.
  3. La visión del mundo del inliner siempre está "optimizada previamente". Tiene un conocimiento muy limitado de propagación de copias y rutas de control muerto, por ejemplo.

C ++ moderno


Desafortunadamente, muchos de los patrones de codificación y modismos comunes a la programación genérica pesada se topan con esas restricciones. Considere la siguiente rutina en la biblioteca Eigen :

Eigen::Matrix<float,-1,1,0,-1,1>::outerStride(void) 

que llama innerSize:

 template<typename Derived> class DenseBase ... Index innerSize() const {    return IsVectorAtCompileTime ? this->size()        : int(IsRowMajor) ? this->cols() : this->rows(); } 

Esa instanciación de outsideStride no hace más que devolver a uno de sus miembros. Por lo tanto, es un excelente candidato para la expansión en línea completa. Sin embargo, para obtener esta ganancia, el compilador debe evaluar y expandir completamente los 18 callejeros totales de externalStride, para cada sitio de llamadas de externalStride en el módulo. Esto afecta tanto el rendimiento del optimizador como el presupuesto del tamaño del código del inliner. También vale la pena mencionar que las llamadas a 'filas' y 'cols' también se expanden en línea, a pesar de que están en un camino estáticamente muerto.
Sería mucho mejor si el optimizador simplemente incluyera el retorno del miembro de dos líneas:

 ?outerStride@?$Matrix@N$0?0$0?0$0A@$0?0$0?0@Eigen@@QEBA_JXZ PROC ; Eigen::Matrix<double,-1,-1,0,-1,-1>::outerStride, COMDAT mov    rax, QWORD PTR [rcx+8]    ret 0 

IR optimizado en línea


Para un subconjunto de rutinas, el inliner ahora expandirá el IR ya optimizado de una rutina, evitando el proceso de obtención de IR y re-expandiendo los callee. Esto tiene el doble propósito de expandir los sitios de llamadas mucho más rápido, así como permitir que el inliner mida su presupuesto con mayor precisión.

Primero, el optimizador resumirá que externalStride es un candidato para esta expansión más rápida cuando se compila originalmente (recuerde que c2.dll intenta compilar rutinas antes que las personas que llaman). Luego, el inliner puede reemplazar las llamadas a esa instancia de exteriorStride con el acceso de campo.

Los candidatos para esta expansión en línea más rápida son funciones de hoja sin locales, que se refieren a lo más a dos argumentos, globales o constantes diferentes. En la práctica, esto se dirige a los captadores y establecedores más simples.

Beneficios


Hay muchos ejemplos como outsideStride en la biblioteca Eigen donde un gran árbol de llamadas se expande en solo una o dos instrucciones. Los módulos que hacen un uso intensivo de Eigen pueden ver una mejora significativa en el rendimiento; Medimos que el optimizador tomaba hasta un 25-50% menos de tiempo para tales repros.

El nuevo Zipliner también permitirá al inliner medir su presupuesto con mayor precisión. Los desarrolladores de Eigen saben desde hace tiempo que MSVC no se ajusta a sus especificaciones (ver EIGEN_STRONG_INLINE). Zipliner debería ayudar a aliviar algo de esta preocupación, ya que una rutina con tirolina ahora se considera una línea virtualmente "libre".

Prueba la función


Esto está habilitado de forma predeterminada en Visual Studio 2019 16.3, junto con algunas mejoras en 16.4. Descargue Visual Studio 2019 y pruebe las nuevas mejoras. 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 nos puede encontrar en Twitter ( @VisualC ).

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


All Articles