gpt4 book ai didi

assembly - 混合使用 pxor 和 xorps 会影响性能吗?

转载 作者:行者123 更新时间:2023-12-02 20:16:27 28 4
gpt4 key购买 nike

我遇到了一个 fast CRC computation using PCLMULQDQ implementation .
我明白了,那些家伙混了 pxorxorps指令很像下面的片段:

movdqa  xmm10, [rk9]
movdqa xmm8, xmm0
pclmulqdq xmm0, xmm10, 0x11
pclmulqdq xmm8, xmm10, 0x0
pxor xmm7, xmm8
xorps xmm7, xmm0

movdqa xmm10, [rk11]
movdqa xmm8, xmm1
pclmulqdq xmm1, xmm10, 0x11
pclmulqdq xmm8, xmm10, 0x0
pxor xmm7, xmm8
xorps xmm7, xmm1

这有什么实际原因吗?性能提升?如果是,那么这背后是什么?或者这只是一种编码风格,为了好玩?

最佳答案

TL:DR:对于这个特定的代码序列,看起来可能是一些特定于微架构的调整。没有什么“一般推荐”可以帮助其他情况。

进一步考虑,我认为@Iwillnotexist Idonotexist 的理论最有可能:这是由认为这可能会有所帮助的非专家撰写的。寄存器分配是一个重要线索:通过选择低 8 位中所有重复使用的寄存器,可以避免许多 REX 前缀。

XORPS 在某些 Intel CPU(Nehalem 及更高版本)上的“ float ”域中运行,而 PXOR 始终在“ivec”域中运行。

由于将每个 ALU 输出连接到每个 ALU 输入以直接转发结果会很昂贵,因此 CPU 设计人员将它们分解为多个域。 (转发节省了写回寄存器文件和重新读取的延迟)。跨域可能需要额外 1 个周期的延迟(英特尔 SnB 系列)或 2 个周期(Nehalem)。

进一步阅读:我在 What's the difference between logical SSE intrinsics? 上的回答

我想到了两个理论:

  • 写这篇文章的人认为 PXOR 和 XORPS 会提供更多的并行性,因为它们不会相互竞争。 (这是错误的:PXOR 可以在所有矢量 ALU 端口上运行,但 XORPS 不能)。
  • 这是一些非常巧妙地调整的代码,它故意创建旁路延迟,以避免可能延迟下一个 PCLMULQDQ 执行的资源冲突。 (或者如 EOF 所建议的,代码大小/对齐可能与它有关)。

  • 代码上的版权声明写着“2011-2015 Intel”,因此值得考虑它对某些最近的 Intel CPU 有一定帮助的可能性,而不仅仅是基于对 Intel CPU 工作方式的误解。 Nehalem 是第一个完全包含 PCLMULQDQ 的 CPU,这是 Intel,因此如果有任何调整,它会在 AMD CPU 上表现不佳。代码历史不在 git repo 中,只有添加当前版本的 5 月 6 日提交。

    Intel whitepaper (from Dec 2009)它仅基于使用的 PXOR,而不是 XORPS,在其 2x pclmul/2x xor 块的版本中。

    Agner Fog 的表格甚至没有显示 Nehalem 上 PCLMULQDQ 的大量 uops,或者它们需要哪些端口。它是 12c 延迟,每 8c 吞吐量一个,因此它可能类似于 Sandy/Ivybridge 的 18 uop 实现。 Haswell 使它成为令人印象深刻的 3 uop (2p0 p5),而它在 Broadwell (p0) 和 Skylake (p5) 上仅以 1 uop 运行。

    XORPS 只能在端口 5 上运行(直到 Skylake 也可以在所有三个矢量 ALU 端口上运行)。当 Nehalem 的输入之一来自 PXOR 时,它具有 2c 旁路延迟。在 SnB 系列 CPU 上,Agner Fog 说:

    In some cases, there is no bypass delay when using the wrong type of shuffle or Boolean instruction.



    所以我认为从 PXOR 转发实际上没有额外的旁路延迟 -> SnB 上的 XORPS,所以唯一的影响是它只能在端口 5 上运行。 在 Nehalem 上,它实际上可能会将 XORPS 延迟到 PSHUFB 完成之后。

    在主展开循环中,XOR 之后有一个 PSHUFB,用于设置下一个 PCLMUL 的输入。 SnB/IvB 可以在 p1/p5 上运行整数洗牌(不像 Haswell 和后来在 p5 上只有一个洗牌单元。但对于 AVX2,它是 256b 宽)。

    由于竞争为下一个 PCLMUL 设置输入所需的端口似乎没有用, 我最好的猜测是代码大小/对齐 如果在调整 SnB 时进行了此更改。

    在 PCLMULQDQ 超过 4 uops 的 CPU 上,它是微编码的 .这意味着每个 PCLMULQDQ 需要一个完整的 uop 缓存线。由于只有 3 个 uop 缓存线可以映射到同一个 32B 的 x86 指令块,这意味着大部分代码根本不适合 SnB/IvB 上的 uop 缓存。 uop 缓存的每一行只能缓存连续的指令。来自英特尔的优化手册:

    All micro-ops in a Way (uop cache line) represent instructions which are statically contiguous in the code and have their EIPs within the same aligned 32-byte region.



    这听起来与在循环中使用整数 DIV 非常相似:
    Branch alignment for loops involving micro-coded instructions on Intel SnB-family CPUs .右对齐, you can get it to run out of the uop cache (the DSB in Intel performance counter terminology) . @Iwillnotexist Idonotexist 在 Haswell CPU 上做了一些有用的微编码指令测试,表明它们阻止从环回缓冲区运行。 (英特尔术语中的 LSD)。

    在 Haswell 和更高版本上,PCLMULQDQ 不是微编码的,因此它可以与之前或之后的其他指令一起进入同一 uop 缓存行。

    对于以前的 CPU,可能值得尝试调整代码以在更少的地方破坏 uop 缓存。 OTOH,在 uop 缓存和传统解码器之间切换可能比总是从解码器运行更糟糕。

    如果这么大的展开真的很有帮助,那么 IDK 也是如此。 SnB 和 Skylake 之间的差异可能很大,因为管道的微编码指令非常不同,而且 SKL 甚至可能不会成为 PCLMUL 吞吐量的瓶颈。

    关于assembly - 混合使用 pxor 和 xorps 会影响性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39811577/

    28 4 0
    文章推荐: selenium - 如何设置 IE 浏览器在 Headless 模式下运行的能力
    文章推荐: gitlab-ci - gitlab ci缓存没有匹配的文件
    文章推荐: angularjs - 如何使用 Angular 1.2.0 - rc2 在
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com