首页 > 解决方案 > _mm_movelh_ps 的 AVX 等效项

问题描述

因为没有_mm_movelh_ps我通常用于_mm256_shuffle_ps(a, b, 0x44)AVX 寄存器作为替代的 AVX 版本。但是,我记得在其他问题中读过,如果可能的话,应该首选没有控制整数(如_mm256_unpacklo_psor )的 swizzle 指令(出于某种我不知道的原因)。_mm_movelh_ps昨天,我突然想到,另一种选择可能是使用以下内容:

_mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(a), _mm256_castps_pd(b)));

由于演员表应该是无操作的,这是否比使用_mm256_shuffle_ps性能更好\等于\更差?

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

提前致谢

附加说明: Clang 实际上将 shuffle 优化为vunpcklpdhttps ://godbolt.org/z/9XFP8D 所以看来我的想法还不错。但是,GCC 和 ICC 会创建 shuffle 指令。

标签: c++sseintrinsicsavx

解决方案


避免立即保存 1 个字节的机器码大小;就这样。出于性能考虑,它位于列表的底部,但由于这个原因,所有其他相同的洗牌(如_mm256_unpacklo_pd使用隐式“控制”)都比直接控制字节好一点。

(但是将控制操作数放在另一个向量中,例如vpermilpscan 或vpermdrequires 通常会更糟,除非您在长时间运行的循环中遇到一些奇怪的前端瓶颈,并且可以在循环外加载 shuffle 控制。目前看来不太合理您必须在 asm 中手动编写才能非常关心代码大小/对齐方式;在 C++ 中,这仍然不是您可以真正直接控制的东西。)

由于演员表应该是无操作的,这是否比使用_mm256_shuffle_ps性能更好\等于\更差?

Ice Lake 有 2/clock vshufpsvs. 1/clockvunpcklpd,根据uops.info在真实硬件上的测试,在端口 1 或端口 5 上运行。 绝对使用_mm256_shuffle_ps. 微不足道的额外代码大小成本实际上可能对早期的 CPU 没有任何影响,并且对于 ICL 的未来利益而言可能是值得的,除非您确定端口 5 不会成为瓶颈。

Ice Lake 在端口 1 上有一个第二个 shuffle 单元,可以处理一些常见的 XMM 和通道内 YMM shuffle,包括vpshufb并且显然一些 2-input shuffle,例如vshufps. 我不知道为什么它不只是使用该控制向量解码vunpcklpd为 a vshufps,或者设法在端口 1 上运行该随机播放。我们知道随机播放硬件本身可以进行随机播放,所以我想这只是控制硬件的问题设置隐式随机播放,以某种方式将操作码映射到随机播放控件。

除此之外,它在较旧的 AVX CPU 上是相同或更好的;没有 CPU 会因为在其他 PS 指令之间使用 PD shuffle 而受到惩罚。任何现有 CPU 的唯一不同是代码大小。像 K8 和 Core 2 这样的旧 CPU的随机播放速度pd比. ps此外,AVX 非破坏性指令的级别差异必须是目标操作数。


正如您从 Godbolt 链接中看到的那样,在随机播放之前/之后有零个额外指令。“cast”内在函数没有进行转换,只是重新解释以保持 C++ 类型系统满意,因为英特尔决定为__m256vs. __m256d(vs. __m256i) 提供单独的类型,而不是使用一种通用的 YMM 类型。不过,他们选择不像ARM 那样使用单独的向量uint8x16uint32x4仅用于整数 SIMD __m256i

所以编译器不需要为强制转换发出额外的指令,在实践中确实如此;他们不会引入额外的vmovaps/apd注册副本或类似的东西。


如果您使用的是 clang,您可以方便地编写它并让 clang 的 shuffle 优化器vunpcklpd为您发出。或者在其他情况下,无论如何都要做任何事情;有时它会做出比来源更糟糕的选择,但通常它做得很好。

Clang 弄错了,即使你写了-march=icelake-client仍然使用。(或者根据周围的代码,可能会将洗牌优化为其他东西的一部分。)vunpcklpd_mm256_shuffle_ps

相关的错误报告


推荐阅读