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;
}
コンパイル時間:
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 (ウィキペディアで見つけることができます) であり、foo は約 1 から 100 の間の実数値を返す役に立たない関数であり、fib ランタイムの複雑さがあります。
91 の遅い計算と ackermann 関数の両方が、コンパイラとコンパイルされたプログラムによって同じ引数で評価されます。
驚くべきことに、コード自体を実行するよりも、コードを生成してコンパイラを介して実行するだけで、プログラムはさらに高速に実行されます。