将 256 位 AVX 向量存储为无符号长整数的最佳方法

Best way to store 256 bit AVX vectors into unsigned long integers

我想知道将 256 位长的 AVX 向量存储为 4 个 64 位无符号长整数的最佳方法是什么。根据网站上写的功能 https://software.intel.com/sites/landingpage/IntrinsicsGuide/ 我只能弄清楚使用maskstore(代码如下)来做到这一点。但这是最好的方法吗?或者还有其他方法吗?

#include <immintrin.h>
#include <stdio.h>

int main() {

    unsigned long long int i,j;
    unsigned long long int bit[32][4];//256 bit random numbers
    unsigned long long int bit_out[32][4];//256 bit random numbers for test

    for(i=0;i<32;i++){ //load with 64 bit random integers
        for(j=0;j<4;j++){
            bit[i][j]=rand();
            bit[i][j]=bit[i][j]<<32 | rand();
        }
    }

//--------------------load masking-------------------------
    __m256i v_bit[32];
    __m256i mask;
    unsigned long long int mask_ar[4];
    mask_ar[0]=~(0UL);mask_ar[1]=~(0UL);mask_ar[2]=~(0UL);mask_ar[3]=~(0UL);
    mask = _mm256_loadu_si256 ((__m256i const *)mask_ar);
//--------------------load masking ends-------------------------

//--------------------------load the vectors-------------------
    for(i=0;i<32;i++){

        v_bit[i]=_mm256_loadu_si256 ((__m256i const *)bit[i]);

    }
//--------------------------load the vectors ends-------------------

//--------------------------extract from the vectors-------------------
    for(i=0;i<32;i++){

        _mm256_maskstore_epi64 (bit_out[i], mask, v_bit[i]);
    }
//--------------------------extract from the vectors end-------------------

    for(i=0;i<32;i++){ //load with 64 bit random integers
        for(j=0;j<4;j++){
            if(bit[i][j]!=bit_out[i][j])
                printf("----ERROR----\n");
        }
    }

  return 0;
}

正如评论中其他人所说,在这种情况下您不需要使用掩码存储。以下循环在您的程序中没有错误

for(i=0;i<32;i++){
   _mm256_storeu_si256 ((__m256i const *) bit_out[i], v_bit[i]);

}

因此,您正在寻找的最佳指令是 _mm256_storeu_si256 此指令将 __m256i 向量存储到未对齐的地址,如果您的数据已对齐,您可以使用 _mm256_store_si256。要查看您的向量值,您可以使用此函数:

#include <stdalign.h>
alignas(32) unsigned long long int tempu64[4];
void printVecu64(__m256i vec)
{
    _mm256_store_si256((__m256i *)&tempu64[0], vec);
    printf("[0]= %u, [1]=%u, [2]=%u, [3]=%u \n\n", tempu64[0],tempu64[1],tempu64[2],tempu64[3]) ;

}

_mm256_maskstore_epi64 让您选择要存储到内存中的元素。当您想要存储具有更多选项的向量以将元素存储到内存或不更改内存值时,此指令很有用。

我正在阅读 Intel 64 和 IA-32 架构优化参考手册 (248966-032),2016 年,第 410 页。 有趣地发现未对齐的存储仍然是性能杀手。

11.6.3 Prefer Aligned Stores Over Aligned Loads

There are cases where it is possible to align only a subset of the processed data buffers. In these cases, aligning data buffers used for store operations usually yields better performance than aligning data buffers used for load operations. Unaligned stores are likely to cause greater performance degradation than unaligned loads, since there is a very high penalty on stores to a split cache-line that crosses pages. This penalty is estimated at 150 cycles. Loads that cross a page boundary are executed at retirement. In Example 11-12, unaligned store address can affect SAXPY performance for 3 unaligned addresses to about one quarter of the aligned case.

我在这里分享是因为有些人说 aligned/unaligned store 除了在调试方面没有区别!