2014年9月6日土曜日

ベクトルレジスタでの位置合わせ (_mm256_alignr_epi8)

引き続き、ベクトルレジスタ同士を結合してシフトの方法など。最後のAVX2編。

AVXでは合わせてシフト命令がなかったので、shuffle命令を使いました。
AVX2でもshuffle命令で操作可能です。

でも、AVX2にはシフト命令が追加されていますのでこれも使えます。
シフト命令は、1バイト単位でシフトできるので、使い方をしっておくと便利そうです。
なので、今回はこれを使います。_mm256_alignr_epi8命令です。

この命令はリンク先の説明の通り、なんか複雑なシフトをします。
何を計算しているかというと、もともと128ビットでやってたシフト処理を、
下位128ビット同士と上位128ビット同士で同時に計算しています。

おお、これは便利と、単純に使ってみると、
__m256 t = _mm256_alignr_epi8(s08, s00, 4);
tには、s01s02s03s08s05s06s07s12みたいなデータが入って(´・ω・`)ガッカリ…

そこで、事前準備をします。
__m256 s04 = _mm256_permute2f128_ps(s08, s00, 3);
__m256 t = _mm256_alignr_epi8(s04, s00, 4);
こうすると、tにはs01s02s03s04s05s06s07s08が入ってばっちりです。

実際に使うには、キャストが必要で、こんな感じですね。
__m256 s04 = _mm256_permute2f128_ps(s08, s00, 3);
__m256 t = _mm256_castsi256_ps(_mm256_alignr_epi8(
        _mm256_castps_si256(s04), _mm256_castps_si256(s00), 4);
また、シフト幅を増やすときは、桁溢れに気をつけてください。
s00 = s00;
s01 = _mm256_alignr_epi8(s04, s00, 4);
s02 = _mm256_alignr_epi8(s04, s00, 8);
s03 = _mm256_alignr_epi8(s04, s00, 12);
s04 = s04;
s05 = _mm256_alignr_epi8(s08, s04, 4);
s06 = ...

みたいな感じになります。

これでシフト処理のintrinsic忘備録お仕舞です。

0 件のコメント:

コメントを投稿