AVX-512 イントリンシックでマスク、またはゼロマスクを使った移動。データはSIMD境界に揃っていない。
アンアラインド・マスク移動
まず、SIMD境界に揃っておらず、マスクを使った移動。
include <iostream> #include <iomanip> #include <immintrin.h> using namespace std; // print template <typename T> void printData(T a[]) { cout.setf(ios::right); for (int i = (sizeof(__m512i) / sizeof(float)) - 1; i >= 0; i--) cout << fixed << setprecision(0) << setw(3) << a[i] << ","; cout << "\b \b" << endl; } //main int main(void) { int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int b[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; const __mmask16 k = 0xaaaa; __m512i va = _mm512_loadu_epi32(a); __m512i vb = _mm512_loadu_epi32(b); __m512i c = _mm512_mask_mov_epi32(vb, k, va); printData((int*)&a); printData((int*)&b); printData((int*)&c); return 0; }
実行結果
C:\>cl /EHsc moveMaskUnaligned.cpp
C:\>moveMaskUnaligned
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11
16, 25, 14, 23, 12, 21, 10, 19, 8, 17, 6, 15, 4, 13, 2, 11
アンアラインド・ゼロマスク移動
次に、SIMD境界に揃っておらず、ゼロマスクを使った移動。
#include <iostream> #include <iomanip> #include <immintrin.h> using namespace std; // print template <typename T> void printData(T a[]) { cout.setf(ios::right); for (int i = (sizeof(__m512i) / sizeof(float)) - 1; i >= 0; i--) cout << fixed << setprecision(0) << setw(3) << a[i] << ","; cout << "\b \b" << endl; } //main int main(void) { int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; const __mmask16 k = 0xaaaa; __m512i va = _mm512_loadu_epi32(a); __m512i c = _mm512_maskz_mov_epi32(k, va); printData((int*)&a); printData((int*)&c); return 0; }
実行結果
C:\>cl /EHsc movMaskZUnaligned.cpp
C:\>movMaskZUnaligned
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
16, 0, 14, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 2, 0