for(int i = 0; i < my_function(MY_CONSTANT); ++i){
//code using i
}
この例ではmy_function(MY_CONSTANT)
、各反復で評価されますか、それとも自動的に保存されますか? これは、使用する最適化フラグに依存しますか?
for(int i = 0; i < my_function(MY_CONSTANT); ++i){
//code using i
}
この例ではmy_function(MY_CONSTANT)
、各反復で評価されますか、それとも自動的に保存されますか? これは、使用する最適化フラグに依存しますか?
関数が毎回呼び出されるかのように機能する必要があります。
ただし、関数の結果が毎回同じであることをコンパイラが証明できる場合、コンパイラは「仮定」ルールの下で最適化できます。
たとえば、これは通常.end()
、標準コンテナの呼び出しで発生します。
一般的なアドバイス: コードをマイクロ最適化するかどうか迷っているときは、
つまり、想像上のパフォーマンスではなく、コードがどれほど明確であるかに基づいて、変数を使用するかどうかを決定します。
繰り返しごとに評価されます。次のようなことを行うことで、余分な計算時間を節約できます
const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
//code using i
}
ここでコメントでas-if rule
概説した場合、最新の最適化コンパイラは関数呼び出しを最適化できる場合があります。は、適合するコンパイラは観察可能な動作をエミュレートするだけであると述べています。これは、ドラフト C++ 標準セクションのプログラムの実行に移動することで確認できます。as-if rule
1.9
[...]むしろ、以下で説明するように、抽象マシンの観察可能な動作をエミュレート (のみ) するために、適合する実装が必要です.5
したがって、定数式を使用my_function
していて、目に見える副作用がない場合は、最適化することができます。簡単なテストをまとめることができます ( godbolt でのライブを参照してください)。
#include <stdio.h>
#define blah 10
int func( int x )
{
return x + 20 ;
}
void withConstant( int y )
{
for(int i = 0; i < func(blah); i++)
{
printf("%d ", i ) ;
}
}
void withoutConstant(int y)
{
for(int i = 0; i < func(i+y); i++)
{
printf("%d ", i ) ;
}
}
の場合withConstant
、計算が最適化されていることがわかります。
cmpl $30, %ebx #, i
その場合でもwithoutConstant
、関数呼び出しを実行する代わりに計算をインライン化します。
leal 0(%rbp,%rbx), %eax #, D.2605
がconstexprmy_function
と宣言され、引数が実際には定数である場合、値はコンパイル時に計算され、それによって「as-if」および「データ競合のない順次一貫性」ルールが満たされます。
constexpr my_function(const int c);
関数に副作用があるfor-loop
場合、コンパイラーがその方法を推論できない限り、「as-if」ルールを満たさないため、コンパイラーはそれを外に移動できなくなります。
コンパイラーは inline my_function
、ループの一部であるかのようにそれを削減し、定数の削減により、実際には単なる定数であることがわかり、事実上、呼び出しを削除して定数に置き換えます。
int my_function(const int c) {
return 17+c; // inline and constant reduced to the value.
}
あなたの質問への答えは...多分です!