问题描述
我想将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 );
}