2.4.3.执行核
Intel Core微架构的执行核是超标量(superscalar)的,可以乱序处理指令。当一个依赖链导致机器等待一个资源(比如第二级数据缓存行)时,执行核执行其他指令。这增加了每周期被执行指令的总体速率(IPC)。
执行核包含以下3个主要部件:
· 重命名器(Renamer)——将微操作从前端移到执行核。架构寄存器被重命名器为微架构寄存器。重命名器消除了称为读后读(read-after-read)以及读后写(write-after-read)风险(hazard)的伪依赖性。
· 重排缓冲(Reorder buffer,ROB)——支持在完成各阶段的微操作,缓冲已完成微操作,顺序更新架构状态,并管理异常次序。ROB有96个入口处理行进中的指令。
· 保留站(Reservation station,RS)——排队微操作,直到所有的源操作数就绪,将就绪的微操作调度并分发到可用的执行单元。RS有32个入口。
乱序核的初始状态将微操作从前端移到ROB与RS。在这个过程中,乱序核执行以下步骤:
· 对微操作分配资源(例如:这些资源可以是读或写缓冲)。
· 将微操作绑定到合适的发布端口。
· 重命名微操作的源与目标,启用乱序执行。
· 当数据是一个立即数或一个已经计算出来的寄存器值,向微操作提供数据。
以下列表描述了常见操作的各种类型,以及核如何高效地执行它们:
· 单周期时延的微操作——大多数单周期微操作可以由多个执行单元执行,使得多个相互依赖操作流被快速执行。
· 更长时延经常使用的微操作——这些微操作具有流水线化的执行单元,因此这些类型的多个微操作可能同时在流水线不同部分执行。
· 具有依赖数据的时延的操作——某些操作,比如除法,具有依赖于数据的时延。整数除法解析操作数仅执行操作数有意义部分(significantportion)的计算,因此加速了除以小数值的常见情形。
· 对满足特定限制的操作数具有固定时延的浮点操作——不满足这些限制的操作数被视为异常情形,以更高的时延执行并降低了吞吐率。对更常见的情形,这些更低吞吐率的案例不影响时延与吞吐率。
· 具有可变时延的内存操作数,即使在L1缓存命中的情形下——来自转发未知安全的读可能会等待,直到执行前一个写地址被解析出来。内存次序缓冲(memoryorder buffer,MOB)接受并处理所有的内存操作。更多关于MOB的信息参考2.4.4节。
2.4.3.1. 发布端口与执行单元
调度器通过发布端口每周期最多可以分发6个微操作。IntelCore微架构与增强IntelCore微架构显示在表2-26中,前者由其CPUID签名的DisplayFamily_DisplayModel值06_0FH表示,后者由相应签名值06_17H表示。这张表提供了每个发布端口常见整数与浮点(FP)操作以周期计的时延与吞吐率数据。
表2-26. Intel Core微架构与增强Intel Core微架构的发布端口
执行操作 | 时延,吞吐率 | 注释[1] | |
签名 = 06_0FH | 签名 = 06_17H | ||
整数ALU 整数SIMD ALU FP/SIMD/SSE2 Mov与Logic | 1, 1 1, 1 1, 1 | 1, 1 1, 1 1, 1 | 包括64比特模式整数MUL; 发布端口0;回写端口0 |
单精度(FP)FP MUL 双精度FP MUL | 4, 1 5, 1 | 4, 1 5, 1 | 发布端口0;回写端口0 |
FP MUL(X87) FP Shuffle DIV/SQRT | 5, 2 1, 1 | 5, 2 1, 1 | 发布端口0;回写端口0 FP shuffle不处理QW shuffle |
整数ALU 整数SIMD ALU FP/SIMD/SSE2 Mov与Logic | 1, 1 1, 1 1, 1 | 1, 1 1, 1 1, 1 | 不包括64比特模式整数MUL; 发布端口1;回写端口1 |
FP ADD QW Shuffle | 3, 1 1, 1[2] | 3, 1 1, 1[3] | 发布端口1;回写端口1 |
整数读 FP读 | 3, 1 4, 1 | 3, 1 4, 1 | 发布端口2;回写端口2 |
写地址[4] | 3, 1 | 3, 1 | 发布端口3 |
写数据[5] |
|
| 发布端口4 |
整数ALU 整数SIMD ALU FP/SIMD/SSE2 Mov与Logic | 1, 1 1, 1 1, 1 | 1, 1 1, 1 1, 1 | 发布端口5;回写端口5 |
QW Shuffle 128比特Shuffle/Pack/Unpack | 1, 110 2-4, 2-6[6] | 1, 111 1-3, 1[7] | 发布端口5;回写端口5 |
在每个周期,RS可以分发最多6个微操作。每个周期,最多4个结果可以写回RS与ROB,由RS最早在下一个周期使用。这个高执行带宽使执行爆发跟上要被解码及回收微融合微操作的功能扩展。
执行核包含以下3个执行栈:
· SIMD整数。
· 普通整数。
· X87/SIMD浮点。
执行核也包含至/自内存簇(memorycluster)。参考图2-7。
注意执行块(灰色)内,且出现在将整数与SIMD整数栈连接到浮点栈路径中的两个黑色区域。这个时延凸显为被称为旁路时延的一个额外周期。来自L1缓存的数据到浮点单元有1个额外的时延。在图2-7中黑色方块表示额外的时延周期。
[1] 混合使用相同端口时延不同的操作可以导致回写总线冲突;这会降低整体吞吐率。
[2] 128比特指令以更长时延以及下降的吞吐率执行。
[3] 在端口5使用128比特混排。
[4] 以要写入数据的地址准备写转发与写回收逻辑。
[5] 以要写入的数据准备写转发与写回收逻辑。
[6] 根据指令而变;128比特指令使用QW shuffle单元执行。
[7] 根据指令而变,在Intel Core微架构中128比特混排定义替换QW shuffle单元。
图2-7. Intel Core微架构的执行核
2.4.4.Intel® Advanced Memory Access
Intel Core微架构包含一个指令缓存以及每个核一个第一级数据缓存。两个核共享一个2或4M字节L2缓存。所有的缓存是回写且非包含的(non-inclusive)。每个核包含:
· L1数据缓存,称为数据缓存单元(DCU)——DCU可以处理多个未解决的缓存不命中,且继续支持进入的读写。它支持缓存一致性维护。DCU有以下规格:
- 32K字节大小。
- 8路集关联。
- 64字节行大小。
· 数据转换旁视缓冲(DTLB)——IntelCore微架构中的DTLB实现了两级层次。DTLB的每一层有多个项,可以支持4K字节或更大的页面。内部层级(DTLB0)的项用于读。外部层级(DTLB1)的项支持写操作以及不命中DTLB0的读。所有的项是4路关联的。以下是每个DTLB中的项列表:
- 用于大页面的DTLB1:32项。
- 用于4K字节页面的DTLB1:256项。
- 用于大页面的DTLB0:16项。
- 用于4K字节页面的DTLB0:16项。
· 页不命中处理(PMH)
· 内存排序缓冲(MOB)——它:
- 使读写能够被推测性以及乱序发布。
- 使被回收的读写在回收过程时具有正确的数据。
- 使读写遵循Intel 64与IA-32架构的内存排序规则。
Intel Core微架构的内存簇使用以下措施加速内存操作:
· 128比特读写操作。
· 预取数据到L1缓存。
· 到L2缓存的数据预取逻辑。
· 写转发。
· 内存歧义消除。
· 8个填充缓冲项。
· 20个写缓冲项。
· 内存操作的乱序执行。
· 流水线化的为所有权读(read-for-ownership,RFO)操作。
为内存簇优化软件的信息,参考3.6节,“优化内存访问”。
2.4.4.1. 读与写
Intel Core微架构每周期可以执行内存位置不同的,最多1个128比特读和最多1个128比特写。这个微架构使就其他指令以及其他内存操作而言的内存操作乱序执行成为可能。
读可以:
· 在读地址与写地址已知不冲突时,可在前面的写之前发布。
· 在前面的分支被解析之前,被推测地执行。
· 以乱序及一个重叠的方式获取缓存不命中。
· 猜测前面的写将不会是一个冲突地址,在它之前发布。
读不可以:
· 猜测性地接受任何失败或陷入。
· 猜测性地访问不可缓存内存类型。
当失败的或不可缓存的读更新程序员可见状态时,它们被检测,并等待直到回收。X87与浮点SIMD读加上1个额外的时钟时延。
写入内存以两个阶段执行:
· 执行阶段——使用地址以及写转发的数据准备写缓冲。用掉方法端口,这是端口3与4。
· 完成阶段——写被回收到程序员可见的内存。它可能与正在执行的读竞争缓存bank,将数据从写缓冲移到L1缓存。
2.4.4.2. 预取数据到L1缓存
Intel Core微架构提供两个硬件预取器,通过预取到L1数据缓存,加速程序对数据的访问:
· 数据缓存单元(DCU)预取器——这个预取器,也称为流媒体预取器,由对最近读入数据的一个上升访问触发。处理器假定这个访问是一个流媒体算法的部分,并自动获取下一行。
· 指令指针(IP)基于跨步的预取器——这个预取器记录独立的读指令。如果一条读指令被检测到具有一个规则的跨步,那么一个预取被发送到当前地址加上跨步的下一个地址。这个预取器可以向前、向后预取,并可以检测到最多半个4KB页面,或2K字节的跨步。
仅当满足以下条件时,数据预取对读起作用:
· 从回写内存类型读入。
· 预取数据与触发它的读指令在同一个4K字节页面内。
· 在流水线中没有正在进行的栅栏(fence)。
· 没有太多的其他读不命中正在进行。
· 没有连续的写操作流。
DCU预取具有以下效果:
· 如果数据在程序中以使用的次序被顺序安排,这会提高性能。
· 如果访问模式是稀疏而不是局部的,可能会因为带宽的问题造成性能轻微下降。
· 偶尔,如果算法的工作集被证明占据大多数缓冲,并且不需要的预取逐出了程序所要求的缓存行,由于L1的缓存容量,硬件预取器可能导致严重的性能下降。
对比依赖硬件预期数据量(data traffic)的硬件预取器,软件预取指令依赖程序员来预期缓存不命中量(cachemiss traffic),软件预取用作将数据的缓存行放入期望缓存层级的暗示。软件控制预取目的在于预取数据,不能预取代码。
2.4.4.3. 数据预取逻辑
数据预取逻辑(data prefetch logic,DPL)基于过去来自L2的DCU请求模式,将数据预取到第二级(L2)缓存。DPL维护两个独立的数组来保存来自DCU的地址:一个用于上行(12项),一个用于下行(4项)。DPL追踪对每项中一个4K字节页面的访问。如果一个访问页面不在这些数组里,那么分配一个数组项。
DLP监控DCU对请求的递增序列,称为流(stream),的读操作。一旦PDL检测到一个流的第二次访问,它预取下一个缓存行。例如,当DCU请求缓存行A与A+1,DPL假定DCU不久将需要缓存行A+2。如果DCU读了A+2,DPL预取缓存行A+3。对“下行”循环,DPL的运作类似。
Intel Pentium M处理器引入DPL。IntelCore微架构向DPL添加了以下特性:
· DPL可以检测更复杂的流,比如当这个流跳过缓存行时。在每次L2查找时,DPL可能发布2个预取请求。在IntelCore微架构中的DPL可以在读请求之前积累8个缓存行。
· 在Intel Core微架构中的DPL动态地适应总线宽度与请求数量。如果总线不忙,DPL进一步加大预取数量,如果总线繁忙降低预取数量。
· DPL适应各种应用程序与系统配置。
用于这两个核的项被分别处理。
2.4.4.4. 写转发
如果一个读允许一个写并重新读入这个写操作写入内存的数据,Intel Core微架构可以将来自这个写的数据直接转发给这个读。这个过程,称为写到读转发,通过使读直接从写操作获得数据,而不是通过内存,节省了周期。
写到读转发要发生,必须满足下列规则:
· 这个写必须是在这个读之前最后写入该地址的。
· 这个写在尺寸上必须不小于要读入的数据。
· 这个读不能跨越一个缓存行边界。
· 这个读不能跨越一个8字节边界。16字节读是这个规则的一个例外。
· 这个读必须对齐到这个写地址的开头,除了以下例外:
- 一个对齐的64比特写可以转发其任一一半(32比特)。
- 一个对齐的28比特写可以转发其任一四分之一(32比特)。
- 一个对齐的128比特写可以转发其任一一半(64比特)。
软件可以使用最后规则的这些例外来移动复杂结构体,而不会损失转发子域的能力。
在增强IntelCore微架构中,允许写转发开始的对齐限制被放松了。增强IntelCore微架构允许写转发在几个情形中开始,即后续的读不对齐到前面的写。图2-8显示了在增强IntelCore微架构中允许,但在IntelCore微架构中不允许的6种情形(在渐变填充背景里)。斜线背景的情形描述可以在IntelCore微架构与增强IntelCore微架构中开始的写转发。
图2-8. 在增强Intel Core微架构中写转发的改进
2.4.4.5. 内存歧义消除
一个读指令微操作可能依赖一个前面的写。许多微架构阻塞读,直到所有前面的写地址已知。
内存歧义消除器预测哪些读将不依赖任何之前的写。当歧义消除器预测到一个读没有这样的一个依赖性时,这个读从L1数据缓存获取其数据。
最终,这个预测被验证。如果检测到了冲突,这个读与所有后续的指令被重新执行。