2016-11-16 8 views
7

?これまで私はスタックを一時的に使用していました。たとえば、ベストな方法は、/ XMMから/ YMM登録する登録するSIMDレジスタから/に登録する目的を生成するロードとストアするための方法が最適です何

mov [rsp + 0x00], r8 
mov [rsp + 0x08], r9 
mov [rsp + 0x10], r10 
mov [rsp + 0x18], r11 
vmovdqa ymm0, [rsp] ; stack is properly aligned first. 

5つのオペランドを持つ命令を意味するので、これを直接(または他の方向)行うことはできません。しかし、上記のコードは私にとって愚かなようです。それを行うより良い方法はありますか?私は1つの選択肢について考えることができ、pinsrdとそれに関連する説明を使用します。しかしそれはそれほど良いとは思わない。

動機は、いつか汎用レジスタと他人ながらAVX2にいくつかのことを行うために高速である、ということです。例えば、小さなコードの中には、64ビットの符号なし整数が4つあり、BMI2の2つのmulxが4つ、xorが4つ必要です。 xorvpxorとする方が速くなりますが、mulxにはAVX2相当品がありません。 vpxor対4 xorのゲインのパフォーマンスは、パッキングとアンパックのプロセスによって失われます。

答えて

5

は、あなたのボトルネックの待ち時間、スループット、または融合されたドメインのuopですか?待ち時間の場合は、狭い店舗から広い荷物への店舗運送停止のため、店舗/リロードは恐ろしいことです。スループットと融合したドメインのuopについては

、それは恐ろしいではありません:ちょうど5融合したドメインのuop、ストアポート上のボトルネック。周囲のコードがほとんどALU uopsであれば、それは検討する価値があります。あなたが提案するユースケースについては


整数とベクトルREGSの間でデータを移動する手順/のuopの多くを過ごす通常は悪い考えです。 PMULUDQは32ビットのmulxに相当しますが、AVX2では64ビットの乗算は直接利用できません。 (AVX512にはそれがあります)。

あなたはPMULUDQと通常の拡張精度の技術を使用して、64ビットのベクトル乗算を行うことができます。私の答えはFastest way to multiply an array of int64_t?で、AVX2 256bベクトルでは64×64 => 64b乗算のベクトル化には値するが、128bベクトルでは不可能であることがわかった。しかし、それはメモリ内のデータであり、ベクトルregで開始して終了するデータではありませんでした。この場合

は、それが 複数の32×32 => 64ビットのベクトル乗算のうち、64×64 => 128Bフル乗算を構築する価値があるかもしれないが、それはそれだけでそれだけの価値はありませんので、多くの命令がかかる場合があります。上半分の結果が必要な場合は、スカラーに展開する(またはスカラー全体を行う)方が良いかもしれません。

整数XORは、優れたILP(クロック当たりのレイテンシ= 1、スループット= 4)を用いて、非常に安価です。あなたがそこで行うことに他にベクトルフレンドリーなことがなければ、ベクトルデータをXORに移動する価値はありません。パフォーマンスリンクについては、tag wikiを参照してください。


おそらくレイテンシーのための最良の方法は次のとおりです。

vmovq xmm0, r8 
vmovq xmm1, r10   # 1uop for p5 (SKL), 1c latency 
vpinsrq xmm0, r9, 1   # 2uops for p5 (SKL), 3c latency 
vpinsrq xmm1, r11, 1 
vinserti128 ymm0, ymm0, ymm1, 1 # 1uop for p5 (SKL), 3c latency 

合計:ほぼすべてのバックツーバック、それらを実行するのに十分なILPとP5のための7つのμop、。おそらくr8はおそらくr10よりも1サイクルまたは2サイクル早く準備ができているので、あまり失うことはありません。また


検討する価値:あなたはr8..r11を生成するためにやっていたものは何でも、あなたのデータは、XMMのregsはすでにあるので、ベクトル整数命令でそれを行います。それでも、2倍のPUNPCKLQDQとVINSERTI128を使用して、それらを一緒にシャッフルする必要があります。

+0

詳細な回答ありがとうございます。 'xor'はおそらく貧弱な例です。事実、「mulx」を除くすべてがAVX2で実行できるということです。しかし、ロード/ストアのコストを正当化するには十分ではありません。また、YMMからr/64へのロードには、シャッフル/置換、またはpextrqなどが必要です。複数のブロック(YMM)を1つのループ反復で処理することで、レイテンシの一部を隠すことができます。私は実験して自分のために見つける必要があると思う。 –

+0

@YanZhou:ストア転送が完全にオーバーラップ負荷を狭くするように整列ワイドストアから動作するため、ストア/リロードとYMM->整数は、他の方向よりもはるかに低いレイテンシです。また、負荷はストアのスループットが2倍になります。必要なベクトル作業があれば、スカラーに抽出することは価値がある可能性があります。 –

+0

@YanZhouを:ああ、私はちょうど32ビットのベクトル乗算のうち、乗算、64ビットのベクトルを構築することは、実際にスカラーとバックに行くよりも効率的であるかもしれないことを思い出しました。効率的な64×64 => 64ビットのベクトル乗算のための[この質問に私の答え](http://stackoverflow.com/questions/37296289/fastest-way-to-multiply-an-array-of-int64-t)を参照してください。 。 64 x 64 => 128bitベクトル乗算の場合、上半分の結果が必要な場合は、余分な指示が必要です。 (私はどれくらいの仕事があるのか​​忘れている、多分多すぎるかもしれない) –

関連する問題