SIMDの天敵として、綺麗に並んでいないデータがあります。
この問題はソフトウェアの設計、仕様とも関わる難しい問題で、一発で問題解決する銀の弾丸は無いのですが、少しでも状況を良くするために、便利そうで便利でない少し便利な命令みたいなのは定期的に追加されてる印象があります。
- 定数しかとれないalignr
- マスク作る余裕があるならpshufbのパターン作れる気がするpmaskmov
- ソフトウェア実装より遅いvpgather
そういうあったらちょっと便利な気がするけど具体例すぐ思い付かない命令ファミリー(vpgatherは確実に便利だけど…)に追加されたのが、vpexpandd, vpcompressd 等のexpand,compress 命令です。
vpexpandd は、マスクの値を使って、連続するデータを飛び飛びにしてくれる命令です。
#include <immintrin.h>
#include <stdio.h>
unsigned int in[16] = {100,101,102,103,
104,105,106,107,
108,109,110,111,
112,113,114,115
};
unsigned int out[16];
void test(__mmask16 mask)
{
for (int i=0; i<16; i++) {
out[i] = -1;
}
__m512i v = _mm512_loadu_si512(out);
v = _mm512_mask_expandloadu_epi32(v, mask, in);
_mm512_storeu_si512(out, v);
printf("0x%04x: ", mask);
for (int i=0; i<16; i++) {
printf("%3d, ", out[15-i]);
}
puts("");
}
int
main()
{
printf(" | ");
for (int i=0; i<16; i++) {
printf("%3d, ", 15-i);
}
puts("\n---------------------------------------------------------------------------------------");
test(1);
test(0xaaaa);
test(0x8888);
test(0x0303);
test(0x0462);
test(0xffff);
}
| 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
---------------------------------------------------------------------------------------
0x0001: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 100,
0xaaaa: 107, -1, 106, -1, 105, -1, 104, -1, 103, -1, 102, -1, 101, -1, 100, -1,
0x8888: 103, -1, -1, -1, 102, -1, -1, -1, 101, -1, -1, -1, 100, -1, -1, -1,
0x0303: -1, -1, -1, -1, -1, -1, 103, 102, -1, -1, -1, -1, -1, -1, 101, 100,
0x0462: -1, -1, -1, -1, -1, 103, -1, -1, -1, 102, 101, -1, -1, -1, 100, -1,
0xffff: 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100,
皆さんもこの便利な命令の使いかたを考えてみましょう!(「俺は思い付かなかった」をオブラートに包んだ表現)
一応
では、
for (j=0, i=0; j<N; j++) {
if (C[i] != 0.0) {
B[i] = A[i] * C[j++];
}
}
という例が挙げられてますね。(でもこれやるなら、いくつスキップしたか情報無いと結局マスクをpopcntしないといけない気がするんですが…)
明日は @tanakmura が vpcompressd について書きます。