Haswell の新機能はいろいろありますが、全世界から(?)切望されていたのがこの VGATHER 系命令です。
VGATHER 系命令は、SIMD レジスタの各要素をアドレス(正確にはインデックス)として対応するデスティネーションレジスタの位置にロードする命令で、マスクをかけるとその部分についてはアクセスせずデスティネーションレジスタは維持されます。残念ながら逆のことをするVSCATTERはAVX2にはありませんが、AVX-512 で追加される予定です。
32bitのインデックスで32bitの整数をロードする VPGATHERDD だと疑似コードは以下のようになります。(ymm1~3 は256bitのレジスタを32bitの8要素の配列として扱っています)
VGATHERDD ymm1, vm32y, ymm2 ^dst ^src ^mask vm32y = [r1 + ymm3 * scale + disp] ^base ^index(signed) for (i = 0; i < 8; i++) { if (ymm2[i] & (1 << 31)) ymm1[i] = MEM32[r1 + ymm3[i] * scale + disp]; else NOTHING; // not be zero-ed } ymm2 = {0}; // mask register is cleared!!
ここで、3つ出てくる SIMD レジスタはすべて異なるものでなければいけません(同じものが出てくると無効命令例外になる)。しかしなんでわざわざマスクレジスタをクリアするんですかねこれ。
ようやく追加された!と思ったら…というかHaswellが発売される前の2013年春のIDFで、HaswellのVGATHER系命令はそもそも残念性能であることがアナウンスされていたようです(ここのARCS003の「Slide Number 55」のところ)。「Will get improvement in Intel next generation CPU」って書いてありますが、Skylake ではまあ期待できるとして、Broadwell では改善されるんでしょうか。
気を取り直してIntel最適化マニュアルを見てみると、こういう時にはVGATHERを使うなと書いてあります。
- シーケンシャルなアクセス – 普通のロード(VMOV[AU]P[SD]/VMOVDQ[AU]) を使うべき
- ロードするのが4要素以下 – 普通にロードした後並び替えるべき
- 小さいストライド(インデックスの値が狭い範囲に収まっている) – 何回か普通にロードした後シャッフル等で並び替えるべき
- 位置の入れ替え – 普通にロードした後シャッフル等で並び替えるべき
- 冗長な要素(同じインデックスが複数回出てくる) – 1回VGATHERした後シャッフル等で並び替えるべき
これらは複数のインデックスの値の間の関係があらかじめ予測できる場合を意味しているような記述になっているので、そりゃ普通にロードした方が速いのはある意味当たり前です。
逆にこういう時にVGATHERを使えと書いてあります。
- 4要素以上で固定でないマスク – 固定でないマスクを普通のロードで行おうとすると、分岐予測が失敗することによる性能低下がある
- 8要素でベクタインデックス(SIMD演算した結果がそのままインデックスになる) – そもそもこれこそがVGATHERの目的とするところである
8要素未満でベクタインデックスの場合はどうなんでしょうね…(俺がやりたいのは4要素でベクタインデックスで固定ではないが偏りの大きいマスク)
具体的な速さについてはちょっとベンチマークした人がいる(w_oさんお世話になってます)のですが、このベンチマークはどちらかというと「こういう時には使うな」のケースに入る(Haswellに対応した最適化マニュアルが出る前の記事なので仕方ないんですが)ため、VGATHER ならではの使い方をした場合にどれくらい速いか(というか遅いか)は分かりません。
たぶんその2に続く。
VGATHER系命令の速さあるいは遅さ(その2)
実際に VGATHER 系命令とVGATHERと等価なことを要素ごとにバラして行うコードのベンチマークを取ってみました。 <a href=”http://umezawa.dyndns.info/archive/instbench/vgatherbench.zip”>プログラム…
Broadwell は VGATHER 系命令が速くなったらしい
8月の記事ですが、たとえばこの記事を見ると、「より高速なベクタ収集」と書いてあります。 最適化マニュアルを見てみると、”Considerations for Gather instructions” に “In the Broadwel…