省略記号で表されたコードは、ほぼ確実に、実際のパフォーマンスの違いを単なるノイズに追いやります。ただし、すべての仮定が正しいわけではありません。
すべての反復では、max をプロセッサのレジスタにロードしてから、i と max を比較する必要があります。
たぶん、しかしおそらくそうではありません。これはコードによって異なりますが、適切な最適化コンパイラであれば、カウンターが反復間で変化しているかどうかを検出できます。
どこからアイデアを得たのかわかりませんが、それらは少し見当違いであり、最適化コンパイラがどのように機能するかを考慮していません。あなたの分解を見て、本当の違いがあなた自身であることを見てください. なんてこった、やります(とにかく楽しいです):
プログラムは次のとおりです。
int main(int argc, char *argv[]){
int max = 10;
for (int i = max-1; i >= 0; i--)
{
cout << i;
}
return 0;
}
生成されたアセンブリ (VS2010 リリース、私自身のコメント) は次のとおりです。
int main(int argc, char *argv[]){
00341000 push esi
int max = 10;
for (int i = max-1; i >= 0; i--)
00341001 mov esi,9 ; move a static 9 into esi
00341006 jmp main+10h (341010h)
00341008 lea esp,[esp] ; load the address of whatever
0034100F nop ; esp points to in memory
{ ; (not a memory fetch, just address calculation)
cout << i;
00341010 mov ecx,dword ptr [__imp_std::cout (342048h)]
00341016 push esi
00341017 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (342044h)]
0034101D dec esi ; decrement counter
0034101E jns main+10h (341010h) ; jump if not signed
}
そして、より慣用的なバージョンについては...
int main(int argc, char *argv[]){
00AC1000 push esi
int max = 10;
for (int i = 0; i < max; i++)
00AC1001 xor esi,esi
{
cout << i;
00AC1003 mov ecx,dword ptr [__imp_std::cout (0AC2048h)]
00AC1009 push esi
00AC100A call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0AC2044h)]
00AC1010 inc esi ; increment esi
00AC1011 cmp esi,0Ah ; compare to 10 (0Ah)
00AC1014 jl main+3 (0AC1003h) ; if less, jump to top
}
そうです、最初のバージョンはjns
命令 (署名されていない場合はジャンプ) を使用するため、比較は少し単純化されています (0 と比較して)。さらにいくつかの指示が含まれていますが、比較はありません。
ただし、バージョン 2 で行われた比較も静的であることに注意してください。max
ループ全体で変化しないことがわかっているため、それに応じてそのビットを最適化できます。
ただし、これによってパフォーマンスが大幅に向上する可能性は低いことを強く繰り返します。私の Windows PC の高性能タイマーでさえ、2 つの間の良好な統計的差異を与えることができませんでしたcout
。