sqrtsd命令のレイテンシが入力に基づいて変化するのはなぜですか?Intelプロセッサ


9

まあ上でインテル固有のガイドには、「sqrtsd」と呼ばれる命令は18サイクルのレイテンシーを持っていることが述べられています。

私はそれを自分のプログラムでテストしました。たとえば、0.15を入力として受け取った場合は正しいです。しかし、256(または任意の2 ^ x)の数をとると、レイテンシはわずか13になります。なぜですか?

私が持っていた1つの理論は、13は「sqrtss」のレイテンシであり、「sqrtsd」と同じですが32ビット浮動小数点で行われるため、プロセッサは256ビットが32ビットに適合し、そのバージョンを使用することを理解するのに十分スマートであるということです一方、0.15は有限の方法で表現できないため、完全な64ビットが必要です。

私はインラインアセンブリを使用してそれをやっています、これはgcc -O3と-fno-tree-vectorizeでコンパイルされた関連部分です。

static double sqrtsd (double x) {
    double r;
    __asm__ ("sqrtsd %1, %0" : "=x" (r) : "x" (x));
    return r;
}

3
テストのコードを見せてください。最適化がプロセッサーではなくコンパイラーによって行われる実装を想像できます。
Robert Navado

プロセッサーはスマートではありません。与えられた命令を実行します。
Weather Vane


2
想像もしていません:skylakeのinstlatx64には、18(最悪の場合)と13(単純な値)もリストされています
ハロルド

1
インラインasmは意味がなく、コンパイルされません:godbolt.org/z/rJA6nS"i"指定は即時であり、出力制約にはできません。 sqrtsd即時ではなく、reg / mem入力のみを受け入れるため、コンパイルされてもアセンブルされません。また、コンパイル時定数のイミディエイトを使用しても、レイテンシをテストすることはできず、スループットのみをテストできます。しかし、あなたの数値は正気に見えるので、実際に行ったことはおそらくsqrtsdレイテンシをテストしたでしょう。
Peter Cordes

回答:


10

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, xmm2sqrtsd出力に依存しますXMM0内の固定値を設定します。

または試験待ち時間に簡単な方法は、偽の出力依存の「利点」を取ることであるsqrtsd xmm0, xmm1ことと- sqrtss従って、出力レジスタは、そのマージするための入力であり、修飾されていない先の上位32分の64ビット(それぞれ)を残します。 これは、単純なインラインasm試行がスループットではなくレイテンシでボトルネックになり、コンパイラーが出力用に別のレジスターを選択してループで同じ入力を再読み取りできるようになったと私は思います。質問に追加したインラインasmは完全に壊れており、コンパイルもできませんが、実際のコードでは(即時)ではなく"x"(xmmレジスター)入出力制約が使用されています"i"か?

静的実行可能テストループ(で実行するため)のこのNASMソースは、perf statVEX以外のエンコーディングの偽の依存関係を使用します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は、レポートの最適化逃し:805868907180571を。)


以前の多くのCPUではスループットも一定ではありませんでしたが、Skylakeは分周器を強化し、スケジューラが最後の単精度入力の3サイクル後に新しいdiv / sqrt uopを開始できることを常に認識しています。

ただし、Skylakeの倍精度スループットも変動します。AgnerFog の命令テーブルが正しい場合、最後の倍精度入力UOPの4〜6サイクル後。 https://uops.info/は、フラットな6c相互スループットを示しています。(または、その倍の長256ビットのベクトルについて、128ビットのスカラは、よりスループットが、同じ遅延を広いSIMDデバイダの別個の半体を使用することができる。)も参照浮動小数点乗算対浮動小数点除算抽出一部スループット/レイテンシ番号についてのAgner Fogの指示表から。


ところで、両極端の間の待ち時間についてはどうですか?それらは起こりますか?ハスウェルでそれを実現することはできませんでしたが、それは決定的ではありません
ハロルド

@harold:IDK、可能であれば、仮数の後続ゼロの数が少なくなると発生すると思います。しかし、おそらく最も単純なケースでは、特別なケースの早期出力検出器が1つしかない場合があります。Haswellの基数の低い除算器を使用すると、早期のアウトをより早く探す方が収益性が高くなりますが、(rsqrtが使用するのと同じテーブルからの)初期推定値が正確かどうかが問題であり、そうでない場合はすべての反復的な調整が必要です。最後への道。
Peter Cordes

rsqrt(ハスウェル上とにかく)2の累乗かかわらため、正確なものではなく、2とゼロの力は、これまでの平方根が速いところ私が見つけた唯一の入力は、再びされrsqrtた命令は、単なる検索与えられたよりもやっているようです実際のレイテンシーの長さ
ハロルド

@harold:rsqrtLUTの生の出力ではない可能性があります(そう、編集したように、レイテンシが高いので多少作業が必要になる場合があります)。あるいは、単純な入力(すべてゼロの仮数)の正確な答えにつながる可能性があります。または、仮数部がすべてゼロの場合、調整を開始する前に LUTルックアップをスキップできます。HWディバイダーについて、これらの推測を​​除外するのに十分な知識はありません。:/
Peter Cordes

1
sqrtsd指数が奇数の2のべき乗では高速ですか?または、指数が2のべき乗だけですか?これは面白い。
fuz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.