x86 / x64 asm 中的指令重新排序 - 最新 CPU 的性能优化

Instruction reordering in x86 / x64 asm - performance optimisation with latest CPUs

在最近的高端 Intel CPU 上重新排序 x64 (x86-64) 指令可以获得多少性能提升(如果有的话)。在时间极其紧迫的情况下值得费心吗?

我还想知道通过更改寄存器使用/使用额外的寄存器(如果免费)以允许在某些奇怪的情况下进行更远距离的代码移动而获得收益的可能性?

指令调度在短距离内通常不是什么大问题,因为乱序执行通常有效。它在某些 ARM 内核等有序 CPU 上更为重要,在这些 CPU 中,在使用结果的指令之前调度加载是一件大事。

不过,它甚至可以在高端 x86 上提供一些帮助,具体取决于限制执行吞吐量的瓶颈类型。请参阅 http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ for some interesting stuff about ROB size vs. number of physical registers being a limiting factor in out-of-order execution. Software-pipelining 可以帮助处理乱序执行难以隐藏的长依赖链。

尽早将指令放在关键路径依赖链上会有所帮助,因为 OOO 调度通常会尝试先执行最旧就绪的。 (参见 )。

现代 CPU 是复杂的野兽,有时重新排序可能会有所不同,而您并不认为它很重要。有时无法准确猜测它产生影响的原因。不同的排序会影响解码器甚至 uop 缓存中的前端带宽,因为有许多关于解码的 uops 如何打包到 uop 缓存(在 Intel CPU 上)中最多 6 uop 行的规则。例如,Branch alignment for loops involving micro-coded instructions on Intel SnB-family CPUs

有时解释非常晦涩。例如,在 Intel 的优化手册 Example 3-25. Re-ordering Sequence to Improve Effectiveness of Zero-Latency MOV Instructions 中,他们讨论了立即覆盖 zero-latency-movzx 结果以更快地释放内部资源。 (我在 Haswell 和 Skylake 上尝试了示例,发现 mov-elimination 实际上在执行此操作时确实在更多时间有效,但实际上它在总周期中稍微慢了一点,而不是更快。该示例旨在展示IvyBridge 的好处,它可能在其 3 个 ALU 端口上存在瓶颈,但 HSW/SKL 仅在 dep 链中的资源冲突上成为瓶颈,并且似乎不会因为需要 ALU 端口来获取更多 movzx 指令而烦恼。)

可能这也适用于 ,而不仅仅是 movzx,但也可能不适用。

IDK 如果我 运行 进入真正的优化情况(对于 IvyBridge),如果英特尔的手册没有使用它作为示例的话。发出的微指令与执行的微指令(融合域与非融合域)的性能计数器显示消除了多少 mov 微指令,但如果没有优化手册说明原因,几乎不可能弄清楚它发生的原因。重新排序附近的独立指令只是为了尝试可以作为调整的最后一步,但在这一点上它是巫术/黑魔法/猜测。


正如玛格丽特指出的那样,除了简单的调度之外,还有其他原因需要对指令进行重新排序。请参阅 Agner Fog's optimization and microarchitecture guides, and other resources in the 标记 wiki 以了解更多信息。

例如,由于宏融合,将 cmp/jcctest/jcc 组合在一起总是一个好主意。当你用 -march=haswell 或其他东西编译时,你的编译器会为你做这件事,因为这会启用 -mtune=haswell.

如果它能让您避免一些 mov 指令或 spill/reload,它还可以打开其他优化机会,但这不仅仅是调度指令。