2015-12-23 1 views
9

を追加し、デフォルト-O3 -fmaが融合乗算GCC 5.3で丸めモード

float mul_add(float a, float b, float c) { 
    return a*b + c; 
} 

で次のコードcompieldは、次のアセンブリ

vfmadd132ss  %xmm1, %xmm2, %xmm0 
ret 

I noticed GCC doing this with -O3 already in GCC 4.8を生成します。 -O3 -mfma

クラン3.7 -O3 fastとGCCと同じコードを生成-Ofast -mfma

vmulss %xmm1, %xmm0, %xmm0 
vaddss %xmm2, %xmm0, %xmm0 
retq 

なくクラン3.7を生成します。 this answerから、それはコンパイラが分離アドオンを融合し、あなたはリラックスした浮動小数点モデルを可能にしない限り、乗算することは許されない

言うので

私はGCCが-O3でないことを驚いています。

これは、FMAには1回の丸めがあり、ADD + MULには2回の丸めがあるからです。したがって、コンパイラはfusingによって厳密なIEEE浮動小数点の動作に違反します。しかしながら

this linkからは

言うかかわらずFLT_EVAL_METHODの値の任意の浮動小数点表現は、すべての中間結果は、無限の範囲及び精度を有しているかのように計算され、すなわち、縮小されてもよいです。

だから私は混乱して懸念しています。

  1. GCCはFMAを使用して-O3で正当化されていますか?
  2. fusingは厳密なIEEE浮動小数点の動作に違反しますか?
  3. ヒューズがIEEE浮動小数点ビアビールに違反し、GCC returns __STDC_IEC_559__がこれと矛盾しないので、 FMA can be emulated in software以来

FMAための2つのコンパイラスイッチがあるはずであるように思わ:ハードウェアはFMAを持っているコンパイラに指示する計算と一つにFMAを使用するようにコンパイラに指示する1。


これは、オプション-ffp-contractで制御できます。 GCCではデフォルトは-ffp-contract=fastで、Clangではそうではありません。 -ffp-contract=on-ffp-contract=offのような他のオプションは、FMA命令を生成しません。

たとえば、-O3 -mfma -ffp-contract=fastのClang 3.7は、vfmadd132ssを生成します。


私は-ffp-contractonにセット、off、およびfastONOFF#pragma STDC FP_CONTRACTセットのいくつかの順列を確認。すべてのケースで私は-O3 -mfmaも使用しました。

答えは簡単です。 #pragma STDC FP_CONTRACT ONまたはOFFは違いはありません。 -ffp-contractのみが重要です。

GCCは、それが

  1. -ffp-contract=fast(デフォルト)とfmaを使用しています。クランで

それは-ffp-contract=fastfma

  1. を使用しています。 -ffp-contract=on(デフォルト)と#pragma STDC FP_CONTRACT ON
  2. (デフォルトはOFFです)。クランと言い換える

あなたは#pragma STDC FP_CONTRACT ONで(-ffp-contract=onがデフォルトであるため)または-ffp-contract=fastfmaを得ることができます。 -ffast-math(したがって-Ofast)は-ffp-contract=fastと設定されています。


MSVCとICCを調べました。 MSVCで

それは/O2 /arch:AVX2 /fp:fastとFMA命令を使用しています。 MSVCの場合/fp:preciseがデフォルトです。

ICCではfmaと-O3 -march=core-avx2(実際には-O1で十分です)。これは、デフォルトでICCが-fp-model fastを使用するためです。しかしICCは-fp-model preciseでもfmaを使用します。 ICCでfmaを無効にするには、-fp-model strictまたは-no-fmaを使用します。

fmaが有効な場合、GCCとICCはfmaを使用します(GCC/Clangの場合は-mfma、ICCの場合は-march=core-avx2)。ただし、ClangとMSVCでは使用できません。あなたが融合した乗算・加算が許可されていることを引用した場合、「プラグマFP_CONTRACTがオフになっている場合を除き」

+0

コンパイラのバグかもしれません。報告することを検討してください。 – fuz

+0

gccがやっていることは大丈夫です。 FP表現を収縮することに関するFLT_EVAL_METHOD文書を読んだ後、私は 'clang' *がこれをしないと驚いています。実際の標準文書に基づいているわけではないので、私はこれを答えとして掲示するつもりではない。 –

+0

@FUZxxl、浮動小数点タグはieee-754よりも適切だろうと思いますか? (そうなら、それを自由に変更してください)。私は浮動小数点タグも使うべきだと思う。 –

答えて

3

IEEE-754は、この点についての言語に延期ので、それは、IEEE-754に違反していない:

言語の標準も定義し、提供するために、実装を必要とし、許可属性と付加価値を禁止すべきですブロックごとに個別にまたは集合的に最適化を変更します。これらの最適化は、含まれる場合がありますが、これらに限定されない:

...

- 乗算と加算からfusedMultiplyAdd操作の合成。

標準Cでは、STDC FP_CONTRACTプラグマは、この値を変更する最適化を制御する手段を提供します。したがって、GCCはデフォルトで融合を実行するためにライセンスされています。ただし、STDC FP_CONTRACT OFFを設定して最適化を無効にすることができます。これをサポートしていないということは、C標準を遵守していないことを意味します。

+0

「それをサポートしていないということは、C標準を遵守しない」という意味はどうですか?ちなみに、GCCは 'STDC FP_CONTRACT'を無視しているようです。代わりに、 '-ffp-contract'だけを使用します。 Clangは両方を認識します。 –

+0

FP_CONTRACTはC標準の一部です。それを無視することは、適合しないことです。 –

+0

ああ、私は、FP_CONTRACT(またはそれをサポートしていないコンパイラ)をサポートしていないGCCを指していることに気が付きましたか?今分かります。 –

4

は、あなたが重要な条件を残しました。 Cでの新しめの特徴はどのです(私はC99で導入されたと思う)とすべては最初から乗加算融合していたのPowerPCで絶対に必要作られた - 実際には、Xの* yは、FMA(X、Y、0と同等でした)、x + yはfma(1.0、x、y)と等価であった。

FP_CONTRACTは、乗算/ FLT_EVAL_METHOD、ない追加融合制御するものです。 FLT_EVAL_METHODの精度が高い場合は、契約は常に有効ですが、オペレーションが非常に高精度で実行された後、丸められたように見せかけるだけです。あなたはスピードが、精度を必要としない場合は

FMA機能が便利です。ハードウェアで利用できない場合でも、契約結果をゆっくりと正確に計算します。また、ハードウェアで使用できる場合はインライン化する必要があります。

+0

GCCが '-O3'でfmaで正当化されているかどうかについて、ある程度はこれが私の最初の質問に答えると思います。しかし、それがIEEEに準拠しているかどうかはまだ分かりません。そしてGCCは '__STDC_IEC_559__'を定義しているので、IEEE準拠だと思うかもしれませんが、他の人々はfmaがこれを打ち破ると主張しています(' __STDC_IEC_559__'が定義されているときにGCCが正当化されないと主張します)。だから私はまだ混乱している。 –

+0

@ Zboson:ドキュメントのプラグマに関することを私は気付きましたが、新しく広範にサポートされていたことはわかりませんでした。だから私はそれを以前に言及しなかったのです。 –

+1

@PeterCordes、それは大丈夫ですが、GCCはそのプラグマを気にしていないようですので、それは間違いです。いずれにせよ、それはIEEEに準拠しているとは何も言わない。 GCCは '__STDC_IEC_559__'を返し、' -ffp-contract = fast'を使いますので、これが矛盾しているかどうかを知りたいと思います。 –