s-ffast-math
を使用してループのベクトル化を実現するために g++ を使用することが必須なのはなぜですか? 精度を落としたくないので嫌いですdouble
。-ffast-math
4 に答える
で精度が落ちるとは限りません-ffast-math
。NaN
などの処理と、Inf
操作が実行される順序にのみ影響します。
GCC で計算を並べ替えたり単純化したりしたくない特定のコードがある場合は、asm
ステートメントを使用して変数が使用されていることを示すことができます。
たとえば、次のコードは に対して丸め演算を実行しf
ます。ただし、この 2 つf += g
のf -= g
操作は gcc によって最適化されてしまう可能性があります。
static double moo(double f, double g)
{
g *= 4503599627370496.0; // 2 ** 52
f += g;
f -= g;
return f;
}
x86_64 では、次のasm
ステートメントを使用して、GCC にその最適化を実行しないように指示できます。
static double moo(double f, double g)
{
g *= 4503599627370496.0; // 2 ** 52
f += g;
__asm__("" : "+x" (f));
f -= g;
return f;
}
残念ながら、これを各アーキテクチャに適応させる必要があります。PowerPC では、+f
の代わりに使用し+x
ます。
ベクトル化により、結果が異なる可能性があるか、浮動小数点信号/例外を見逃す可能性があるため、非常に可能性があります。
32 ビット x86 用にコンパイルしている場合、gcc と g++ はデフォルトで浮動小数点演算に x87 を使用し、64 ビットではデフォルトで SSE を使用しますが、x87 は同じ計算に対して異なる値を生成できるため、g++ である可能性は低いです。フラグを使用する-ffast-math
か、オンにするフラグの一部を使用しない限り、同じ結果が得られることを保証できない場合は、ベクトル化を検討します。
基本的に、ベクトル化されたコードの浮動小数点環境は、ベクトル化されていないコードの浮動小数点環境と同じではない可能性があります。違いが問題にならない場合は、重要な意味で、
-fno-math-errno -fno-trapping-math -fno-signaling-nans -fno-rounding-math
ただし、最初にそれらのオプションを調べて、プログラムの正確さに影響を与えないことを確認してください。-ffinite-math-only
も役立つかもしれません
gcc で自動ベクトル化を有効にするために、ffast-math は実際には必要ありません。https://gcc.gnu.org/projects/tree-ssa/vectorization.html#usingを参照してください
浮動小数点リダクションのベクトル化を有効にするには、-ffast-math または -fassociative-math を使用します。
-fassociative-math を使用するだけで十分です。
これは 2007 年から続いています。https://gcc.gnu.org/projects/tree-ssa/vectorization.html#oldnewsを参照してください。
- -ffast-math の代わりに -fassociative-math を使用して、float のリダクションのベクトル化を有効にすることができます (2007-09-04)。