C 用AVX2左移(float32数组)并用零填充

C 用AVX2左移(float32数组)并用零填充,c,gcc,intrinsics,avx2,sse2,C,Gcc,Intrinsics,Avx2,Sse2,我在C代码中使用SSE2进行单精度浮点运算已经有一段时间了: static inline\uum128 SSEI\um128移位(\uuuum128数据) { 返回(数据),4; } 对于像[1.0,2.0,3.0,4.0]这样的数据,它会导致[2.0,3.0,4.0,0.0],即它左移一个位置,并用零填充数据结构。如果我没记错的话,上面的内联函数可以编译成一条指令(至少带有gcc) 我在AVX2上做同样的事情时,不知何故,我没有认真考虑。我如何以有效的方式实现这一点 类似的问题:,如果您使用

我在C代码中使用SSE2进行单精度浮点运算已经有一段时间了:

static inline\uum128 SSEI\um128移位(\uuuum128数据)
{
返回(数据),4;
}
对于像
[1.0,2.0,3.0,4.0]
这样的数据,它会导致
[2.0,3.0,4.0,0.0]
,即它左移一个位置,并用零填充数据结构。如果我没记错的话,上面的内联函数可以编译成一条指令(至少带有gcc)

我在AVX2上做同样的事情时,不知何故,我没有认真考虑。我如何以有效的方式实现这一点


类似的问题:,

如果您使用的是
gcc
,我建议尽可能使用gcc向量扩展,而不是特定于体系结构的内部函数。特别是,您可以使用
uu内置shuffle(data,(flectype){0},(ivectype){1,2,3,4})
。请注意,超过128位的AVX向量由车道组成,车道交叉指令(在直接扩展示例时不可避免)比车道内操作慢一点(大约慢3倍),因此最好检查一下您是否真的需要它。确定
gcc
将gcc向量内部函数编译到以下程序集:
vmovaps%ymm0,%ymm1 vxorps%xmm0,%xmm0,%xmm0 vperm2f128$33,%ymm0,%ymm1,%ymm0 VPALIGNER$4,%ymm1,%ymm0,%ymm0
。如果您愿意,您可以将其反向工程到intel Intrinsic中。或者,一个明智的解决方案是gcc向量内部函数。不客气。如果您想正确地执行此操作,下面是实现的一个示例。@EOF:执行此洗牌的另一种方法(最好是在循环中,您可以在循环外加载向量常量):
vpermd
使用32位元素执行车道交叉洗牌,
vpblendd
在你想要的地方加入一个
0.0
元素。@EOF:不,它没有,这就是为什么将
paign
扩展到256位时很难使用/如此糟糕的设计,以及为什么GCC需要
vperm2f128
。如果您使用的是
gcc
,请参阅中的256位图,我建议尽可能使用gcc向量扩展,而不是特定于体系结构的内部函数。特别是,您可以使用
uu内置shuffle(data,(flectype){0},(ivectype){1,2,3,4})
。请注意,超过128位的AVX向量由车道组成,车道交叉指令(在直接扩展示例时不可避免)比车道内操作慢一点(大约慢3倍),因此最好检查一下您是否真的需要它。确定
gcc
将gcc向量内部函数编译到以下程序集:
vmovaps%ymm0,%ymm1 vxorps%xmm0,%xmm0,%xmm0 vperm2f128$33,%ymm0,%ymm1,%ymm0 VPALIGNER$4,%ymm1,%ymm0,%ymm0
。如果您愿意,您可以将其反向工程到intel Intrinsic中。或者,一个明智的解决方案是gcc向量内部函数。不客气。如果您想正确地执行此操作,下面是实现的一个示例。@EOF:执行此洗牌的另一种方法(最好是在循环中,您可以在循环外加载向量常量):
vpermd
使用32位元素执行车道交叉洗牌,
vpblendd
在你想要的地方加入一个
0.0
元素。@EOF:不,它没有,这就是为什么将
paign
扩展到256位时很难使用/如此糟糕的设计,以及为什么GCC需要
vperm2f128
。请参阅中的256位图表