内容简介:3.4.2.4. 优化循环流检测器(LSD)在Intel Core微架构中,满足以下准则的循环由LSD检测,并从指令队列重播(replay)来供给解码器。在Intel微架构Nehalem中,这样改进循环流寄存器:
3.4.2.4. 优化循环流检测器(LSD)
在Intel Core微架构中,满足以下准则的循环由LSD检测,并从指令队列重播(replay)来供给解码器。
- 必须不超过4个16字节的取指。
- 必须不超过18条指令。
- 可以包含不超过4被采用的分支,并且它们不能是RET。
- 通常应该具有超过64个迭代。
在Intel微架构Nehalem中,这样改进循环流寄存器:
- 在指令已解码队列(IDQ,参考2.5.2节)中缓冲已解码微操作来供给重命名/分配阶段。
- LSD的大小被增加到28个微操作。
在Sandy Bridge与Haswell微架构中,LSD与微操作队列实现持续改进。它们具有如下特性:
表3-2. 由Sandy Bridge与Haswell微架构检测的小循环准则
Sandy Bridge 与Ivy Bridge 微架构 |
Haswell 微架构 |
最多8个32指令字节块的取指 |
如果启用HTT,8块取指,如果关闭HTT,11块取指 |
最多28个微操作 |
如果启用HTT,28个微操作,如果关闭HTT,56个微操作 |
所有微操作位于已解码ICache(即DSB),但不来自MSROM |
所有微操作位于DSB,包括来自MSROM的微操作 |
不超过8个被采用分支 |
不固定 |
不包括CALL与RET |
不包括CALL与RET |
不匹配的栈操作不适用 |
同左 |
许多计算密集循环,搜索以及字符串移动符合这些特征。这些循环超出了BPU预测能力,总是导致一个分支误预测。
Assembly/Compiler 编程规则23. (影响MH ,普遍性MH ) 将一个循环长的指令序列分解为不超过LSD 大小的短指令块的循环。
Assembly/Compiler 编程规则24. (影响MH ,普遍性M ) 如果展开后的块超过LSD 的大小,避免展开包含LCP 暂停的循环。
3.4.2.5. 在Intel® Sandy Bridge中利用LSD微操作发布带宽
LSD持有构成小的“无限”循环的微操作。来自LSD的微操作在乱序引擎中分配。在LSD中的循环以一个回到循环开头的被采用分支结束。在循环末尾的被采用分支总是在该周期中最后分配的微操作。在循环开头的指令总是在下一个周期分配。如果代码性能受限于前端带宽,未使用的分配槽造成分配中的一个空泡,并导致性能下降。
在Intel微架构Sandy Bridge中,分配带宽是每周期4个微操作。当LSD中的微操作数导致最少未使用分配槽时,性能是最好的。你可以使用循环展开来控制在LSD中的微操作数。
在例子3-17里,代码对所有的数组元素求和。原始的代码每次迭代加一个元素。每次迭代有3个微操作,都在一个周期中分配。代码的吞吐率是每周期一个读。
在展开循环一次时,每次迭代有5个微操作,它们在2个周期中分配。代码的吞吐率仍然是每周期一个读。因此没有性能提高。
在展开循环两次时,每次迭代有7个微操作,仍然在2个周期中分配。因为在每个周期中可以执行两个读,这个代码具有每两个周期3个读操作的潜在吞吐率。
例子 3-17. 在 LSD 中展开循环优化发布带宽
没有展开 |
展开一次 |
展开两次 |
lp: add eax, [rsi + 4* rcx] dec rcx jnz lp |
lp: add eax, [rsi + 4* rcx] add eax, [rsi + 4* rcx +4] add rcx, -2 jnz lp |
lp: add eax, [rsi + 4* rcx] add eax, [rsi + 4* rcx +4] add eax, [rsi + 4* rcx + 8] add rcx, -3 jnz lp |
3.4.2.6. 为已解码ICache优化
已解码ICache是Intel微架构Sandy Bridge的一个新特性。从已解码ICache运行代码有两个好处:
- 乱序引擎更高的微操作供给带宽。
- 前端不需要解码在已解码ICache中的代码。这节省了能源。
在已解码ICache与遗留解码流水线间切换需要开销。如果你的代码频繁地在前端与已解码ICache间切换,性能损失会超出仅从遗留流水线运行。
要确保“热”代码从已解码ICache供给:
- 确保每块热代码少于500条指令。特别地,在一个循环中不要展开超过500条指令。这应该会激活已解码ICache存留,即使启用了超线程。
- 对于在一个循环中有非常大块计算的应用程序,考虑循环分裂(loop-fission):将循环分裂为合适已解码ICache的多个循环,而不是会溢出单个循环。
- 如果一个应用程序可以确定每核仅运行一个线程,它可以将热代码块大小增加到大约1000条指令。
稠密读- 修改- 写代码(dense read-modify-write code )
已解码ICache对每32字节对齐内存块仅可以保持最多18个微操作。因此,以少量字节编码,但有许多微操作的指令高度集中的代码,可能超过18个微操作的限制,不能进入已解码ICache。读-修改-写(RMW)指令是这样指令的一个良好例子。
RMW指令接受一个内存源操作数,一个寄存器源操作数,并使用内存源操作数作为目标。相同的功能可以两到三条指令实现:第一条读内存源操作数,第二条使用第二个寄存器源操作数执行该操作,最后的指令将结果写回内存。这些指令通常导致相同数量的微操作,但使用更多的字节来编码相同的功能。
一个可以广泛使用RMW指令的情形是当编译器进取地优化代码大小时。
下面是将热代码放入已解码ICache的某些可能解决方案:
- 以2到3条功能相同的指令替换RMW指令。例如,“adc [rdi], rcx”只有3字节长;等效的序列“adc rax, [rdi]”+“mov [rdi], rax”是6个字节。
- 对齐代码,使稠密部分被分开到两个32字节块。在使用一个自动对齐代码的 工具 时,这个解决方案是有用的,并且不关心代码改变。
- 通过在循环中添加多字节NOP展开代码。注意这个解决方案对执行添加了微操作。
为已解码ICache 对齐无条件分支
对于进入已解码ICache的代码,每个无条件分支是占据一个已解码ICache通道(way)的最后微操作。因此,每32字节对齐块仅3个无条件分支可以进入已解码ICache。
在跳转表与switch声明中无条件分支是频繁的。下面是这些构造的例子,以编写它们的方法,使它们可以放入已解码ICache。
编译器为C++虚拟函数或DLL分发表创建跳转表。每个无条件分支消耗5字节;因此最多7个无条件分支可与一个32字节块关联。这样,如果在每个32字节对齐块中无条件分支太稠密,跳转表可能不能放入已解码ICache。这会导致在分支表前后执行的代码的性能下降。
解决方案是在分支表的分支中添加多个字节NOP指令。这可能会增加代码大小,小心使用。不过,这些NOP不会执行,因此在后面的流水线阶段中不会有性能损失。
Switch-case构造代表了一个类似的情形。一个case条件的求值导致一个无条件分支。在放入一个对齐32字节块的每3条连续无条件分支上可以应用相同的多字节NOP方法。
在一个已解码ICache 通道中的两个分支
已解码ICache可以在一个通道在保持两个分支。在一个32字节对齐块中稠密的分支,或它们与其他指令的次序,可能阻止该块中指令所有的微操作进入已解码ICache。这不经常发生。当它发生时,你可以在代码合适的地方放置NOP指令。要确保这些NOP指令表示热代码的部分。
Assembly/Compiler 编程规则25. (影响M ,普遍性M ) 避免在一个栈操作序列(POP ,PUSH ,CALL ,RET )中放入对ESP 的显式引用。
3.4.2.7. 其他解码指引
Assembly/Compiler 编程规则26. (影响ML ,普遍性L ) 使用小于8 字节长度的简单指令。
Assembly/Compiler 编程规则27. (影响M ,普遍性MH ) 避免使用改变立即数及位移(displacement )大小的前缀。
长指令(超过7字节)会限制每周期解码指令数。每个前缀增加指令长度1字节,可能会限制解码器的吞吐率。另外,多前缀仅能由第一个解码器解码。这些前缀也导致了解码时的时延。如果不能避免改变立即数或位移大小多前缀或一个前缀,在因为其他原因暂停流水线的指令后调度它们。
以上所述就是小编给大家介绍的《[译]64-ia-32架构优化手册(16)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MySQL™ 参考手册(关于本手册)
- LLVM 程序员手册 —— LLVM 4.0 文档(非常非常完整的手册)
- [译]Python手册——模块
- Axure函数使用手册
- 线上故障处理手册
- OpenSSH 实践手册
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms + Data Structures = Programs
Niklaus Wirth / Prentice Hall / 1975-11-11 / GBP 84.95
It might seem completely dated with all its examples written in the now outmoded Pascal programming language (well, unless you are one of those Delphi zealot trying to resist to the Java/.NET dominanc......一起来看看 《Algorithms + Data Structures = Programs》 这本书的介绍吧!