ここにいくつかの完全な例がありますが、あなたの質問に正確に答えることができない点が不完全です。
unsigned int fun (void)
{
unsigned int x[8];
unsigned int ra;
unsigned int rb;
for(ra=0;ra<5;ra++) x[ra]=ra;
rb=0; for(ra=0;ra<5;ra++) rb+=x[ra];
return(rb);
}
void more_fun (void)
{
unsigned int x[8];
unsigned int ra;
for(ra=0;ra<5;ra++) x[ra]=ra;
}
と最適化されたコンパイル済みの出力第二の機能最初
00000000 <fun>:
0: e3a0000a mov r0, #10
4: e12fff1e bx lr
00000008 <more_fun>:
8: e12fff1e bx lr
の例は、RAもXのどちらも関数の外で使用されていることを確認するために、彼らが生産されているのは何も非常に簡単ではありません本当の価値のあるものは、それは未使用の変数とデッドコードなので、それはすべて消えると、全機能がこれに最適化されています。それがあるべきよう
void more_fun (void)
{
}
。
これをさらに踏襲すると、ランダマイザや他のアルゴリズムを使用してこのようなことをさらに進めています。この場合はかなり簡単でした。
fun()関数内の回転のどれもランタイム値を持たず、すべてがデッドコードであり、結果は入力やグローバルなものに基づいて変化しません。答えを事前に計算することができます。コンパイラはコンパイル時(0 + 1 + 2 + 3 + 4 = 10)に答えを計算し、すべてのデッドコードを削除します。あなたがなど、ループを使用して時刻を燃やすか、おそらくループが実装されている方法を見たいと思っている場合は基本的に正しい答え
unsigned int fun (void)
{
return(10);
}
を考え出す、あなたは物事のカップルを試すことができます。
あなたが見ることができるように揮発性の解決策は、私はあなたが実際にあなたが使用するたびに出かけ、タッチラムしたいと言っているかなり醜いです(コンパイラは異なります)
00000000 <fun>:
0: e3a03000 mov r3, #0
4: e24dd008 sub sp, sp, #8
8: e58d3004 str r3, [sp, #4]
c: e59d3004 ldr r3, [sp, #4]
10: e58d3004 str r3, [sp, #4]
14: e59d3004 ldr r3, [sp, #4]
18: e2833001 add r3, r3, #1
1c: e58d3004 str r3, [sp, #4]
20: e59d3004 ldr r3, [sp, #4]
24: e2833002 add r3, r3, #2
28: e58d3004 str r3, [sp, #4]
2c: e59d3004 ldr r3, [sp, #4]
30: e2833003 add r3, r3, #3
34: e58d3004 str r3, [sp, #4]
38: e59d3004 ldr r3, [sp, #4]
3c: e2833004 add r3, r3, #4
40: e58d3004 str r3, [sp, #4]
44: e59d0004 ldr r0, [sp, #4]
48: e28dd008 add sp, sp, #8
4c: e12fff1e bx lr
00000050 <more_fun>:
50: e92d4010 push {r4, lr}
54: e3a04000 mov r4, #0
58: e1a00004 mov r0, r4
5c: e2844001 add r4, r4, #1
60: ebfffffe bl 0 <dummy>
64: e3540005 cmp r4, #5
68: 1afffffa bne 58 <more_fun+0x8>
6c: e8bd4010 pop {r4, lr}
70: e12fff1e bx lr
のようなものを与えることができます
void dummy (unsigned int);
unsigned int fun (void)
{
unsigned int ra;
volatile unsigned int rb;
rb=0; for(ra=0;ra<5;ra++) rb+=ra;
return(rb);
}
void more_fun (void)
{
unsigned int ra;
for(ra=0;ra<5;ra++) dummy(ra);
}
この変数は、何かをしたいときにRAMから読み込み、各ステップの後に書き戻します。 more_fun()ソリューションは、コンパイラが外部関数を呼び出すように強制した場合、コンパイラが期待しているようにvolatileを期待することには依存しません(コンパイラはローカル、これは最適化ドメインにはなく、結果としてインライン化することはできません。たとえば、dummy()が入力変数を使用しない場合は、デッドコードが表示される可能性があります。そのような小さなループであるため、コンパイラはループを実装することができます。または、アンロールすることができます。アンロールすると、それが意味をなさない場合にはループとして実装されるか、一連の呼び出しとして実装されます。
void more_fun (void)
{
dummy(0);
dummy(1);
dummy(2);
dummy(3);
dummy(4);
}
gnuのような無料のツールでは、最強のコンパイラではありませんが、最もタイトな/最速のコード(1つのサイズは、誰にも当てはまりません)まで、オブジェクトやバイナリにコンパイルしますオブジェクトとバイナリの両方を逆アセンブルするディスアセンブラを持っているので、これらのような単純な関数で遊ぶことができ、コンパイルオプションが何をしているのかを調べ、デッドコードが何であるかを理解することができます。あなたは時間以外何も費用はかかりません。
ほとんどの人は、揮発性のソリューションを手に入れようとしていますが、手作業の最適化を試みてゆっくりとビルドすると、結果が不安定になり、あなたがそれを持っていなかった場合よりも不自然な方法で、最終的には、変数の1つに揮発性の有無にかかわらずパフォーマンスが大きく変化するループ内の他の関数を呼び出す実際のコードを思いつくことができます。
同じコンパイラを使用して同じ正確なコンピュータで同じ正確なソースコードを使用しても、単語のベンチマークは、とにかく偽です。重要なのは、実際のタスクを実行する実際のプログラムで、このパフォーマンスがあります。それを別の方法で実装し、可能であればそれを測定し、いくらかのマージンを追加し、どちらがより速く、そしてそれと一緒に行くか、あるいは同じことが読んだり、維持したりする方が簡単なのかを判断します。
'for'ループとその中で呼び出される関数の内容を表示できますか? –
参考のためにサンプルコードを追加しました。 – user7439633
コードを適切に書式化して読みやすくしてください。 –