在最近的高端英特尔CPU上重新排序x64 (x86-64)指令可以获得多少性能增益(如果有的话)。在时间非常紧迫的情况下,这值得去费心吗?
我还想知道是否有可能通过改变寄存器的使用/使用额外的寄存器(如果是免费的话),以便在某些奇怪的情况下允许长距离的代码移动?
发布于 2017-08-30 22:32:22
指令调度在短距离内通常不是什么大问题,因为无序执行通常是有效的。就像一些ARM内核一样,在顺序CPU上有很多更重要的事情,在使用结果的指令之前,调度负载是一件很重要的事情。
但是,它可以帮助一些人,即使是在高端x86上,这取决于限制执行吞吐量的瓶颈类型。有关ROB大小与物理寄存器数量之间的一些有趣的内容,请参见http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/,这是无序执行中的一个限制因素。软件流水线可以帮助处理长的依赖链,因为无序执行很难隐藏起来。
尽早将指令放在关键路径依赖链上可能会有所帮助,因为OOO调度通常尝试执行最早的就绪优先。(见确切地说,x86的行动计划是如何安排的?)。
现代CPU是复杂的猛兽,有时候重新排序可能会产生不同的效果,而你并不认为它会起作用。有时候,没有办法准确地猜测它为什么会产生不同的效果。不同的排序会影响解码器的前端带宽,甚至影响uop缓存中的前端带宽,因为在uop缓存中(在Intel CPU上),关于解码uop如何打包成向上到6 uop行有很多规则。例如,Intel SnB系列CPU上涉及微编码指令的循环的分支对齐
有时解释很模糊。例如,在英特尔的优化手册https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf#page=127中,他们讨论了立即覆盖零延迟-movzx结果,以便更快地释放内部资源。(我在Haswell和Skylake上尝试了这些例子,发现mov-消除实际上在这样做的时候起的作用要大得多,但是它实际上在总周期中稍微慢了一些,而不是更快。该示例旨在显示IvyBridge的好处,这可能是它的3个ALU端口上的瓶颈,但是HSW/SKL仅仅是dep链中资源冲突的瓶颈,并且似乎不需要更多的movzx指令需要一个ALU端口。)
这可能也适用于使用说明,不仅是movzx,而且可能不适用。
如果我没有用英特尔的手册作为例子的话,如果我遇到了一个真正的优化情况(对于IvyBridge),IDK就会发现这一点。uops发布与执行(融合域与未融合域)的性能计数器显示有多少mov uop被消除,但如果没有优化手册说明原因,就几乎不可能找出发生这种情况的原因。重新排序附近的独立指令,仅仅为了尝试一些东西,可以帮助调优的最后一步,但在这一点上,它是伏都教/黑魔法/猜测。
正如玛格丽特所指出的,除了简单的日程安排之外,还有理由重新排序指令。请参阅Agner雾优化与微结构指南和x86标记wiki中的其他资源来了解更多信息。
例如,将cmp/jcc和test/jcc组合在一起总是一个好主意,因为这是宏融合的结果。当您使用-march=haswell或其他工具编译时,编译器将为您执行此操作,因为这将启用-mtune=haswell。
如果它允许您避免某些mov指令或溢出/重新加载,它还可以打开其他优化机会,但这不仅仅是调度指令。
https://stackoverflow.com/questions/45967358
复制相似问题