c++ - _mm_moveh_ps 的 AVX 等效项

标签 c++ sse intrinsics avx

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

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

由于强制转换应该是无操作的,因此就性能而言,这比使用 _mm256_shuffle_ps 更好\等于\更差吗?

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

提前致谢

附加说明: Clang 实际上将 shuffle 优化为 vunpcklpd:https://godbolt.org/z/9XFP8D 如此看来,我的想法还不算太糟糕。然而,GCC 和 ICC 创建了 shuffle 指令。

最佳答案

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

(但是在另一个 vector 中获取控制操作数,例如 vpermilps can 或 vpermd require 通常更糟糕,除非您在长时间运行中遇到一些奇怪的前端瓶颈循环,并且可以在循环外加载 shuffle 控制。不太合理,此时您必须在 asm 中手动编写才能关心代码大小/对齐;在 C++ 中,这仍然不是您真正可以做到的直接控制。)

Since the casts are supposed to be no-ops, is this better\equal\worse than using _mm256_shuffle_ps regarding performance?

根据 uops.info 的测试,Ice Lake 的速度为 2/时钟 vshufps 与 1/时钟 vunpcklpd在真实硬件上,在端口 1 或端口 5 上运行。一定使用_mm256_shuffle_ps。在早期的 CPU 上,微不足道的额外代码大小成本实际上可能根本不会造成任何损害,而且为了 ICL 的 future 利益,可能是值得的,除非您确定端口 5 不会成为瓶颈。

Ice Lake 在端口 1 上有一个第二个洗牌单元,可以处理一些常见的 XMM 和 channel 内 YMM 洗牌,包括 vpshufb 以及一些 2 输入洗牌,例如 vshufps。我不知道为什么它不只是使用该控制 vector 将 vunpcklpd 解码为 vshufps,或者设法在端口 1 上运行该 shuffle。我们知道 shuffle 硬件它本身可以进行洗牌,所以我想这只是控制硬件设置隐式洗牌的问题,以某种方式将操作码映射到洗牌控制。

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

<小时/>

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

所以编译器不需要为强制转换发出额外的指令,实际上这是事实;他们不会引入额外的 vmovaps/apd 寄存器拷贝或类似的东西。

<小时/>

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

Clang 在使用 -march=icelake-client 时出现此错误,即使您编写 _mm256_shuffle_ps,仍然使用 vunpcklpd。 (或者根据周围的代码,可能会将洗牌优化为其他内容的一部分。)

Related bug report .

关于c++ - _mm_moveh_ps 的 AVX 等效项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58954801/

相关文章:

c++ - 修改 Qt 库

c++ - 从 HCURSOR 获取游标类型

具有多种功能的 C++ SSE 优化

c++ - 可以通过使用输入寄存器来寻址输出 SIMD 寄存器

c++ - 我是否违反了严格的别名规则?

c++ - 使用 SSE 的矩阵 vector 和矩阵矩阵乘法

c++ - 收到的套接字客户端-服务器字符串是中文字符

memory - 非临时指令如何工作?

simd - 使用 ARM-v8 Neon SIMD 将 ascii 字符串打包成 7 位二进制 blob

c++ - 多次同时调用 uv_write 有时不起作用