GCC はなぜ a*a*a*a*a*a を (a*a*a)*(a*a*a) に最適化しないのでしょうか? 質問する

GCC はなぜ a*a*a*a*a*a を (a*a*a)*(a*a*a) に最適化しないのでしょうか? 質問する

私は科学アプリケーションで数値最適化を行っています。私が気づいたことの 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 -msse4mulsd

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-mathgcc が浮動小数点演算を再関連付けできるようにする gcc のオプション、または-ffast-math精度と速度のさらに積極的なトレードオフを可能にするオプションもあります。

おすすめ記事