SIMD、(ゼロ)マスク移動、アンアラインド

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