Подтвердить что ты не робот

Оптимизация производительности компиляции путем кэширования метафайлов

Скажем, у меня есть следующая метафункция:

template <typename T>
struct make_pair {
    using type = std::pair<
        typename std::remove_reference<T>::type,
        typename std::remove_reference<T>::type
    >;
};

Может ли это улучшить скорость компиляции (или что-то еще)?

template <typename T>
struct make_pair {
    using without_reference = typename std::remove_reference<T>::type;
    using type = std::pair<without_reference, without_reference>;
};

Я вижу две возможности:

  • Компилятор должен выполнять некоторую работу каждый раз, когда видит typename std::remove_reference<T>::type. Использование промежуточного псевдонима имеет какое-то "кэширование" поведения, которое позволяет компилятору выполнять некоторую работу только один раз.

  • Производительность времени компиляции измеряется с точки зрения количества экземпляров шаблонов, которые должен выполнить компилятор. Поскольку std::remove_reference<T>::type относится к тому же типу, что и std::remove_reference<T>::type, в обоих случаях требуется только один экземпляр шаблона, поэтому обе реализации эквивалентны производительности времени компиляции WRT.

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

Edit

Я сравнивал компиляцию тестовой программы с некоторыми данными для работы. Программа тестирования делает что-то вроде этого:

template <typename ...> struct result;    

template <typename T>
struct with_cache {
    using without_reference = typename std::remove_reference<T>::type;
    using type = result<without_reference, ..., without_reference>;
};

template <typename T>
struct without_cache {
    using type = result<
        typename std::remove_reference<T>::type,
        ...,
        typename std::remove_reference<T>::type
    >;
{ };

using Result = with[out]_cache<int>::type;

Это среднее время для 10 компиляций программы, с 10 000 параметров шаблона в result<>.

                -------------------------
                | g++ 4.8 | clang++ 3.2 |
-----------------------------------------
| with cache    | 0.1628s | 0.3036s     |
-----------------------------------------
| without cache | 0.1573s | 0.3785s     |
-----------------------------------------

Программа тестирования генерируется script здесь.

4b9b3361

Ответ 1

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

Рассмотрим следующий код

&f<X, Y>::some_value == &f<X, Y>::some_value

Это требование должно быть истинным, поэтому компилятор должен убедиться, что он не дублирует определения методов и статических членов. Теперь могут быть другие способы сделать это, но это просто кричит мне воспоминания; Я не вижу другого способа реализовать это даже (предоставлено, я думал об этом очень сложно)

Когда я использую TMP, я ожидаю, что произойдет мемонирование. Это было бы настоящей болью, если бы это было не так, слишком медленно. Единственный способ, с помощью которого я видел существенные различия во времени выполнения компиляции, - это: а) использование более быстрого компилятора, такого как Clang (что примерно в 3 раза быстрее, чем GCC) и выбора разных алгоритмов. Небольшие постоянные факторы кажутся мне еще менее значимыми в TMP, чем у C или С++. Выбирайте правильный алгоритм, старайтесь не делать ненужной работы, старайтесь держать количество экземпляров вниз и использовать хороший компилятор (MSVС++ действительно медленный и далекий от соответствия С++ 11, но GCC и Clang неплохие); это все, что вы можете сделать на самом деле.

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