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

Я нашел "Искусство Пролога" очень хорошим чтением.

11
задан jalf 25 July 2009 в 20:13
поделиться

8 ответов

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

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

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

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

Итак, если это «эквивалентный код C», производительность такая же. беззнаковое длинное fib11 = 89uL '. Шаблоны оцениваются во время компиляции, давая константу, которую можно присвоить переменной. Таким образом, во время выполнения код фактически идентичен простому назначению.

Итак, если это «эквивалентный код C», производительность такая же. беззнаковое длинное fib11 = 89uL '. Шаблоны оцениваются во время компиляции, давая константу, которую можно присвоить переменной. Таким образом, во время выполнения код фактически идентичен простому назначению.

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

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

Более реалистичным примером общего программирования является сортировка.

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

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

В C ++ эквивалентом является шаблон функции 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 () .

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

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

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

27
ответ дан 3 December 2019 в 01:09
поделиться

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

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

11
ответ дан 3 December 2019 в 01:09
поделиться

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

Например, посмотрите qsort из стандартной библиотеки C и стандартную сортировку 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);
}

Теперь взгляните на sort :

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, с spirit вы можете написать EBNF внутри C ++ и позволить компилятору проверять синтаксис EBNF для вас, а с xpressive вы можете написать регулярное выражение и позволить компилятору проверить синтаксис регулярного выражения для вас также !


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

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

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

4
ответ дан 3 December 2019 в 01:09
поделиться

Ответ в том, что зависит.

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

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

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

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

1
ответ дан 3 December 2019 в 01:09
поделиться

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

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

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

1
ответ дан 3 December 2019 в 01:09
поделиться

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

Я пресыщен C ++ МетаПрограммирование благодаря этому опыту.

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

1
ответ дан 3 December 2019 в 01:09
поделиться

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

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

0
ответ дан 3 December 2019 в 01:09
поделиться

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

0
ответ дан 3 December 2019 в 01:09
поделиться
Другие вопросы по тегам:

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