問題タブ [fma]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - 融合乗算加算とデフォルトの丸めモード
GCC 5.3 では、次のコードでコンパイルされます-O3 -fma
次のアセンブリを生成します
-O3
GCC が既に GCC 4.8 でこれを行っていることに気付きました。
-O3 -mfma
プロデュースを使用したClang 3.7
しかし、Clang 3.7 with-Ofast -mfma
は GCC with と同じコードを生成し-O3 fast
ます。
この回答-O3
から、GCCがそうしていることに驚いています
緩和された浮動小数点モデルを許可しない限り、コンパイラは分離された加算と乗算を融合することはできません。
これは、FMA には丸めが 1 つしかないのに対し、ADD + MUL には丸めが 2 つあるためです。そのため、コンパイラは融合によって厳密な IEEE 浮動小数点の動作に違反します。
ただし、このリンクからそれは言う
FLT_EVAL_METHOD の値に関係なく、任意の浮動小数点式を縮小できます。つまり、すべての中間結果が無限の範囲と精度を持っているかのように計算されます。
だから今、私は混乱し、心配しています。
- GCC は FMA を使用することで正当化され
-O3
ますか? - 融合は厳密な IEEE 浮動小数点の動作に違反しますか?
- 融合がIEEE浮動小数点の動作に違反し、GCCが戻っ
__STDC_IEC_559__
てきたので、これは矛盾していませんか?
FMAはソフトウェアでエミュレートできるため、FMAには 2 つのコンパイラ スイッチが必要なようです。
どうやら、これはオプションで制御できます-ffp-contract
。GCC ではデフォルトで-ffp-contract=fast
あり、Clang ではそうではありません。-ffp-contract=on
やnoなどのその他のオプション-ffp-contract=off
は、FMA 命令を生成しません。
たとえば、 Clang 3.7 の-O3 -mfma -ffp-contract=fast
プロデュースvfmadd132ss
.
#pragma STDC FP_CONTRACT
set toON
とset to 、、およびのいくつかの順列を確認OFF
しました。すべての場合で私も使用しました。-ffp-contract
on
off
fast
-O3 -mfma
GCC の場合、答えは簡単です。#pragma STDC FP_CONTRACT
ONもOFFも関係ありません。重要なだけ-ffp-contract
です。
GCCでfma
使う
-ffp-contract=fast
(デフォルト)。
Clangで使用fma
- と
-ffp-contract=fast
。 -ffp-contract=on
(デフォルト) と(#pragma STDC FP_CONTRACT ON
デフォルトはOFF
)。
つまり、Clang を使用するfma
と#pragma STDC FP_CONTRACT ON
(-ffp-contract=on
がデフォルトであるため) または で取得できます-ffp-contract=fast
。-ffast-math
(したがって-Ofast
)セット-ffp-contract=fast
。
MSVCとICCを調べました。
MSVC では、fma 命令を使用し/O2 /arch:AVX2 /fp:fast
ます。With MSVC/fp:precise
がデフォルトです。
ICC では fma を使用します-O3 -march=core-avx2
(実際-O1
には十分です)。これは、デフォルトで ICC が を使用するためです-fp-model fast
。しかし、ICC は-fp-model precise
. ICC で fma を無効にするには-fp-model strict
、 またはを使用します-no-fma
。
したがって、デフォルトでは、fma が有効になっている場合 ( -mfma
GCC/Clang またはICC を使用-march=core-avx2
)、GCC と ICC は fma を使用しますが、Clang と MSVC は使用しません。
gcc - GCC 4.9 が AVX FMA を使用する機会を認識するようにするには、どうすればよいですか?
両方std::vector<double> X,Y
のサイズN
( ありN%16==0
) があり、 を計算したいsum(X[i]*Y[i])
。これは、 Fused Multiply and Add (FMA)の古典的な使用例であり、AVX 対応プロセッサで高速になるはずです。ターゲット CPU がすべて Intel、Haswell、またはそれ以降であることはわかっています。
GCCにそのAVXコードを発行させるにはどうすればよいですか? -mfma
はソリューションの一部ですが、他のスイッチが必要ですか?
そして、std::vector<double>::operator[]
これを妨げていますか?変身できることを知っている
に
そのため、コンパイラ&X[0]
はループ内で変更されていないことを検出できます。しかし、これで十分でしょうか、それとも必要でしょうか?
現在のコンパイラは GCC 4.9.2、Debian 8 ですが、必要に応じて GCC 5 にアップグレードできます。
c - インテル FMA 命令によるパフォーマンスの利点はゼロ
Haswell の FMA 命令を使用した次の命令シーケンスを考えてみましょう。
同じ計算は、次のように非 FMA 命令を使用して表現できます。
FMA バージョンでは、非 FMA バージョンよりもパフォーマンスが向上すると予想されます。
残念ながら、この場合、パフォーマンスの向上はゼロ (0) です。
誰かが理由を理解するのを手伝ってくれますか?
コア i7-4790 ベースのマシンで両方のアプローチを測定しました。
アップデート:
そこで、生成されたマシン コードを分析したところ、Haswell には 2 つの FMA パイプがあるため、r1 と r2 の依存関係チェーンが並行してディスパッチできるように、MSFT VS2013 C++ コンパイラがマシン コードを生成していると判断しました。
r3 は r1 の後にディスパッチする必要があるため、この場合、2 番目の FMA パイプはアイドル状態になります。
ループを展開して 3 セットではなく 6 セットの FMA を実行すれば、反復ごとにすべての FMA パイプをビジー状態に保つことができると考えました。
残念ながら、この場合のアセンブリ ダンプを確認したところ、MSFT コンパイラは、探していた種類の並列ディスパッチを許可するレジスタ割り当てを選択していませんでした。また、求めていたパフォーマンスの向上が得られなかったことが確認されました。為に。
C コードを (組み込み関数を使用して) 変更して、コンパイラがより良いコードを生成できるようにする方法はありますか?
c++ - AVX レジスタからデータを取得する方法は?
MSVC 2013 と AVX 1 を使用して、レジスタに 8 つの浮動小数点数があります。
inline void print(float) {...}
ここで、8 つのフロートすべてを呼び出したいと思います。インテル® AVX 組み込み関数により、これがかなり複雑になるようです。
しかし、MSVC にはこれら 2 つの組み込み関数のいずれもありません。確かに、値をメモリに書き戻してそこからロードすることはできますが、アセンブリ レベルではレジスタをスピルする必要はないと思います。
おまけQ:もちろん書きたい
しかし、MSVC は、多くの組み込み関数がループ展開を必要とすることを理解していません。で 8x32 浮動小数点数のループを作成するにはどうすればよい__m256 foo
ですか?
floating-point - AVX FMA ユニットを使用して、正確な 52 ビット整数乗算を行うことはできますか?
AXV2 には、32 ビットより大きいソースとの整数乗算はありません。32 x 32 -> 32の乗算、および32 x 32 -> 64の乗算1を提供しますが、64 ビット ソースでは何も提供しません。
入力が 32 ビットより大きいが 52 ビット以下の符号なし乗算が必要だとします。浮動小数点DP 乗算または FMA 命令を単純に使用できますか。整数入力と結果は 52 ビット以下 (つまり、[0, 2^52-1] の範囲) で表すことができますか?
積の 104 ビットすべてが必要な、より一般的なケースはどうですか? または、整数積が 52 ビットを超える場合 (つまり、積のビット インデックス > 52 にゼロ以外の値がある) - しかし、下位 52 ビットのみが必要ですか? この後者の場合、MUL
は上位ビットを提供し、下位ビットの一部を切り捨てます (おそらく、それが IFMA の助けになるのでしょうか?)。
編集:実際、この回答に基づいて、おそらく2 ^ 53まで何でもできる可能性があります-1
仮数の前の暗黙のリーディングが効果的に別のビットを与えることを忘れていました。
1興味深いことに、 Mystialがコメントで説明しているように、64 ビット製品のPMULDQ
動作は 32 ビット バージョンの半分のレイテンシと 2 倍のスループットを持っています。PMULLD
floating-point - FMA 命令のパフォーマンスについて
CPU で実行できる操作の数を最大にする方法を理解しようとしています。私は単純な行列乗算プログラムを実行しており、Skylake プロセッサを使用しています。このアーキテクチャに関するフロップ情報については、ウィキペディアのページを見ていましたが、理解するのが困難です。
私の理解では、FMA 命令では 3 方向の FP 入力が許可されていますよね? そして、それらの間で加算と乗算を混在させることができます。しかし、フロートを 2 つだけ追加するとどうなりますか? 単純に1倍するだけですか?1 サイクルで 3 つのフロートを追加できますか、それとも分割されますか? skylake には単精度入力で 32 FLOP/サイクルがあることがわかりましたが、「2 つの 8 幅 FMA 命令」の意味は何ですか?
事前に説明をありがとう
c++ - 融合乗算加算浮動小数点の不正確さを処理する一般的な方法
昨日、私は自分のプロジェクトでバグを追跡していました.数時間後、多かれ少なかれ次のようなことをしているコードに絞り込みました:
コンパイルと実行後:
私の観点からは、2 つのビットごとに同一のペアの 2 つの減算を要求し (2 つのゼロを取得すると予想していました)、それらを 2 乗し (再び 2 つのゼロ)、それらを加算 (ゼロ) したため、何かが間違っています。
問題の根本的な原因は、融合乗算加算操作の使用であることが判明しました。これにより、どこかで結果が不正確になります(私の観点からは)。より正確な結果が得られると約束されているため、通常、この最適化に反対するものは何もありませんが、この場合、1.34925e-06 は、私が期待していた 0 とはかけ離れています。
テストケースは非常に「壊れやすい」です。より多くの出力またはより多くのアサートを有効にすると、コンパイラが fused-multiply-add を使用しなくなったため、アサートが停止します。たとえば、すべての行のコメントを外すと:
これはコンパイラのバグだと思ったので報告しましたが、これは正しい動作だという説明で締めくくられました。
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79436
だから私は疑問に思っています-問題を回避するには、そのような計算をどのようにコーディングする必要がありますか? 私は一般的な解決策について考えていましたが、次のものよりも優れています。
とにかく、コードを修正または改善したいと思います-修正/改善するものがあれば--ffp-contract=off
プロジェクト全体に設定するのではなく、とにかくコンパイラライブラリで内部的に fuse-multiply-add が使用されているため(sinf( ) と cosf()) であるため、解決策ではなく「部分的な回避策」になります...「浮動小数点を使用しない」(;