私は科学アプリケーションで数値最適化を行っています。私が気づいたことの 1 つは、GCC は 呼び出しpow(a,2)
を にコンパイルして最適化しますa*a
が、呼び出しはpow(a,6)
最適化されておらず、実際にはライブラリ関数 を呼び出すためpow
、パフォーマンスが大幅に低下することです。(対照的に、インテル C++ コンパイラ、実行可能ファイルicc
は、 のライブラリ呼び出しを排除しますpow(a,6)
。
私が興味を持っているのは、GCC 4.5.1 とオプション " " を使用して置き換えた場合、5 つの命令が使用されるpow(a,6)
ことです。a*a*a*a*a*a
-O3 -lm -funroll-loops -msse4
mulsd
movapd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
と書くと(a*a*a)*(a*a*a)
、
movapd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm13, %xmm13
これにより、乗算命令の数が 3 に減ります。icc
同様の動作をします。
なぜコンパイラはこの最適化トリックを認識しないのでしょうか?
ベストアンサー1
なぜなら浮動小数点演算は結合性がない浮動小数点乗算でオペランドをグループ化する方法は、答えの数値精度に影響します。
その結果、ほとんどのコンパイラは、答えが同じままであることが確実である場合、または数値の精度を気にしないことをコンパイラに指示しない限り、浮動小数点計算の順序変更について非常に慎重になります。例:オプション-fassociative-math
gcc が浮動小数点演算を再関連付けできるようにする gcc のオプション、または-ffast-math
精度と速度のさらに積極的なトレードオフを可能にするオプションもあります。