AVXの場合は256ビット長のベクトルレジスタ2つに入ったデータを、
合わせてシフトする命令はありません。
そこでshuffle命令を使います。_mm256_shuffle_psです。
shuffle命令を使うと、2つの256ビット長レジスタから、
1つ目の上位128ビット長のどこか2か所の32ビット2つと、
2つ目の上位128ビット長のどこか2か所の32ビット2つ、
続けて1つ目の下位128ビット長の先程と同じ相対位置の32ビット2つ、
最後に2つ目の下位128ビット長のやはり先程と同じ相対位置の32ビット2つ、
これをまとめて計256ビット長の値を合成できます。
はっきりいって訳わかりません。
分かりやすく書くと、以下の処理でシフトできるわけです。
__m256 x02x03x04x05x06x07x08x09 =これを文章で書くと、
_mm256_shuffle_ps(
x04x05x06x07x08x09x10x11,
x00x01x02x03x04x05x06x07,
_MM_SHUFFLE(1, 0, 3, 2) /* = 0x4E */);
まず第2引数の下位128ビットの2番目(8~11バイト)と3番目(12~15バイト)を取り出し、
次に第1引数の下位128ビットの0番目(0~3バイト)と1番目(4~7バイト)を取り、
続けて第2引数の上位128ビットの2番目(24~27バイト)と3番目(28~31バイト)を、
最後に第1引数の上位128ビットの0番目(16~19バイト)と1番目(20~23バイト)を取って、
それを結果の256ビットにまとめる。という処理になります。
Little-endianなので下位ビットが最初のバイトになります。
同様に、今度は1番目(4バイト目)からの256ビット長の値が欲しい場合は、
__m256 x01x02x03x04x05x06x07x08 =となります。
_mm256_shuffle_ps(
x02x03x04x05x06x07x08x09,
x00x01x02x03x04x05x06x07,
_MM_SHUFFLE(2, 1, 2, 1) /* = 0x99 */);
最後に、4番目(16バイト目)からの256ビット長の値が欲しい場合は、
__m256 x04x05x06x07x08x09x10x11 =となります。_mm256_permute2f128_psを使います。
_mm256_permute2f128_ps(
x08x09x10x11x12x13x14x15,
x00x01x02x03x04x05x06x07,
3);
ここら辺は、面倒臭いので呪文のように覚えるのが吉ですね。
0 件のコメント:
コメントを投稿