Время компиляции шаблона шаблона профилирования

Я работаю над проектом С++ с обширными вычислениями времени компиляции. Длительное время компиляции замедляет нас. Как я могу узнать самые медленные части наших метапрограмм шаблонов, чтобы я мог их оптимизировать? (Когда у нас медленные вычисления во время выполнения, у меня есть много профилировщиков, например, valgrind callgrind. Поэтому я попытался создать отладочный GCC и профилировать его, компилируя наш код, но я не многому научился от этого.)

Я использую GCC и Clang, но любые предложения приветствуются.

Я нашел profile_templates на сайте Boost, но он, как представляется, тонко документирован и требует системы сборки jam/bjam. Если вы покажете, как использовать его в проекте, отличном от jam 1 я буду перенаправлять вас. https://svn.boost.org/svn/boost/sandbox/tools/profile_templates/, кажется, подсчитывает количество экземпляров, тогда как время отсчета было бы идеальным.

1 В нашем проекте используется CMake и достаточно мала, чтобы взломать Jamfile только для профилирования шаблонов может быть приемлемым.

Ответ 1

Я работаю с 2008 года в библиотеке, которая сильно использует метапрограммирование шаблонов. Существует настоятельная потребность в лучших инструментах или подходах для понимания того, что потребляет наибольшее время компиляции.

Единственный метод, о котором я знаю, - это подход с разделением и завоеванием, либо разделяя код на разные файлы, комментируя тела определений шаблонов, либо обертывая ваши экземпляры шаблонов в макросах #define и временно переопределяя эти макросы, чтобы ничего не делать. Затем вы можете перекомпилировать проект с помощью различных экземпляров и без ограничений.

Кстати, просто разделяя один и тот же код на большее, файлы меньшего размера могут ускорить его компиляцию. Я не просто говорю о возможности параллельной компиляции - даже в серийном режиме, я заметил, что она все еще быстрее. Я наблюдал этот эффект в gcc как при компиляции моей библиотеки, так и при компиляции парсеров Boost Spirit. Моя теория заключается в том, что некоторая часть разрешения символа, разрешения перегрузки, SFINAE или кода ввода типа в gcc имеет сложность O (n log n) или даже O (n ^ 2) в отношении количества определений типов или символов в игре в исполнительном устройстве.

В конечном счете, вам нужно тщательно изучить ваши шаблоны и отделить то, что действительно зависит от информации о типе от того, чего нет, и использовать стирание стилей и виртуальные функции, если это возможно, на части кода, которая фактически не требует шаблона типы. Вам нужно получить материал из заголовков и в файлы cpp , если, что часть кода может быть перемещена. В идеальном мире компилятор должен уметь это понять сам по себе - вам не нужно вручную перемещать этот код, чтобы его нянчить, но это современное состояние с компиляторами, которые у нас есть сегодня.

Ответ 2

Я знаю, что это старый вопрос, но есть более новый ответ, который я хотел бы дать.

Существует набор проектов на основе клана, предназначенных для этой конкретной проблемы. Первый компонент - это инструментарий для компилятора clang, который дает полную трассу всех экземпляров шаблонов, которые произошли во время компиляции, с указанием значений времени и, при необходимости, использования памяти. Этот инструмент называется Templight, так как он доступен здесь (в настоящее время он должен компилироваться с поврежденным деревом источника clang):

https://github.com/mikael-s-persson/templight

Второй компонент - это инструмент преобразования, который позволяет конвертировать трассировки templight в другие форматы, такие как легко анализируемый текстовый формат (yaml, xml, text и т.д.) и в форматы, которые легче визуализировать, таких как graphviz/graphML и, что более важно, вывод callgrind, который может быть загружен в KCacheGrind для визуализации и проверки мета-графика вызовов экземпляров шаблонов и их затрат времени на компиляцию, таких как этот скриншот шаблона для создания экземпляра объекта кода, который создает boost::container::vector и сортирует его с помощью std::sort:

enter image description here

Посмотрите здесь:

https://github.com/mikael-s-persson/templight-tools

Наконец, есть и другой связанный проект, который создает интерактивную оболочку и отладчик, чтобы иметь возможность интерактивно перемещаться вверх и вниз по шаблону экземпляра шаблона:

https://github.com/sabel83/metashell

Ответ 3

Классическая книга С++ Template Metaprogramming: понятия, инструменты и методы из Boost and Beyond содержит 20-страничное приложение для профилирования компиляции, время. У этого есть компаньонный компакт-диск с кодом, который генерирует графики в этом приложении.

Другой документ http://aszt.inf.elte.hu/~gsd/s/cikkek/profiling/profile.pdf, возможно, это вам полезно.

Еще один, но более трудоемкий способ - подсчитать количество экземпляров каждого класса из вашего компилятора.

Ответ 4

http://www.cs.uoregon.edu/research/tau/about.php может быть чем-то, что может вас заинтересовать, как для шаблонных объектов, это показывает распад времени, затрачиваемого на каждый экземпляр. Другие данные включают, сколько раз каждая функция была вызвана, сколько профилированных функций вызывало каждую функцию, и какое среднее время включительно для каждого вызова было