指令中的x86/x64的ASM重新排序 - 与最新的CPU性能优化
多少的性能提升,如果有的话,可以从一个最近高端的Intel CPU重新排序的x64(x86-64的)指令得到。在极度危急的情况下值得一提吗?指令中的x86/x64的ASM重新排序 - 与最新的CPU性能优化
我也想知道关于通过改变寄存器的使用取得的成果的可能性/使用附加寄存器(如果免费),以允许在某些情况下,奇较长距离的代码移动?
指令调度通常不是什么大不了的事在短距离内,因为乱序执行通常工作。对于像一些ARM内核这样的有序CPU来说,它更重要,在这些内核中,调度加载远远超过使用结果的指令,这很重要。
它可以帮助一些甚至高端的X86,不过,这取决于什么样的瓶颈制约着你的执行吞吐量。参见http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/关于ROB大小与物理寄存器数量有关的一些有趣的内容是无序执行中的限制因素。 Software-pipelining可能有助于长期依赖链,无序执行很难隐藏。关键路径依赖链
把指令早可以帮助,因为OOO调度通常试图执行最古老准备先。 (见How are x86 uops scheduled, exactly?)。
现代的CPU是复杂的野兽,有时重新排序的东西可以让你的时候就不能指望它重要的差异。有时候无法准确猜测它为什么会产生变化。不同的排序可能会影响解码器甚至uop缓存中的前端带宽,因为关于解码uops如何打包到uop缓存(在Intel CPU上)的up-to-6-uop行有很多规则。例如,Branch alignment for loops involving micro-coded instructions on Intel SnB-family CPUs
有时候的解释是非常模糊。例如,在英特尔的优化手册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指令。)
也许这也适用于eliminated mov
instructions,不只是movzx
,但它可能不会。
IDK如果如果我在真正的优化情况(对于IvyBridge)遇到如果英特尔的手册没有使用它作为例子,我会想到这一点。发布与执行的uops的性能计数器(融合域与非融合域)显示消除了多少个mov uops,但如果没有优化手册说明原因,几乎不可能找出发生这种情况的原因。重新排序附近的独立指令只是为了尝试一下,可以帮助我们作为调整的最后一步,但在那一点上,它是巫术/黑魔法/猜测。
正如玛格丽特所指出的那样,除了简单的调度之外,还有其他原因需要重新排序。请参阅Agner Fog's optimization and microarchitecture guides以及x86标记wiki中的其他资源以了解更多信息。
例如,由于宏融合,将cmp/jcc
和test/jcc
分组在一起总是一个好主意。你的编译器会在你编译-march=haswell
之类的时候为你做这个,因为那样可以启用-mtune=haswell
。
它也可以打开其他优化机会,如果它可以让你避免一些mov
指令或溢出/重新加载,但不仅仅是调度指令。
多么慷慨的答案,谢谢你的许多链接 - 你是一个明星! –
你的意思是手动重新排序代码中的指令吗?很多!考虑你可以通过重新排序来隐藏长指令的全部延迟(如果你有足够的独立数据路径)。您可以避免端口压力,做出一些宏指令的保险丝,避免失速(有很多,包括同时在同一单元中有多条指令退休)等等。如果避免向/从内存移动数据,使用附加寄存器是有用的,否则,CPU将重新命名寄存器本身(例如''eax'现在不再是'eax') –
感谢玛格丽特。我问的唯一原因是因为我不确定最新的CPU能够在内部有效产生多少动静。 –