リリースモードでコンパイルされたコードの逆アセンブルを見ると、違いは非常に明白です。インラインを削除し、2つの仮想関数を使用して、コンパイラーがあまり最適化しないようにし、違いを示します。
これが最初の機能です。
013D1002 in al,dx
union {
float x;
int a;
} u;
u.x = x;
013D1003 fld dword ptr [x] // Loads a float on top of the FPU STACK.
013D1006 fstp dword ptr [x] // Pops a Float Number from the top of the FPU Stack into the destination address.
u.a &= 0x7FFFFFFF;
013D1009 and dword ptr [x],7FFFFFFFh // Execute a 32 bit binary and operation with the specified address.
return u.x;
013D1010 fld dword ptr [x] // Loads the result on top of the FPU stack.
}
これは2番目の関数です。
013D1020 push ebp // Standard function entry... i'm using a virtual function here to show the difference.
013D1021 mov ebp,esp
int b= *((int *)&a) & 0x7FFFFFFF;
013D1023 mov eax,dword ptr [a] // Load into eax our parameter.
013D1026 and eax,7FFFFFFFh // Execute 32 bit binary and between our register and our constant.
013D102B mov dword ptr [a],eax // Move the register value into our destination variable
return *((float *)(&b));
013D102E fld dword ptr [a] // Loads the result on top of the FPU stack.
最初のケースでは、浮動小数点演算の数とFPUスタックの使用量が多くなります。関数はあなたが要求したとおりに実行されているので、驚くことではありません。したがって、2番目の関数の方が高速であると期待しています。
さて...仮想とインライン化の削除は少し異なります。もちろんコンパイラは良い仕事をするので、ここで逆アセンブリコードを書くのは難しいですが、繰り返しますが、値が定数でない場合、コンパイラはより多くの浮動小数点を使用します最初の関数での操作。もちろん、整数演算は浮動小数点演算よりも高速です。
math.h abs関数を直接使用すると、メソッドよりも遅くなりますか?正しくインライン化されている場合、abs関数はこれを実行します!
00D71016 fabs
このようなマイクロ最適化は長いコードではわかりにくいですが、関数が浮動小数点演算の長いチェーンで呼び出された場合、値はすでにFPUスタックまたはSSEレジスタにあるため、ファブはより適切に機能します。absは、コンパイラーによってより高速で最適化されます。
コードの一部でループを実行する最適化のパフォーマンスを測定することはできません。コンパイラが実際のコードでどのようにすべてを混合するかを確認する必要があります。