SQRT *とDIV *は、最新のIntel / AMD CPUでデータに依存するスループットまたはレイテンシを持つ2つの「単純な」ALU命令(マイクロコード化された分岐/ループではなく、単一のuop)です。(add / multiply / fmaの非正規化aka subnormal FP値のマイクロコードアシストはカウントされません)。他のすべてはかなり修正されているので、アウトオブオーダーのuopスケジューリング機構は、結果がいくつかのサイクルで準備ができていることの確認を待つ必要はありません。
いつものように、インテルの組み込みガイドは、パフォーマンスの単純化しすぎた図を提供します。Skylakeの倍精度では、実際のレイテンシは固定の18サイクルではありません。(あなたが引用することを選択した数に基づいて、私はあなたがスカイレイクを持っていると思います。)
div / sqrtの実装は困難です。ハードウェアでさえ、私たちにできる最善のことは反復的な改良プロセスです。一度により多くのビットを洗練すると(Broadwell以降の基数1024の除算器)、スピードが上がります(ハードウェアに関するこのQ&Aを参照)。 しかし、それでも十分に遅いので、初期段階を使用して単純なケースを高速化できます (または、高速化メカニズムが、部分的にパイプライン化されたdiv / sqrtユニットを備えた最近のCPUですべてゼロの仮数のセットアップ手順をスキップしているだけです。古いCPUにはスループットがありました。 = FP div / sqrtのレイテンシ。その実行ユニットはパイプライン処理が困難です。)
https://www.uops.info/html-instr/VSQRTSD_XMM_XMM_XMM.htmlは、Skylake SQRTSDが13〜19サイクルのレイテンシで変化する可能性があることを示しています。SKL(クライアント)の数値は13サイクルのレイテンシのみを示していますが、詳細なSKL vsqrtsdページから、input = 0でのみテストされていることがわかります。SKX(サーバー)の数値は、13〜19サイクルのレイテンシを示しています。(このページには、テストのバイナリビットパターンを含む、使用したテストコードの詳細な内訳が記載されています。)同様のテスト(クライアントコアは0のみ)が非VEXsqrtsd xmm, xmm
ページで行われました。:/
InstLatx64の結果は、Skylake-X(Skylake-clientと同じコアを使用しますが、AVX512を有効にした状態)で13〜18サイクルの最良/最悪のレイテンシを示しています。
Agner Fogの指示表は、Skylakeでの15〜16サイクルの待ち時間を示しています。(Agnerは通常、さまざまな入力値の範囲でテストを行います。)彼のテストは自動化されておらず、他の結果と正確に一致しない場合があります。
一部のケースが速くなるのはなぜですか?
ほとんどのISA(x86を含む)は2進浮動小数点を使用することに注意してください。
ビットは、値を線形仮数(仮数)×2 expと符号ビットとして表します。
最近のIntelでは速度が2つしかないようです(少なくともHaswell以降) (コメントの@haroldとの議論を参照してください)。たとえば、0.25、1、4、16のように、2の累乗でさえすべて高速です。仮数= 0x0は1.0を表します。 https://www.h-schmidt.net/FloatConverter/IEEE754.htmlには、単精度用のインタラクティブな10進数<->ビットパターンコンバーターがあり、仮数と指数が表すもののセットビットと注釈のチェックボックスが付いています。
Skylakeで私がクイックチェックで見つけた唯一の高速なケースは、 4.0ではなく2の累乗でさえ、2.0ではありません。これらの数値は、入力と出力の両方が1.0の仮数(暗黙の1ビットセットのみ)を持つ正確なsqrt結果を持っています。 9.0
正確に表現できても3.0
結果はそうですが、高速ではありません。 3.0は仮数= 1.5で、仮数の最上位ビットのみがバイナリ表現で設定されます。9.0の仮数は1.125(0b00100 ...)です。したがって、ゼロ以外のビットはトップに非常に近いですが、明らかにそれを失格にするのに十分です。
(+-Inf
そしてNaN
高速でもあります。通常の負の数でもあります:結果= -NaN。私はi7-6700kでこれらの13サイクルのレイテンシを測定し4.0
ます。遅い場合の。対18サイクルのレイテンシと同じです。)
x = sqrt(x)
x = 1.0
(暗黙の先行1ビットを除いてすべてゼロの仮数)で間違いなく高速です。シンプルな入力とシンプルな出力があります。
2.0では、入力も単純です(仮数部がすべてゼロで、指数が1大きい)。出力は丸められません。sqrt(2)は不合理であり、したがって、任意の基数にゼロ以外の無限ビットがあります。これにより、Skylakeの速度が低下するようです。
Agner Fogの命令表は、AMD K10の整数div
命令のパフォーマンスは、商ではなく被除数(入力)の有効ビット数に依存すると述べていますが、Agnerのmicroarch pdfと命令表を検索しても、sqrtの具体的な脚注や情報は見つかりませんでしたデータ依存。
FP sqrtがさらに遅い古いCPUでは、速度の範囲に余裕がある場合があります。入力の仮数部の有効ビット数がおそらく関係があると思います。これが正しければ、有効ビットが少ないほど(仮数部の後続ゼロが多いほど)高速になります。しかし、繰り返しになりますが、Haswell / Skylakeでは、2の累乗でさえ高速なケースのみです。
あなたはこれをテストすることができ、データの依存関係を壊すことなく、カップルの入力に対する出力の背中を、例えばことを何かにandps xmm0, xmm1
/ orps xmm0, xmm2
sqrtsd出力に依存しますXMM0内の固定値を設定します。
または試験待ち時間に簡単な方法は、偽の出力依存の「利点」を取ることであるsqrtsd xmm0, xmm1
ことと- sqrtss
従って、出力レジスタは、そのマージするための入力であり、修飾されていない先の上位32分の64ビット(それぞれ)を残します。 これは、単純なインラインasm試行がスループットではなくレイテンシでボトルネックになり、コンパイラーが出力用に別のレジスターを選択してループで同じ入力を再読み取りできるようになったと私は思います。質問に追加したインラインasmは完全に壊れており、コンパイルもできませんが、実際のコードでは(即時)ではなく"x"
(xmmレジスター)入出力制約が使用されています"i"
か?
静的実行可能テストループ(で実行するため)のこのNASMソースは、perf stat
VEX以外のエンコーディングの偽の依存関係を使用しますsqrtsd
。
このISA設計のイボは、Pentium III上のSSE1でIntelが短期的に最適化したおかげです。P3は、128ビットレジスタを内部的に2つの64ビットハーフとして処理しました。上半分を変更しないでおくと、スカラー命令が単一のuopにデコードされます。(しかし、それでもPIII sqrtss
に誤った依存関係が与えられます)。AVXを使用するとvsqrtsd dst, src,src
、少なくともレジスタソースの場合やvcvtsi2sd dst, cold_reg, eax
、同様に近視眼的に設計されたスカラーint-> fp変換命令の場合に、最終的にこれを回避できます。(GCCは、レポートの最適化逃し:80586、89071、80571を。)
以前の多くのCPUではスループットも一定ではありませんでしたが、Skylakeは分周器を強化し、スケジューラが最後の単精度入力の3サイクル後に新しいdiv / sqrt uopを開始できることを常に認識しています。
ただし、Skylakeの倍精度スループットも変動します。AgnerFog の命令テーブルが正しい場合、最後の倍精度入力UOPの4〜6サイクル後。
https://uops.info/は、フラットな6c相互スループットを示しています。(または、その倍の長256ビットのベクトルについて、128ビットのスカラは、よりスループットが、同じ遅延を広いSIMDデバイダの別個の半体を使用することができる。)も参照浮動小数点乗算対浮動小数点除算抽出一部スループット/レイテンシ番号についてのAgner Fogの指示表から。