Как ускорить g ++ время компиляции (при использовании большого количества шаблонов)

Этот вопрос, возможно, так или иначе нечетен, но как я могу ускорить g ++ время компиляции? Мой код C++ в большой степени использует повышение и шаблоны. Я уже переместился как можно больше из файлов заголовков, и используйте-j опцию, но тем не менее требуется долгое время для компиляции (и ссылка).

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

63
задан Danvil 4 August 2010 в 12:04
поделиться

11 ответов

Что было для меня наиболее полезным:

  • Построить на файловой системе RAM. В Linux это тривиально. Вы также можете сохранить копию общих файлов заголовков (предварительно скомпилированных или фактических файлов .h) в файловой системе RAM.
  • Предварительно скомпилированные заголовки . У меня есть одна (основная) библиотека (например, Boost, Qt, stdlib).
  • По возможности объявляйте классы вместо включения. Это уменьшает зависимости и, следовательно, уменьшает количество файлов, которые необходимо перекомпилировать при изменении файла заголовка.
  • Распараллелить make . Обычно это помогает от случая к случаю, но у меня есть -j3 глобально для make. Тем не менее, убедитесь, что ваши графики зависимостей в вашем Makefile верны, иначе у вас могут возникнуть проблемы.
  • Используйте -O0 , если вы не тестируете скорость выполнения или размер кода (и ваш компьютер достаточно быстр, чтобы вас не волновало (возможно, небольшое) снижение производительности).
  • Компилировать каждый раз при сохранении. Некоторым это не нравится, но это позволяет вам заранее увидеть ошибки и может быть сделано в фоновом режиме, сокращая время ожидания, когда вы закончите писать и будете готовы к тестированию.
49
ответ дан 24 November 2019 в 16:23
поделиться

Компиляция с g ++ с использованием нескольких ядер

Компиляция с g ++ с использованием нескольких ядер

0
ответ дан 4 July 2019 в 19:56
поделиться

Я предполагаю, что мы говорим о минутах для компиляции файла, то есть проблемы с предварительно скомпилированными заголовками или локальным диском не являются проблемой.

Длительное время компиляции с глубоким кодом шаблона (ускорение и т. Д.) Часто коренится в недружелюбном асимптотическом поведении gcc, когда дело доходит до создания экземпляров шаблона, в частности, когда вариативные шаблоны эмулируются с аргументами шаблона по умолчанию.

Вот документ, в котором сокращение времени компиляции названо мотивом для вариативных шаблонов:

cpptruths опубликовала статью о том, как gcc-4.5 намного лучше в этом отношении и тем, как он блестяще справляется со своими вариативными шаблонами:

IIRC, то у BOOST есть способ ограничить создание параметров шаблона по умолчанию для псевдовариадиков, я думаю, что 'g ++ -DBOOST_MPL_LIMIT_LIST_SIZE = 10' должно работать (по умолчанию 20)

UPDATE: Там также хороший поток с общими методами ускорения компиляции здесь на SO, который может быть полезен:

ОБНОВЛЕНИЕ: Это касается проблем с производительностью при компиляции шаблонов принятый ответ также рекомендует использовать gcc-4.5, также в качестве положительного примера упоминается clang:

17
ответ дан 24 November 2019 в 16:23
поделиться

Помимо того, что все добавили и что вы уже делаете (параллельная сборка, параметры компилятора и т. Д.), Рассмотрите возможность скрытия шаблонов в классах реализации, доступных через интерфейсы. Это означает, что вместо такого класса, как:

// ClsWithNoTemplates.h file, included everywhere

class ClsWithTemplates
{
    ComplicatedTemplate<abc> member;
    // ...

public:
    void FunctionUsingYourMember();
};

, вы должны иметь:

// ClsWithNoTemplates.h file:

class ClsWithTemplatesImplementation; // forward declaration
  // definition included in the ClsWithNoTemplates.cpp file
  // this class will have a ComplicatedTemplate<abc> member, but it is only 
  // included in your ClsWithNoTemplates definition file (that is only included once)


class ClsWithNoTemplates
{
     ClsWithTemplatesImplementation * impl; // no templates mentioned anywhere here
public:
    void FunctionUsingYourMember(); // call impl->FunctionUsingYourMember() internally
};

Это немного изменяет ваш дизайн ООП, но это к лучшему: включение определения 'ClsWithNoTemplates' теперь быстро и вы только (предварительно) компилируете определение ClsWithNoTemplates один раз.

Кроме того, если вы измените код реализации, любой код, который включает ClsWithNoTemplates.h, вероятно, не потребуется переопределять.

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

3
ответ дан 24 November 2019 в 16:23
поделиться

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

Дополнительная идея: если ваш код компилируется с clang , используйте его. Обычно это быстрее, чем gcc.

10
ответ дан 24 November 2019 в 16:23
поделиться

Вот что я сделал для ускорения сборки в очень похожем сценарии, который вы описываете (boost, templates, gcc)

  • сборка на локальном диске вместо сетевой файловой системы, такой как NFS
  • , обновите до более новой версии gcc
  • исследуйте distcc
  • более быстрые системы сборки, особенно больше оперативной памяти
17
ответ дан 24 November 2019 в 16:23
поделиться

Если файлов много, вы можете значительно ускорить компиляцию, имея только один файл .cpp, который # включает все остальные файлы .cpp. Это, конечно, требует, чтобы вы были более осторожны с макросами и такими, которые вы уже определили для каждого файла, поскольку теперь они будут видны другим файлам cpp.

Если файлов много, это может значительно сократить время компиляции.

2
ответ дан 24 November 2019 в 16:23
поделиться

Создавайте меньше шаблонов и встроенных функций. Предварительно скомпилируйте столько, сколько сможете, и просто свяжите это, а не компилируйте все с нуля. Убедитесь, что вы используете последнюю версию GCC.

Однако очевиден тот факт, что C ++ - невероятно сложный язык, и его компиляция занимает довольно много времени.

1
ответ дан 24 November 2019 в 16:23
поделиться

В данной работе описывается метод компиляции шаблонного кода подобно "традиционным" нешаблонным объектным файлам. Экономится время компиляции и компоновки, при этом на инстанцирование шаблона приходится всего одна строка кода.

1
ответ дан 24 November 2019 в 16:23
поделиться

Обычно наиболее дорогостоящими частями компиляции являются (а) чтение исходных файлов ( ВСЕ из них) и (б) загрузка компилятора в память для каждого исходного файла.

Если у вас есть 52 файла с исходным кодом (.cc), каждый из которых # включает 47 файлов #include (.h), вы собираетесь загрузить компилятор 52 раза и обработать 2496 файлов. В зависимости от плотности комментариев в файлах вы можете потратить значительную часть времени на поедание бесполезных символов. (В одной организации, которую я видел, файлы заголовков варьировались от 66% до 90% комментариев, при этом только от 10% до 33% файла были «значимыми». Единственное, что можно было сделать для повышения удобочитаемости этих файлов, - это удаление вычеркните каждый последний комментарий, оставив только код.)

Внимательно посмотрите, как ваша программа устроена физически. Посмотрите, можете ли вы объединить исходные файлы и упростить иерархию файлов #include.

Десятилетия назад такие компании, как IBM, понимали это и писали свои компиляторы так, чтобы компилятору можно было передать список файлов для компиляции, а не только один файл, и компилятор загружался бы только один раз.

0
ответ дан 24 November 2019 в 16:23
поделиться

Попробуйте метод PIMPL, этот вопрос: Какие методы можно использовать для ускорения времени компиляции C ++?

Это предотвратит отслеживание компилятором цепочки файлов заголовков и реализации каждый раз, когда вам нужно что-то сделать.

3
ответ дан 24 November 2019 в 16:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: