私はスタックオーバーフローに関するこの非常に興味深い質問を読んでいました。
整数の乗算は、最新のCPUでの加算と同じ速度で本当に行われますか?
コメントの1つは言った:
「Haswellでは、FP乗算スループットがFP加算の2倍であることは何の価値もありません。これは、ポート0と1の両方を乗算に使用できますが、加算に使用できるのはポート1だけだからです。 -multiplyは両方のポートで実行できるため追加します。」
加算と比較して2倍の同時乗算を許可するのはなぜですか?
私はスタックオーバーフローに関するこの非常に興味深い質問を読んでいました。
整数の乗算は、最新のCPUでの加算と同じ速度で本当に行われますか?
コメントの1つは言った:
「Haswellでは、FP乗算スループットがFP加算の2倍であることは何の価値もありません。これは、ポート0と1の両方を乗算に使用できますが、加算に使用できるのはポート1だけだからです。 -multiplyは両方のポートで実行できるため追加します。」
加算と比較して2倍の同時乗算を許可するのはなぜですか?
回答:
これは、本文ではない場合、おそらく質問のタイトルに答えます:
浮動小数点の加算では、2つの仮数を揃えてから(2つの指数の差に応じて)加算する必要があり、加算器の前に大きな可変シフトが必要になる可能性があります。次に、仮数加算の結果を再正規化する必要があり、浮動小数点の結果を適切にフォーマットするために、別の大きな可変量のシフトが必要になる可能性があります。したがって、2つの仮数バレルシフターには、ゲート遅延、ワイヤ遅延、またはコンパクトなキャリーセーブ加算ツリー乗算器フロントエンドの遅延を超える余分なサイクルが必要になる可能性があります。
OPに追加:2ミリメートルと2キロメートルの長さを追加しても、どちらの単位も4ではないことに注意してください。これは、追加する前に、いずれかの測定値を同じスケールまたは単位表現に変換する必要があるためです。その変換には、基本的に10の累乗による乗算が必要です。浮動小数点数は可変スケーリング整数の形式であるため、同じことが通常浮動小数点加算時に発生する必要があります(例えば、単位またはスケール係数、指数、各番号)。したがって、両方が同じ単位またはスケールを表すようにするために、生の仮数ビットを追加する前に、数値の1つを2の累乗でスケールする必要がある場合があります。このスケーリングは、基本的に2の累乗による単純な乗算形式です。したがって、浮動小数点加算には乗算が必要です。 (2のべき乗である可変ビットシフトまたはバレルシフターを使用すると、トランジスタサイズに比べて比較的長い配線が必要になり、ディープサブミクロンリソグラフィ回路では比較的遅くなる可能性があります)。2つの数値の大部分がキャンセルされる場合(一方が他方の負に近いため)、加算の結果を適切にフォーマットするために、加算の結果を再スケーリングする必要がある場合があります。したがって、数値形式(IEEE浮動小数点)の性質により、同等の単位またはスケールを表す仮の固定(有限)数の仮数ビットのバイナリ加算を囲む2つの乗算(プリおよびポスト)ステップがさらに必要な場合、加算が遅くなる可能性があります)。
追加#2:また、多くのベンチマークは、ベアアドよりもFMACS(積和)を重視しています。融合MACでは、加数のアライメント(シフト)はほとんどが乗算と並行して行われることが多く、仮数の加算は最終キャリー伝播の前にCSAツリーに含まれることがよくあります。
FP乗算では、指数処理は単純な加算であることが判明しました(ログ領域での乗算が単なる加算であるというまったく同じ理由で)。対数に出会ったことを願っています。
ここで、対数形式で2つの数値を追加するのがどれほど難しいか考えてみてください...
浮動小数点は、リニアドメインとログドメインの間の灰色の領域に存在し、両方の側面があります。各FP番号は、仮数(線形)と(対数)指数で構成されます。仮数の各ビットの意味を判断するには、最初に指数(単なるスケールファクター)を調べる必要があります。
FP加算では、一般的な場合の指数処理には仮数を2回バレルシフトする必要があります。各バレルシフトは、事実上、わずかに単純化された乗算の特殊なケースです。
(最初のシフトは、両方の入力を同じ2のべき乗に揃えるため、仮数ビットの各オペランドのバイナリウェイトが同じになります。
10進数の例で十分です(ただし、明らかにバイナリが使用されます)...
2番目は出力を再スケーリングします...
逆説的に言えば、FP加算には、2つの乗算のようなものが含まれます。その観点から、報告されたパフォーマンスはそれほど驚くことではありません。
TL:DR:Intelは、SSE / AVX FPの追加レイテンシがスループットよりも重要だと考えたため、Haswell / BroadwellのFMAユニットでは実行しないことを選択しました。
Haswell実行(SIMD)FPはFMA(Fused Multiply-Add)と同じ実行ユニットで乗算しますが、FPを集中的に使用するコードのほとんどは命令ごとに2つのFLOPを実行できるためです。FMAと同じ5サイクルレイテンシ、およびmulps
以前のCPU(Sandybridge / IvyBridge)と同じ。 Haswellは2つのFMAユニットを必要としていましたが、以前のCPUの専用乗算ユニットと同じレイテンシーであるため、乗算を実行することのマイナス面もありません。
しかし、それはまだ実行するために、以前のCPUから専用のSIMD FPアドユニットを保持addps
/ addpd
3サイクルのレイテンシで。 考えられる理由は、多くのFPを追加するコードがスループットではなく、レイテンシのボトルネックになる傾向があるということです。GCCの自動ベクトル化からよく得られるように、1つの(ベクトル)アキュムレータのみを持つ配列の単純な合計に対しては、これは確かに当てはまります。しかし、Intelがそれが彼らの推論であることを公に確認したかどうかはわかりません。
Broadwellマイクロアーキテクチャは同じである(しかしスピードアップmulps
/mulpd
FMAは、図5Cに宿泊しながら、3C待ち時間に)。おそらく、彼らはFMAユニットをショートカットし、のダミー加算を行う前に乗算結果を得ることができた0.0
かもしれませんし、まったく異なるものかもしれませんが、それはあまりにも単純すぎます。 BDWは、ほとんどがHSWのダイシュリンクであり、ほとんどの変更はマイナーです。
Skylakeでは、すべてのFP(追加を含む)は、もちろんdiv / sqrtおよびビットごとのブール値(絶対値または否定など)を除き、4サイクルレイテンシおよび0.5cスループットでFMAユニットで実行されます。Intelは、低レイテンシFPの追加に余分なシリコンを使用する価値はない、または不均衡なaddps
スループットには問題があると判断したようです。また、レイテンシを標準化することで、ライトバックの競合を回避できます(同じサイクルで2つの結果が準備されている場合)。すなわち、スケジューリングおよび/または完了ポートを簡素化します。
そのため、Intelは次の主要なマイクロアーキテクチャリビジョン(Skylake)で変更しました。 FMAレイテンシーを1サイクル短縮すると、レイテンシーが制限されていた場合に、専用のSIMD FPアドユニットのメリットがはるかに小さくなりました。
Skylakeはまた、インテルがAVX512の準備をしている兆候を示しています。別のSIMD-FP加算器を512ビット幅に拡張すると、さらに多くのダイ面積が必要になります。Skylake-X(AVX512搭載)は、通常のSkylakeクライアントとほぼ同じコアを持っていると報告されていますが、大きなL2キャッシュと(一部のモデルの)追加の512ビットFMAユニットはポート5に「ボルトオン」されます。
SKXは、512ビットuopが飛行中の場合、ポート1 SIMD ALUをシャットダウンしますが、vaddps xmm/ymm/zmm
任意の時点で実行する方法が必要です。これにより、専用のFP ADDユニットをポート1に配置することが問題となり、既存のコードのパフォーマンスとは異なる変更の動機となります。
楽しい事実:Skylake、KabyLake、Coffee Lake、Cascade Lakeのすべては、いくつかの新しいAVX512命令を追加することを除いて、Skylakeとマイクロアーキテクチャ的に同一です。それ以外の場合、IPCは変更されていません。ただし、新しいCPUには優れたiGPUがあります。Ice Lake(Sunny Coveのマイクロアーキテクチャー)は、実際に新しいマイクロアーキテクチャーを目にした数年ぶりの例です(広くリリースされていないCannon Lakeを除く)。
FMULユニットとFADDユニットの複雑さに基づく議論は興味深いが、この場合には関係ない。 FMAユニットには、FMA 1の一部としてFP加算を行うために必要なすべてのシフトハードウェアが含まれています。
注:x87 fmul
命令を意味するのではなく、32ビットの単精度/ float
および64ビットのdouble
精度(53ビットの仮数、別名仮数)をサポートするSSE / AVX SIMD /スカラーFP乗算ALUを意味します。例えばmulps
またはのような指示mulsd
。実際の80ビットx87 fmul
は、ポート0のHaswellでまだ1クロックスループットです。
最近のCPUには、価値があるときに問題を投げるのに十分なトランジスタがあり、物理的な距離の伝播遅延の問題を引き起こさない場合に問題があります。特に、時々アクティブになる実行ユニットの場合。https://en.wikipedia.org/wiki/Dark_siliconおよび2011年のカンファレンスペーパー:Dark Silicon and the End of Multicore Scalingを参照してください。これにより、CPUが大量のFPUスループットと大量の整数スループットを持つことが可能になりますが、同時に両方を実行することはできません(これらの異なる実行ユニットは同じディスパッチポート上にあるため、互いに競合します)。mem帯域幅のボトルネックにならない、慎重に調整されたコードの多くでは、制限要因はバックエンド実行ユニットではなく、フロントエンド命令のスループットです。(ワイドコアは非常に高価です)。http://www.lighterra.com/papers/modernmicroprocessors/も参照してください。
HSW以前は、NehalemやSandybridgeなどのIntel CPUは、ポート0でSIMD FPを乗算し、ポート1でSIMD FPを追加していました。したがって、個別の実行ユニットがあり、スループットがバランスしていました。(https://stackoverflow.com/questions/8389648/how-do-i-achieve-the-theoretical-maximum-of-4-flops-per-cycle
Haswellは、Intel CPUにFMAサポートを導入しました(AMDがブルドーザーにFMA4を導入してから2年後、Intelが4オペランド非-破壊先FMA4)。面白い事実:AMD Piledriverは、FMA3を搭載した最初のx86 CPUであり、2013年6月のHaswellの約1年前
これには、3つの入力を持つ単一のuopをサポートするために、内部のいくつかの大きなハッキングが必要でした。しかし、とにかく、Intelはオールインし、縮小し続けるトランジスタを利用して2つの256ビットSIMD FMAユニットを搭載し、FP数学のためのHaswell(およびその後継)の獣を作りました。
インテルが念頭に置いていたパフォーマンス目標は、BLAS密行列とベクトルドット積です。それらの両方は、主にFMAを使用することができますし、必要がないだけで追加します。
前に述べたように、FPをほとんどまたは単に追加する一部のワークロードは、スループットではなく(ほとんど)遅延の追加でボトルネックになります。
脚注1:そして、乗数がの1.0
場合、FMAは文字通り加算に使用できますが、addps
命令よりも遅延が長くなります。これは、FPがレイテンシよりもスループットを追加するL1dキャッシュでホットなアレイを合計するようなワークロードに潜在的に役立ちます。これは、複数のベクトルアキュムレータを使用してレイテンシを非表示にし、FP実行ユニットで10個のFMA操作を実行し続ける場合にのみ役立ちます(5cレイテンシ/ 0.5cスループット= 10オペレーションレイテンシ*帯域幅積)。 ベクトルドット積にFMAを使用する場合も、これを行う必要があります。
David KanterのSandybridgeマイクロアーキテクチャの記事を参照してください。これには、NHM、SnB、およびAMD BulldozerファミリのどのポートにどのEUがあるのかを示すブロック図があります。(Agner Fogの命令表とasm最適化マイクロアーキテクチャガイド、およびhttps://uops.info/も参照してください。これには、多くの世代のIntelマイクロアーキテクチャのほぼすべての命令のuop、ポート、レイテンシ/スループットの実験的テストもあります。)
また関連する:https : //stackoverflow.com/questions/8389648/how-do-i-achieve-the-theoretical-maximum-of-4-flops-per-cycle
[cpu-architecture]
、[performance]
、[x86-64]
、[assembly]
、と[sse]
。手書きのアセンブリよりも高速にCollatz予想をテストするためのC ++コードに関する回答を書きました-なぜですか?多くの人が良いと思うこと。また、この OOOについては、実行パイプライン。
この部分を見ていきます:
「なぜ彼らが許可するのか」
TL; DR-彼らはそれをそのように設計したからです。それは管理上の決定です。仮数とビットシフターの答えは確かにありますが、これらは管理上の決定事項になります。
なぜ彼らはそのように設計したのですか?答えは、特定の目標を達成するために仕様が作成されていることです。これらの目標には、パフォーマンスとコストが含まれます。パフォーマンスは運用ではなく、CrysisのFLOPSやFPSなどのベンチマークを対象としています。
これらのベンチマークには複数の機能があり、それらのいくつかは同時に処理できます。
デザイナーが、ウィジェットAの2つの機能を使用すると、ウィジェットBの2つの機能ではなく、はるかに高速になると考えている場合、ウィジェットAを使用します。
スーパースカラーおよびスーパーパイプライン(マルチコアの前)が商用チップで最初に一般的になったときを振り返ると、これらはパフォーマンスを向上させるために存在していました。Pentiumには2つのパイプがあり、ベクトル結合はありません。Haswellには、より多くのパイプ、ベクトルユニット、より深いパイプ、専用機能などがあります。なぜ2つすべてがないのですか?彼らがそのように設計したからです。
Intelのこの図は、次の場合に役立ちます。
彼らは各ユニットにFMA(融合乗算加算)と乗算加算器および単一加算器を与えているようです。それらは、ハードウェアを共有する場合としない場合があります。
内部設計の理論的根拠がなければ、なぜ答えるのがはるかに難しいのですが、紫色のボックス内のテキストは、「倍のピークFLOP」を示すヒントを与えてくれます。プロセッサは、実際のユースケースから派生したベンチマークのセットをターゲットにします。FMAは行列乗算の基本単位であるため、これらで非常に人気があります。素の追加はあまり人気がありません。
指摘されているように、乗算パラメーターが1であるFMA命令で両方のポートを使用して加算を行うことができます。(A x 1)+ Bを計算します。これは、裸の加算よりも若干遅くなります。
時間のかかるステップを見てみましょう。
追加:指数を揃えます(大規模なシフト操作の場合があります)。1つの53ビット加算器。正規化(最大53ビット)。
乗算:1つの大規模な加算器ネットワークにより、53 x 53の1ビット積を2つの106ビット数の合計に減らします。1つの106ビット加算器。正規化。ビット積を2つの数値に減らすことは、最終加算器と同じくらい速くできると思います。
可変時間を乗算できる場合、正規化はほとんどの場合1ビットだけシフトするという利点があり、他のケースを非常に迅速に検出できます(非正規化入力、または指数の合計が小さすぎる)。
さらに、正規化手順が必要になることは非常に一般的です(サイズが等しくない数値を加算し、近い数値を減算します)。したがって、乗算では高速パスを使用し、低速パスで大ヒットする余裕があります。追加することはできません。
PS。コメントを読む:非正規化された数値を追加してもペナルティは発生しないというのは理にかなっています。つまり、指数を揃えるためにシフトされたビットの多くがゼロであることを意味します。また、非正規化された結果とは、指数が小さくなりすぎる場合に先行ゼロを削除するためにシフトを停止することを意味します。
-ffast-math
、FPアシストを使用する代わりにFTZ / DAZ(非正規化をゼロに設定)でコンパイルしてコンパイルする理由です。