C++ AVX等价物,用于移动

C++ AVX等价物,用于移动,c++,sse,intrinsics,avx,C++,Sse,Intrinsics,Avx,由于没有AVX版本的\u-mm\u-movelh\u-ps我通常使用\u-mm256\u-shuffle\u-ps(a、b、0x44)替换AVX寄存器。然而,我记得在其他问题中读到过,如果可能的话(出于某种原因我不知道),最好是不带控制整数的swizzle指令(如\u mm256\u unclo\u ps或\u mm\u movelh\u ps)。昨天,我突然想到,另一种选择可能是使用以下方法: \u mm256\u castpd\u ps(\u mm256\u unplo\u pd(\u mm

由于没有AVX版本的
\u-mm\u-movelh\u-ps
我通常使用
\u-mm256\u-shuffle\u-ps(a、b、0x44)
替换AVX寄存器。然而,我记得在其他问题中读到过,如果可能的话(出于某种原因我不知道),最好是不带控制整数的swizzle指令(如
\u mm256\u unclo\u ps
\u mm\u movelh\u ps
)。昨天,我突然想到,另一种选择可能是使用以下方法:

\u mm256\u castpd\u ps(\u mm256\u unplo\u pd(\u mm256\u castps\u pd(a),\u mm256\u castps\u pd(b));
既然强制转换应该是无操作的,那么在性能方面,这是否比使用
\u mm256\u shuffle\u ps
更好\相等\更差

此外,如果情况确实如此,如果有人能用简单的话解释一下(我对汇编和微体系结构的理解非常有限)为什么人们更喜欢没有控制整数的指令,那就太好了

提前谢谢

附加说明: Clang实际上将洗牌优化为
vunpcklpd

看来我的想法还不错。但是,GCC和ICC会创建一条随机指令。

避免立即执行会节省1字节的机器码大小;这就是全部。出于性能考虑,它位于列表的底部,但由于这个原因,所有其他相同的洗牌,如带有隐式“控制”的
\u mm256\u unplo\u pd
,都比立即控制字节稍微好一点

(但是在另一个向量(如
vpermilps
can或
vpermd
requires)中获取控制操作数通常更糟糕,除非您在长时间运行的循环中遇到了一些奇怪的前端瓶颈,并且可以在循环外加载shuffle控件。这不是很合理,此时您必须在asm中手工编写才能完成任务。)关于代码大小/对齐的很多;在C++中,这不是你可以直接控制的东西。 既然强制转换应该是无操作的,那么在性能方面,这是否比使用
\u mm256\u shuffle\u ps
更好\相等\更差

冰湖有2个/时钟
vshufps
和1个/时钟
vunpcklpd
,根据在实际硬件上的测试,运行在端口1或端口5上。肯定使用
\u mm256\u shuffle\u ps
。在早期的CPU上,微不足道的额外代码大小成本可能根本不会带来任何伤害,而且可能是值得的对于ICL的未来好处,除非您确定端口5不会成为瓶颈

Ice Lake在端口1上有一个第二个洗牌单元,可以处理一些常见的XMM和车道内的YMM洗牌,包括
vpshufb
,显然还有一些像
vshufps
这样的2输入洗牌。我不知道为什么它不使用该控制向量将
vunpcklpd
解码为
vshufps
,或者以其他方式运行该程序端口1上的huffle。我们知道shuffle硬件本身可以执行shuffle,所以我想设置隐式shuffle只是控制硬件的问题,以某种方式将操作码映射到shuffle控件

除此之外,它在旧的AVX CPU上是相同或更好的;没有任何CPU会因为在其他PS指令之间使用PD洗牌而受到惩罚。任何现有CPU上唯一的不同是代码大小。像K8和Core 2这样的旧CPU具有比
PS
更快的
PD
洗牌,但没有任何带有AVX的CPU具有这种弱点的洗牌单元。此外,AVX非破坏性指令之间的级别差异,操作数必须是目标


从GoDebug链接中可以看出,在洗牌之前/之后,没有额外的指令。“Casic”本质不做转换,只是重新解释以保持C++类型系统的幸福,因为英特尔决定有不同的类型:<代码>·y250/<代码> vs.代码> y.M256d(vs.代码>M256i < /代码>),而不是有一个通用的YMM类型。他们选择不象ARM那样有单独的

uint8x16
vs

因此,编译器不需要为强制转换发出额外的指令,实际上这是正确的;它们不引入额外的
vmovaps
/
apd
注册副本或类似的内容


如果您使用的是clang,您可以方便地编写它,让clang的shuffle optimizer为您发出
vunpcklpd
。或者在其他情况下,不管它要做什么,都要做;有时它会做出比源代码更糟糕的选择,通常它做得很好

Clang在
-march=icelake client
中犯了这个错误,即使您编写
\u mm256\u shuffle\u ps
(或者根据周围的代码,可能会将该shuffle优化为其他内容的一部分)


如果可能的话,最好选择[Shuffle without immediate control byes]听起来像我写的:P@PeterCordes:谢谢你的回答(如下)。我觉得我应该在将来直接向你提出我的问题。:DHeh,我可能仍然会回答它,如果它对未来的读者有用的话。顺便说一句,请注意我在你接受后刚刚做的更新。@PeterCordes看到了更新。有趣的是,即使是对于
-march=icelake clien,Clang也做了这种糟糕的优化t
。你认为一个人应该提交一份bug报告来引起他们的注意吗?是的,应该得到报告。至少对于icelake,应该改为更喜欢
vshufps
,可能对于generic也是如此。好的,我会处理好的(今天或明天)并在问题中发布链接。建议对该答案进行编辑或发表评论,将是LLVM错误报告链接的更好位置。感谢您花时间这么做。顺便说一句,您可能希望在您的LLVM missed optimization bug中链接该答案,或至少链接uops.info搜索结果。@chtz:我在后面的回答中提到过这一点;CorE2和K8在使用64位块时具有更快的洗牌速度。Conro