Является ли шаблон метапрограммированием быстрее, чем эквивалентный код C?

Является ли метапрограммирование шаблона быстрее, чем эквивалентный код C? (Я говорю о производительности во время выполнения):)

Ответ 1

Во-первых, отказ от ответственности: То, о чем я думаю, вы спрашиваете, это не просто метапрограммирование шаблона, но и общее программирование. Эти два понятия тесно связаны, и нет точного определения того, что каждый из них охватывает. Но, короче говоря, метапрограммирование шаблонов, по существу, записывает программу с использованием шаблонов, которая оценивается во время компиляции. (что делает его полностью бесплатным во время выполнения. Ничего не происходит. Значение (или, чаще всего, тип) уже было вычислено компилятором и доступно как константа (либо константная переменная, либо перечисление), либо как typedef вложенные в класс (если вы использовали его для "вычисления" типа).

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

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

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

В любом случае...


Зависит от того, как вы определяете "эквивалентный код C" .

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

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

Код С++ 'unsigned long fib11 = fibonacci<11uL>::value', опирается на метапрограмму шаблона, определенную в этой ссылке, и эффективен как код C 'unsigned long fib11 = 89uL'. Шаблоны оцениваются во время компиляции, давая константу, которая может быть назначена переменной. Таким образом, во время выполнения код фактически идентичен простому назначению.

Итак, если это "эквивалентный код C" , производительность одинакова. Если эквивалентный C-код - это "программа, которая может вычислять произвольные числа фибоначчи, применяемые для поиска 11-го числа в последовательности", то версия C будет намного медленнее, поскольку она должна быть реализована как функция, которая вычисляет значение во время выполнения. Но это "эквивалентный C-код" в том смысле, что он представляет собой программу на C, которая обладает такой же гибкостью (это не просто фиксированная константа, а фактическая функция, которая может возвращать любое число в последовательности фибоначчи).

Конечно, это не всегда полезно. Но это в значительной степени канонический пример метапрограммирования шаблонов.

Более реалистичный пример универсального программирования сортирует.

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

Конечно, альтернативой является ручная сортировка, предназначенная для вашего конкретного типа данных.

В С++ эквивалентным является шаблон функции std::sort. Он также принимает компаратор, но вместо этого он является указателем на функцию, это объект функции, выглядящий следующим образом:

struct MyComp {
  bool operator()(const MyType& lhs, const MyType& rhs) {
     // return true if lhs < rhs, however this operation is defined for MyType objects
  }
};

и это может быть включено. Функция std::sort передается аргумент шаблона, поэтому он знает точный тип компаратора и поэтому знает, что функция компаратора является не только неизвестным указателем функции, но MyComp::operator().

Конечным результатом является то, что функция С++ std::sort точно такая же эффективная, как ваша ручная реализация в C того же алгоритма сортировки.

Итак, если это "эквивалентный код C" , то производительность одинакова. Но если "эквивалентный C-код" представляет собой "обобщенную функцию сортировки, которая может быть применена к любому типу и допускает определяемые пользователем компараторы", то общая программная версия на С++ значительно эффективнее.

Это действительно трюк. Общее программирование и метапрограммирование шаблонов не являются "быстрее, чем C". Это методы для получения общего кода многократного использования, который работает так же быстро, как и ручной код, и жестко закодированный C

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

Ответ 2

Metaprogramming (TMP) запускается во время компиляции, поэтому он не сравнивает яблоки с яблоками при сравнении с обычным кодом C/С++.

Но, если у вас есть что-то оцененное TMP, тогда вообще нет времени исполнения.

Ответ 3

Если вы имеете в виду код повторного использования, то да, без сомнения. Метапрограммирование - превосходный способ создания библиотек, а не кода клиента. Клиентский код не является общим, он написан для выполнения конкретных действий.

Например, посмотрите на qsort из стандартной библиотеки C и стандартный С++. Вот как работает qsort:

int compare(const void* a, const void* b)
{
    return (*(int*)a > *(int*)b);
}

int main()
{
    int data[5] = {5, 4, 3, 2, 1};

    qsort(data, 5, sizeof(int), compare);
}

Теперь просмотрите сортировку:

struct compare
{
    bool operator()(int a, int b)
    { return a < b; }
};

int main()
{
    int data[5] = {5, 4, 3, 2, 1};
    std::sort(data, data+5, compare());
}

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


Другое место, где я нахожу метапрограммирование очень красивым, - это когда вы пишете библиотеку, например boost:: spirit или boost:: xpressive, с духом вы можете написать EBNF внутри С++ и позволить компиляции проверить синтаксис EBNF для вас и с помощью xpressive you может писать регулярное выражение и позволить компилятору проверить синтаксис регулярных выражений и для вас!


Я не уверен, что вопросник означает, что TMP вычисляет значения во время компиляции. Это пример, который я написал с помощью boost:)

unsigned long greatestCommonDivisor = boost::math::static_gcd<25657, 54887524>::value;

Что бы вы ни делали с C, вы не можете имитировать приведенный выше код, в основном вы должны вручную вычислить его, а затем назначить результат greatCommonDivisor!

Ответ 4

Ответ зависит от этого.

Метапрограммирование шаблонов может использоваться для легкого написания рекурсивных парсеров языка спуска, и они могут быть неэффективными по сравнению с тщательно продуманной программой на C или реализацией на основе таблиц (например, flex/bison/yacc).

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

Основное преимущество заключается в том, что метапрограммы позволяют программисту делать больше с меньшим количеством кода.

Недостатком является то, что он также дает вам оружие для стрельбы, чтобы стрелять в ногу.

Ответ 5

Метапрограммирование шаблона можно рассматривать как выполнение времени компиляции.

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

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

Ответ 6

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

Я запутался в С++ MetaProgramming из-за этого опыта.

Я твердо убежден, что лучший код наиболее легко читается средним разработчиком. Это читаемость программного обеспечения, которая является приоритетом №1. Я могу заставить все работать с использованием любого языка... но умение заключается в том, чтобы сделать его читаемым и легко выполнимым для следующего человека в проекте. С++ MetaProgramming не проходит.

Ответ 7

Я не думаю, что есть реклама, но ясный и простой ответ о шаблонах дается с помощью С++ FAQ: https://isocpp.org/wiki/faq/templates#overview-templates

О исходном вопросе: на него нельзя ответить, поскольку эти вещи не сопоставимы.

Ответ 8

Метапрограммирование шаблонов не дает вам никаких магических способностей с точки зрения производительности. Это в основном очень сложный препроцессор; вы всегда можете записать эквивалент в C или С++, это может занять очень много времени.