g++ (4.7.2) и аналогичные версии, похоже, неожиданно оценивают constexpr во время компиляции. На моих машинах на самом деле намного быстрее, чем скомпилированная программа во время выполнения.
Есть ли разумное объяснение этого поведения? Применяются ли какие-либо методы оптимизации применимо во время компиляции, которое может быть выполнено быстрее, чем фактический скомпилированный код? Если да, то какой?
Вот моя тестовая программа и наблюдаемые результаты.
#include <iostream>
constexpr int mc91(int n)
{
return (n > 100)? n-10 : mc91(mc91(n+11));
}
constexpr double foo(double n)
{
return (n>2)? (0.9999)*((unsigned int)(foo(n-1)+foo(n-2))%100):1;
}
constexpr unsigned ack( unsigned m, unsigned n )
{
return m == 0
? n + 1
: n == 0
? ack( m - 1, 1 )
: ack( m - 1, ack( m, n - 1 ) );
}
constexpr unsigned slow91(int n) {
return mc91(mc91(foo(n))%100);
}
int main(void)
{
constexpr unsigned int compiletime_ack=ack(3,14);
constexpr int compiletime_91=slow91(49);
static_assert( compiletime_ack == 131069, "Must be evaluated at compile-time" );
static_assert( compiletime_91 == 91, "Must be evaluated at compile-time" );
std::cout << compiletime_ack << std::endl;
std::cout << compiletime_91 << std::endl;
std::cout << ack(3,14) << std::endl;
std::cout << slow91(49) << std::endl;
return 0;
}
compiletime:
time g++ constexpr.cpp -std=c++11 -fconstexpr-depth=10000000 -O3
real 0m0.645s
user 0m0.600s
sys 0m0.032s
во время выполнения:
time ./a.out
131069
91
131069
91
real 0m43.708s
user 0m43.567s
sys 0m0.008s
Здесь mc91 является обычным mac carthy f91 (как можно найти в wikipedia), а foo - это просто бесполезная функция, возвращающая реальные значения от 1 до 100 с сложностью выполнения Flash.
Как медленный расчет 91, так и функции ackermann вычисляются с помощью тех же аргументов компилятором и скомпилированной программой.
Удивительно, что программа будет работать даже быстрее, просто создавая код и запуская его через компилятор, чем выполнение самого кода.