Intel Sandy Bridge/Ivy Bridge架构/微架构/流水线 (7) - 流水线前端/译码后指令缓存

版权声明:转载必须保留原出处,没有书面许可不可用于商用目的, https://blog.csdn.net/qq_43401808/article/details/85997249

Decoded ICache

译码后微指令缓存本质上是对传统的译码流水线的高速缓存加速器。通过缓存微指令,可以提供如下的优势:

  • 减少由于分支预测失败导致的延迟
  • 增加发射微指令到乱序引擎的带宽
  • 降低流水线前端的能耗

译码后微指令缓存存储指令译码器生成的微指令。以后当这些微指令需要被执行时,可以直接从缓存中获取,而不再需要这些微指令的取指和译码阶段,从而节省前端的能耗,消除译码延迟。微指令缓存提供大约80%的微指令命中率;而且,对于频繁执行的“热代码”通常可以达到100%的命中率。

典型的整型程序平均每条指令略小于4字节,流水线前端的译码速度能够“跑赢”后端的消费速度,可以填充一个较大的微指令缓冲区窗口,从而让调度器发现可以并行的指令。但是对于高性能的程序,某些基本的代码块由许多指令组成,例如Intel SSE媒体算法或者重度的循环展开,每个周期译码16字节指令流可能会到导致后端发生指令饥饿(即无指令可执行)。这时候面向32字节的微指令缓存可以帮助避免指令饥饿。

如果程序运行具有时间和空间局部性,微指令缓存可以自动地提升程序性能。但是要想充分地利用微指令缓存的潜能,程序员还是需要了解一些缓存的内部组织结构。

微指令缓存由32个组(set)构成。每个组包含8路。每路可以保存最多6条微指令。故整个缓存可以保存32*8*6=1536条微指令,即上面图中显示的1.5K uop cache。

下面是微指令缓存中填充微指令的规则:

  • 每路中的所有微指令(最多6条)都必须来自于同一个静态连续的代码块,这些微指令的EIP必须位于同一个32字节对齐的区域内。
  • 最多只能有3路缓存被分配给同一个32字节对齐的代码区,即原始的IA程序中每32字节的区域中最多可以有18条微指令可以被缓存。
  • 多微指令的x86指令不能跨路保存,即x86指令对应的多条微指令不能分别保存在两路中。
  • 每路中最多保存两条分支
  • 需要使用MSROM进行译码的指令会占据整路缓存
  • 每路中的非条件分支指令必须是最后一条微指令。
  • 微熔合的微指令(load + op和store)作为一条微指令缓存
  • 宏熔合的指令作为一条微指令缓存
  • 带有64位(8字节)立即数的指令需要两个缓存槽(slot)来保存数据。(注:大概每个slot是8字节长,Intel文档未说明)

当微指令不满足以上的条件限制,无法存储在微指令缓存中时,它们只能由传统的译码流水线处理。一旦前端切换到传统的译码流水线进行译码,只能等到下一个分支指令才能切换回从微指令缓存中获取微指令。所以频繁的在“传统译码流水线”与“微指令缓存”之间切换会产生性能损失。

事实上,微指令缓存是包含在一级指令缓存和ITLB中的。即一级指令缓存中保存的x86指令与微指令缓存中的微指令对应存在。一级指令缓存中的缓存行被决出(evicted)时,对应的微指令也会从微指令缓存中被决出。

在某些情况下,整个微指令缓存可能会被刷新(fluashed)。一个原因可能是由于ITLB条目被决出。其他的原因通常是应用程序员不可见的,可能是由于某些重要的控制状态发生了变化,例如,重新映射了CR3,或者CR0和CR4的某些特性或模式标志位被启用等。

注:CR3与虚拟地址转换有关,CR0/CR4用于控制处理器的特性,例如开启保护模式,分页模式,物理地址扩展等。详情可参看Intel SDM文档或https://en.wikipedia.org/wiki/Control_register

还存在一些情况会导致整个微指令缓存被禁用,例如,当CS段寄存器的基地址是非0时。

猜你喜欢

转载自blog.csdn.net/qq_43401808/article/details/85997249