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

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

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

Ответы [ 11 ]

48 голосов
/ 03 августа 2010

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

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

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

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

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

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

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

ОБНОВЛЕНИЕ: Есть также хороший поток с общими методами для ускорениякомпиляция здесь на SO, которая может быть полезна:

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

17 голосов
/ 03 августа 2010

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

  • сборка на локальном диске вместо сетевой файловой системы, такой как NFS
  • обновление до новой версии gcc
  • исследование distcc
  • систем с более быстрой сборкой, особенно больше оперативной памяти
9 голосов
/ 03 августа 2010

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

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

3 голосов
/ 03 августа 2010

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

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

3 голосов
/ 03 августа 2010

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

// 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 теперь fast , и вы только (предварительно) компилируете определение ClsWithNoTemplates 'один раз.

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

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

2 голосов
/ 03 августа 2010

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

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

1 голос
/ 04 августа 2010

В этой статье описан метод компиляции шаблонного кода, очень похожий на «традиционные» не шаблонные объектные файлы.Экономит время компиляции и компоновки, используя только одну строку кода для каждого экземпляра шаблона.

1 голос
/ 03 августа 2010

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

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

0 голосов
/ 03 августа 2010

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

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

...