2014年6月22日日曜日

vgatherdd命令って本当に役立つの?

最近チューニングでgather intrinsicを使ってみている。

vgather命令は、配列のbaseアドレスを渡し、更にindexが入ったベクトルレジスタを渡し、 ベクトルレジスタ長分のメモリ上のデータを一個一個indexを見ながら一気に取得する命令。

これは凄い便利!!!と使ってみたのだが、あまり性能が出ない。
分岐のmiss predictionは増えるし、ロード命令数もなんか凄い増えるなと、不思議に思ってた。

そんなわけで、最近ずっと悩んでたんだけど、やっと分かった気がする。
この「一気」というのが間違いだった。

正確には、一命令で一度に取得できるのは1ベクトルロードで取得できる範囲内だけで、
離れたメモリ位置上のデータ全てを取得するには、vgather命令を複数回実行する必要があった。
内部でマイクロコードでループしてるのかなって思ってたら、実はコンパイラが1つのintrinsicを、
アセンブラレベルでループにしてぶんまわしてた。そりゃmiss prediction増えますわwww

例えばAVX512だと、32ビットのデータを扱う場合、ベクトル長は16。
なので、indexには16個の添字が入ったベクトルレジスタを渡すのだけど、
その値がバラバラだと、最悪16回ループを回ることになる。これはあかん……。

明日はgatherを使わずに取得するコード(ループアンロールされる)と、
asmを使ってvgatherを手でアンロールして16回vgatherするコードにして、
比べてみよ。

そして比べた結果、遅くなってたので、泣く泣く諦めましたw
コンパイラちゃんのintrinsicのほうが速かった。
もうちょっといいコードが作れそうなのだけど、今回は無理でした。

0 件のコメント:

コメントを投稿