2个AVX-512向量元素的交错合并-C本征

问题描述

我想将2个AVX-512向量的元素合并到其他两个向量中,并且时钟周期数最少。

具体问题如下:

// inputs
__m512i a = {a0,a1,...,a31}; // 32x 16-bit int16_t integers
__m512i b = {b0,b1,b31}; // 32x 16-bit int16_t integers

// desired output
__m512i A = {a0,b0,a15,b15};
__m512i B = {a16,b16,a17,b17,a31,b31};

天真的方法是将向量(a和b)复制到内存中,并通过如下所示的直接索引创建向量(A和B):

union U512i {
    __m512i vec;
    alignas(64) int16_t vals[32];
};

U512i ta = { a };
U512i tb = { b }

U512i A = _mm512_set_epi16( tb.vals[15],ta.vals[15],... tb.vals[0],ta.vals[0] );
U512i B = _mm512_set_epi16( tb.vals[31],ta.vals[31],... tb.vals[16],ta.vals[16] );

我还需要进行类似的合并,但步幅不同,例如:

// inputs
__m512i a = {a0,a14,b14,a30,b30,b31};

最适合解决此问题的AVX-512内部函数是什么?由于我是AVX-512内在函数的新手,因此请多加解释。

谢谢您的帮助!

解决方法

由于上面提到的评论,解决此问题的一种方法是使用# Python 3.8.5 from pathlib import Path _home = Path("~") _application_dir = Path("application") _data_dir = Path("data") def do_path_stuff(_home,_application_dir,_data_dir) -> Path: _complete_path: Path = _home.joinpath(_application_dir) _complete_path: Path = _complete_path.joinpath(_data_dir) _complete_path: Path = _complete_path.expanduser() return _complete_path p = do_path_stuff(_home,_data_dir) print(p) 或固有的vpermt2w

在Skylake-avx512和Ice Lake CPU(https://uops.info/)上,_mm512_mask_permutex2var_epi16解码为3 oups(其中2只能在端口5上运行)。总体而言,它具有7个周期的延迟,每2个周期1个吞吐量。

使用vpermt2w的优化代码如下:

vpermt2w

此处显示了幼稚的方法以供参考,但是对于不是编译时常量的输入向量,它会使用GCC效率很低地编译

#include <immintrin.h>
#include <inttypes.h>

void foo(__m512i a,__m512i b) {

    __m512i A,B;
    __m512i idx1 = _mm512_set_epi16( 47,15,46,14,45,13,44,12,43,11,42,10,41,9,40,8,39,7,38,6,37,5,36,4,35,3,34,2,33,1,32,0 );
    __m512i idx2 = _mm512_set_epi16(
        47 + 16,15 + 16,46 + 16,14 + 16,45 + 16,13 + 16,44 + 16,12 + 16,43 + 16,11 + 16,42 + 16,10 + 16,41 + 16,9 + 16,40 + 16,8 + 16,39 + 16,7 + 16,38 + 16,6 + 16,37 + 16,5 + 16,36 + 16,4 + 16,35 + 16,3 + 16,34 + 16,2 + 16,33 + 16,1 + 16,32 + 16,0 + 16 );

    A = _mm512_mask_permutex2var_epi16( a,0xFFFFFFFF,idx1,b );
    B = _mm512_mask_permutex2var_epi16( a,idx2,b );
}