c++ - test - Plantilla de perfil metaprograma tiempo de compilación
test de metaprogramas (4)
El clásico libro C ++ Template Metaprogramming: Conceptos, herramientas y técnicas de Boost and Beyond viene con un apéndice de 20 páginas sobre la creación de perfiles de costos de tiempo de compilación. Tiene un CD complementario con el código que genera los gráficos en ese apéndice.
Otro documento es http://aszt.inf.elte.hu/~gsd/s/cikkek/profiling/profile.pdf , tal vez sea de utilidad para usted.
Otra forma más, pero más laboriosa, es contar el número de instancias de cada clase a partir de la salida de su compilador.
Estoy trabajando en un proyecto de C ++ con cálculos extensos en tiempo de compilación. El largo tiempo de compilación nos está ralentizando. ¿Cómo puedo descubrir las partes más lentas de nuestros meta-programas de plantillas para poder optimizarlos? (Cuando tenemos cálculos de tiempo de ejecución lentos, tengo muchos perfiladores para elegir, por ejemplo, la herramienta callgrind de callgrind
. Así que intenté crear un GCC de depuración y perfilarlo compilando nuestro código, pero no aprendí mucho de eso).
Yo uso GCC y Clang, pero cualquier sugerencia es bienvenida.
Encontré profile_templates
en el sitio de Boost, pero parece estar muy poco documentado y requiere el sistema de compilación de jam / bjam. Si muestra cómo usarlo en un proyecto que no sea un atasco 1 , le votaré. https://svn.boost.org/svn/boost/sandbox/tools/profile_templates/ parece contar el número de instancias, mientras que contar el tiempo tomado sería ideal.
1 Nuestro proyecto utiliza CMake y es lo suficientemente pequeño como para que el pirateo de un archivo Jam solo para el perfilado de plantillas pueda ser aceptable.
He estado trabajando desde 2008 en una biblioteca que utiliza una metaprogramación de plantillas en gran medida. Existe una necesidad real de mejores herramientas o enfoques para comprender qué consume el mayor tiempo de compilación.
La única técnica que conozco es un enfoque de dividir y conquistar, ya sea separando el código en diferentes archivos, comentando cuerpos de definiciones de plantillas, o envolviendo las instancias de su plantilla en #define macros y redefiniendo temporalmente esas macros para que no hagan nada. Luego puede volver a compilar el proyecto con y sin varias instancias y reducirlo.
Incidentalmente, simplemente separando el mismo código en más archivos pequeños puede hacer que se compile más rápido. No estoy hablando solo de oportunidades para la compilación paralela, incluso en serie, observé que aún es más rápido. He observado este efecto en gcc tanto al compilar mi biblioteca como al compilar analizadores de Boost Spirit. Mi teoría es que parte de la resolución de símbolos, resolución de sobrecarga, SFINAE o código de inferencia de tipo en gcc tiene una complejidad O (n log n) o incluso O (n ^ 2) con respecto al número de definiciones de tipo o símbolos en juego En la unidad de ejecución.
En última instancia, lo que debe hacer es examinar cuidadosamente sus plantillas y separar lo que realmente depende de la información de tipo de lo que no lo hace, y usar el borrado de tipo y las funciones virtuales siempre que sea posible en la parte del código que no requiere los tipos de plantilla. Necesitas sacar cosas de los encabezados y en archivos cpp si esa parte del código se puede mover. En un mundo perfecto, el compilador debería poder resolver esto por sí mismo; no debería tener que mover manualmente este código para cuidar a los niños, pero este es el estado de la técnica con los compiladores que tenemos hoy.
Sé que esta es una pregunta antigua, pero hay una respuesta más reciente que me gustaría dar.
Hay un conjunto de proyectos basados en el argot que se dirigen a este problema en particular. El primer componente es una instrumentación en el compilador Clang que produce un seguimiento completo de todas las instancias de la plantilla que se produjeron durante la compilación, con valores de temporización y, opcionalmente, cuentas de uso de memoria. Esa herramienta se llama Templight, como se puede acceder aquí (actualmente se necesita compilar contra un árbol de origen de parche):
https://github.com/mikael-s-persson/templight
Un segundo componente es una herramienta de conversión que le permite convertir las trazas de templight a otros formatos, como el formato basado en texto fácilmente analizable (yaml, xml, texto, etc.) y en formatos que se pueden visualizar más fácilmente, como graphviz / graphML y, lo que es más importante, un resultado de callgrind que se puede cargar en KCacheGrind para visualizar e inspeccionar el meta-call-graph de las instancias de plantilla y sus costos de tiempo de compilación, como esta captura de pantalla de un perfil de instanciación de plantilla de una pieza de código que crea un boost::container::vector
y lo ordena con std::sort
:
Échale un vistazo aquí:
https://github.com/mikael-s-persson/templight-tools
Finalmente, también hay otro proyecto relacionado que crea una shell interactiva y un depurador para poder subir y bajar interactivamente el gráfico de creación de instancias de la plantilla:
http://www.cs.uoregon.edu/research/tau/about.php puede ser algo que puede ser de su interés en cuanto a las entidades con plantilla, muestra el desglose del tiempo dedicado a cada instanciación. Otros datos incluyen cuántas veces se llamó a cada función, cuántas funciones con perfil invocó cada función y cuál fue el tiempo medio inclusivo por llamada.