CPU技术总览
具有三个解码、四个重命名/调度、八个发射/执行和两个加载/存储执行单元。
取指(预取,分支预测) → 译码(重命名) → 发射(乱序发射,动态调度) → 执行(超标量执行,超线程) → 访存(加载/存储单元) → 写回 → 提交
对于 CMOS 芯片,传统的首要能量消耗在于开关晶体管,也称为动态能量。每个晶体管所需的能量与晶体管驱动的电容负载和电压的平方成正比:
每个晶体管所需的功率只是转换能量与转换频率的乘积:
阿姆达尔定律
假设原来在一个系统中执行一个程序需要时间Told,其中某一个部分占的时间百分比为x,然后,把这一部分的性能提升k倍。即这一部分原来需要的时间为xTold,现在需要的时间变为(xTold)。则整个系统执行此程序需要的时间变为:
处理器性能方程
CPU time = 指令数 * 每条指令需要的时钟周期数 * 每个时钟周期的时间
clock cycle (or rate), clock cycles per instruction, and instruction count
处理器性能取决于三个特性:时钟周期(或速率)、每条指令的时钟周期数和指令计数
- 时钟周期时间——硬件技术和组织
- CPI——组织和指令集体系结构
- 指令计数——指令集体系结构和编译器技术
微处理器、内存、网络、磁盘 25-40年内的里程碑
CPU
| Microprocessor | 16-Bit address/bus, microcoded | 32-Bit address/bus, microcoded | 5-Stage pipeline, on-chip I&D caches, FPU | 2-Way srperscalar, 64-bit bus | Out-of-order 3 way superscalar | Out-of-order superpipelined, on-chip L2 cache | Multicore OOO 4-way on chip L3 cache, Turbo |
| Product | Intel 80286 | Intel 80386 | Intel 80486 | Intel Pentium | Intel Pentium Pro | Intel Pentium 4 | Intel Core i7 |
| Year | 1982 | 1985 | 1989 | 1993 | 1997 | 2001 | 2015 |
| Die size(mm2) | 47 | 43 | 81 | 90 | 308 | 217 | 122 |
| Transistors | 134,000 | 275,000 | 1,200,000 | 3,100,000 | 5,500,000 | 42,000,000 | 1,750,000,000 |
| Pins | 68 | 132 | 168 | 273 | 387 | 423 | 1400 |
| Latency(clocks) | 6 | 5 | 5 | 5 | 10 | 22 | 14 |
| Bus width(bits) | 16 | 32 | 32 | 64 | 64 | 64 | 196 |
| Clock rate(MHz) | 12.5 | 16 | 26 | 66 | 200 | 1500 | 4000 |
| Bandwidth(MIPS) | 2 | 6 | 25 | 132 | 600 | 4500 | 6400 |
| Latency(ns) | 320 | 313 | 200 | 76 | 50 | 15 | 4 |
Memory
| Memory module | DRAM | Page mode DRAM | Fast page mode DRAM | Synchronous DRAM | Double data rate SDRAM | DDR4 SDRAM |
| Module width(bits) | 16 | 16 | 32 | 64 | 64 | 64 |
| Year | 1980 | 1983 | 1986 | 1997 | 2000 | 2016 |
| Mbits/DRAM chip | 0.06 | 0.25 | 1 | 16 | 64 | 256 |
| Die size(mm2)096 | 35 | 45 | 70 | 170 | 204 | 50 |
| Pins | 16 | 16 | 18 | 54 | 66 | 134 |
| Bandwidth(MBytes/s) | 13 | 40 | 160 | 640 | 1600 | 27000 |
| Latency(ns) | 225 | 170 | 125 | 62 | 52 | 30 |
Network
| Local area network | Ethernet | Fast Ethernet | Gigabit Ethenet | 10 Gigabit Ethernet | 100 Gigabit Ethenet | 400 Gigabit Ethernet |
| IEEE stardard | 802.3 | 803.3u | 802.3ab | 802.3ac | 802.3ba | 802.3bs |
| Year | 1978 | 1995 | 1999 | 2003 | 2010 | 2017 |
| Bandwidth(Mbits/seconds) | 10 | 100 | 1000 | 10000 | 100000 | 400000 |
| Latency(us) | 3000 | 500 | 340 | 190 | 100 | 60 |
Disk
| Hard disk | 3600 RPM | 5400 RPM | 7200 RPM | 10000 RPM | 15000 RPM | 15000 RPM |
| Product | CDC WrenI 94145-36 | Seagate ST41600 | Seagate ST15150 | Seagate ST39102 | Seagate ST373453 | Seagate ST600MX0062 |
| Year | 1983 | 1990 | 1994 | 1998 | 2003 | 2016 |
| Capacity(GB) | 0.03 | 1.4 | 4.3 | 9.1 | 73.4 | 600 |
| Disk form factor | 5.25 in | 5.25 in | 3.5 in | 3.5 in | 3.5 in | 3.5 in |
| Media diameter | 5.25 in | 5.25 in | 3.5 in | 3.0 in | 2.5 in | 2.5 in |
| Interface | ST-412 | SCSI | SCSI | SCSI | SCSI | SAS |
| Bandwidth(MBytes/s) | 0.6 | 4 | 9 | 24 | 86 | 250 |
| Latency(ms) | 48.3 | 17.1 | 12.7 | 8.8 | 5.7 | 3.6 |
计算机类别
物联网/嵌入式计算机
嵌入式计算机存在于日常机器中:微波炉、洗衣机、大多数打印机、网络交换机和所有汽车。物联网 (IoT) 是指连接到互联网的嵌入式计算机,通常是无线方式。当通过传感器和执行器进行增强时,物联网设备会收集有用的数据并与物理世界进行交互,从而产生各种各样的“智能”应用,例如智能手表、智能恒温器、智能扬声器、智能汽车、智能家居、智能电网和智能城市。
嵌入式计算机具有最广泛的处理能力和成本。
它们包括可能售价 1 美分的 8 位至 32 位处理器,以及售价 100 美元的用于汽车和网络交换机的高端 64 位处理器。尽管嵌入式计算市场的计算能力范围非常大,但价格是该领域计算机设计的关键因素。当然,性能要求确实存在,但主要目标通常以最低价格满足性能需求,而不是以更高的价格实现更高的性能。预计 2020 年物联网设备数量将在 200 亿到 500 亿之间。
本书的大部分内容都适用于嵌入式处理器的设计、使用和性能,无论它们是现成的微处理器还是将与其他专用硬件组装在一起的微处理器内核。
个人移动设备
个人移动设备 (PMD) 是我们应用于具有多媒体用户界面的无线设备集合的术语,例如手机、平板电脑等。成本是一个主要问题,因为整个产品的消费者价格是几百美元。尽管对能源效率的重视通常是由电池的使用推动的,但需要使用更便宜的包装(塑料与陶瓷相比)以及没有风扇进行冷却也限制了总功耗。我们将在第 1.5 节中更详细地研究能源和电力问题。PMD上的应用程序通常是基于Web和面向媒体的,就像前面提到的谷歌翻译示例一样。能源和尺寸要求导致使用闪存进行存储(第 2 章)而不是磁盘。
PMD 中的处理器通常被认为是嵌入式计算机,但我们将它们作为一个单独的类别保留,因为 PMD 是可以运行外部开发软件的平台,并且它们具有台式计算机的许多特征。其他嵌入式设备在硬件和软件的复杂程度上受到更多限制。我们使用运行第三方软件的能力作为非嵌入式计算机和嵌入式计算机之间的分界线。
响应性和可预测性是媒体应用程序的关键特征。实时性能要求意味着应用程序的某个段具有绝对的最大执行时间。例如,在播放视频时PMD处理每个视频帧的时间是有限的,因为处理器必须很快接受并处理下一帧。在某些应用程序中,存在更细微的要求:特定任务的平均时间受到限制,以及超过某个最大时间的实例数。这种方法(有时称为软实时)出现在可能偶尔错过事件的时间限制时,只要错过的时间限制不多。
实时性能往往高度依赖于应用程序。
许多PMD应用中的其他关键特征是需要最小化内存和需要高效利用能源。能源效率由电池电量和散热共同驱动。内存可能是系统成本的很大一部分,在这种情况下优化内存大小非常重要。内存大小的重要性转化为对代码大小的强调,因为数据大小是由应用程序决定的。
桌面计算
第一个,也可能仍然是以美元计算的最大市场,是桌面计算。桌面计算的范围从售价低于 300 美元的低端上网本到售价为 2500 美元的高端、配置繁多的工作站。自 2008 年以来,每年生产的台式电脑中有一半以上是电池供电的笔记本电脑。桌面计算的销售额正在下降。
在这个价格和功能范围内,台式机市场倾向于优化性价比。性能(主要根据计算性能和图形性能来衡量)和系统价格的组合对于这个市场中的客户来说最为重要,因此对计算机设计人员来说也是最重要的。因此,最新、性能最高的微处理器和成本更低的微处理器通常首先出现在桌面系统中(有关影响计算机成本的问题的讨论,请参见第 1.6 节)。
桌面计算在应用程序和基准测试方面也往往具有相当好的特性,尽管越来越多地使用以 Web 为中心的交互式应用程序在性能评估方面提出了新的挑战。
服务器
随着 1980 年代向桌面计算的转变,服务器的作用越来越大,以提供更大规模、更可靠的文件和计算服务。此类服务器已成为大型企业计算的骨干,取代了传统的大型机。
对于服务器来说,不同的特性很重要。首先,可用性至关重要。
(我们将在第 1.7 节中讨论可用性。考虑运行银行或航空公司预订系统的ATM机的服务器。此类服务器系统的故障比单个桌面的故障更具灾难性,因为这些服务器必须每周 7 天、每天 24 小时运行。图 1.3 估算了服务器应用程序停机的收入成本。
服务器系统的第二个关键特性是可伸缩性。服务器系统通常会随着对所支持服务的需求不断增长或功能需求的扩展而增长。因此,扩展服务器的计算能力、内存、存储和 I/O 带宽的能力至关重要。
最后,服务器旨在实现高效的吞吐量。也就是说,服务器的整体性能(以每分钟的事务数或每秒提供的网页数表示)至关重要。对单个请求的响应能力仍然很重要,但总体效率和成本效益(由单位时间内可以处理的请求数量决定)是大多数服务器的关键指标。在第 1.8 节中,我们回到了评估不同类型计算环境的性能的问题。
群集/仓库规模计算机
软件即服务 (SaaS) 在搜索、社交网络、视频观看和共享、多人游戏、在线购物等应用中的增长导致了一类称为集群的计算机的增长。群集是通过局域网连接起来的台式计算机或服务器的集合,以充当一台较大的计算机。每个节点都运行自己的操作系统,节点使用网络协议进行通信。WSC 是最大的集群,因为它们的设计使数以万计的服务器可以作为一个服务器运行。第 6 章介绍了这类超大型计算机。
性价比和功率对 WSC 至关重要,因为它们非常大。正如第 6 章所解释的,仓库的大部分成本与仓库内计算机的电源和冷却有关。WSC 的年度摊销计算机本身和网络设备成本为 4000 万美元,因为它们通常每隔几年更换一次。当你需要大量的计算,您需要明智地购买,因为性价比提高 10% 意味着每个 WSC 每年可节省 400 万美元(4000 万美元的 10%);像亚马逊这样的公司可能有 100 个 WSC!
WSC 与服务器相关,因为可用性至关重要。例如,Amazon.com 2016 年的销售额为 1360 亿美元。由于一年大约有 8800 小时,每小时的平均收入约为 1500 万美元。在圣诞节购物的高峰时段,潜在的损失会高出许多倍。正如第 6 章所解释的,WSC 和服务器之间的区别在于,WSC 使用冗余、廉价的组件作为构建块,依靠软件层来捕获和隔离这种规模的计算将发生的许多故障,以提供此类应用程序所需的可用性。请注意,WSC 的可伸缩性由连接计算机的局域网处理,而不是由集成计算机硬件处理,就像服务器一样。
超级计算机与WSCs的关系在于它们同样昂贵,耗资数亿美元,但超级计算机的不同之处在于强调浮点性能,并运行一次可以运行数周的大型通信密集型批处理程序。相比之下,WSC 强调交互式应用程序、大规模存储、可靠性和高互联网带宽。
并行和并行架构的类别
多层次的并行性现在是所有四类计算机计算机设计的驱动力,能源和成本是主要制约因素。应用程序中基本上有两种并行性:
- 数据级并行性 (DLP) 的出现是因为可以同时操作许多数据项。
- 任务级并行性 (TLP) 的出现是因为创建了可以独立且在很大程度上并行运行的工作任务。
反过来,计算机硬件可以通过四种主要方式利用这两种应用程序并行性:
- 指令级并行性利用适度级别的数据级并行性,使用编译器帮助,使用流水线等想法,在中等级别使用推测执行等想法。
- 矢量架构、图形处理器单元 (GPU) 和多媒体指令集通过将单个指令应用于并行数据集合来利用数据级并行性。
- 线程级并行性利用紧密耦合的硬件模型中的数据级并行性或任务级并行性,允许并行线程之间的交互。
- 请求级并行性利用程序员或操作系统指定的基本解耦任务之间的并行性。
当Flynn(1966)在1960年代研究并行计算工作时,他发现了一个简单的分类,我们今天仍在使用其缩写。它们以数据级并行性和任务级并行性为目标。他研究了指令和数据流的并行性,这些指令在多处理器最受限制的组件上要求,并将所有计算机归入以下四类之一:
- 单指令流、单数据流 (SISD) — 此类别为单处理器。程序员认为它是标准的顺序计算机,但它可以利用 ILP。第 3 章介绍了使用 ILP 技术(如超标量和推测执行)的 SISD 体系结构。
- 单指令流,多数据流 (SIMD) — 同一指令由多个处理器使用不同的数据流执行。SIMD 计算机通过对多个数据项并行应用相同的操作来利用数据级并行性。每个处理器都有自己的数据存储器(因此,SIMD的MD),但只有一个指令存储器和控制处理器,用于获取和调度指令。第 4 章介绍了 DLP 和利用它的三种不同架构:矢量架构、标准指令集的多媒体扩展和 GPU。
- 多指令流、单数据流 (MISD) — 迄今为止,尚未构建这种类型的商用多处理器,但它完善了这种简单的分类。
- 多指令流、多数据流 (MIMD) — 每个处理器获取自己的指令并处理自己的数据,并以任务级并行性为目标。一般来说,MIMD 比 SIMD 更灵活,因此更普遍适用,但它本质上比 SIMD 更昂贵。例如,MIMD 计算机还可以利用数据级并行性,尽管开销可能高于 SIMD 计算机中的开销。这种开销意味着晶粒尺寸必须足够大才能有效地利用并行性。第 5 章介绍了紧密耦合的 MIMD 架构,该架构利用了线程级并行性,因为多个协作线程并行运行。第 6 章介绍了松散耦合的 MIMD 架构,特别是集群和仓库规模的计算机,它们利用了请求级并行性,其中许多独立任务可以自然地并行进行,几乎不需要通信或同步。
此分类是一个粗略的模型,因为许多并行处理器是 SISD、SIMD 和 MIMD 类的混合体。尽管如此,在本书中我们将看到的计算机的设计空间上放置一个框架是很有用的。
定义计算机体系结构
计算机设计人员面临的任务是一项复杂的任务:确定哪些属性对新计算机很重要,然后设计计算机以最大化性能和能效,同时保持在成本、功耗和可用性限制范围内。这个任务有很多方面,包括指令集设计、功能组织、逻辑设计和实现。该实现可能包括集成电路设计、封装、电源和冷却。优化设计需要熟悉非常广泛的技术,从编译器和操作系统到逻辑设计和封装。
几十年前,计算机体系结构一词通常仅指指令集设计。计算机设计的其他方面被称为实现,通常暗示实现是无趣的或挑战性较小的。
我们认为这种观点是不正确的。架构师或设计师的工作不仅仅是指令集设计,项目其他方面的技术障碍可能比指令集设计中遇到的技术障碍更具挑战性。在描述计算机架构师面临的更大挑战之前,我们将快速回顾指令集架构。
指令集架构:计算机架构的短视观点
在本书中,我们使用术语指令集架构 (ISA) 来指代实际的程序员可见指令集。ISA 充当软件和硬件之间的边界。本 ISA 快速回顾将使用 80x86、ARMv8 和 RISC-V 中的示例来说明 ISA 的七个维度。最受欢迎的RISC处理器来自ARM(Advanced RISC Machine),2015年出货的芯片数量为148亿片,大约是80x86处理器出货芯片数量的50倍。附录A和附录K提供了关于三项国际审计准则的更多细节。
RISC-V(“RISC Five”)是加州大学伯克利分校开发的现代 RISC 指令集,应业界的要求免费开放。除了完整的软件堆栈(编译器、操作系统和仿真器)之外,还有几种 RISC-V 实现可以免费用于定制芯片或现场可编程门阵列。RISC-V在第一个RISC指令集问世30年后开发,它继承了其祖先的好想法——大量的寄存器、易于流水线的指令和一组精益操作——同时避免了它们的遗漏或错误。它是前面提到的 RISC 架构的一个自由、开放、优雅的例子,这就是为什么有 60 多家公司加入了 RISC-V 基金会,包括 AMD、谷歌、惠普企业、IBM、Microsoft、英伟达、高通、三星和西部数据。在本书中,我们以 RISC-V 的整数核心 ISA 为例。
- ISA 类 — 目前几乎所有的 ISA 都被归类为通用寄存器体系结构,其中操作数要么是寄存器,要么是存储器位置。80x86 有 16 个通用寄存器和 16 个可以保存浮点数据的寄存器,而 RISC-V 有 32 个通用寄存器和 32 个浮点寄存器(见图 1.4)。此类的两个流行版本是寄存器存储器 ISA,例如 80x86,它可以作为许多指令的一部分访问内存,以及加载存储 ISA,例如 ARMv8 和 RISC-V,它们只能通过加载或存储指令访问内存。自 1985 年以来宣布的所有 ISA 都是加载存储的。
- 内存寻址 — 几乎所有台式机和服务器计算机(包括 80x86、ARMv8 和 RISC-V)都使用字节寻址来访问内存操作数。某些体系结构(如 ARMv8)要求对象必须对齐。
- 寻址模式 - 除了指定寄存器和常量操作数外,寻址模式还指定内存对象的地址。RISC-V 寻址模式包括寄存器、即时(用于常数)和位移,其中将常数偏移添加到寄存器中以形成存储器地址。80x86 支持这三种模式,以及三种位移变体:无寄存器(绝对值)、两个寄存器(基于位移索引)和两个寄存器,其中,一个寄存器乘以以字节为单位的操作数大小(基于缩放的索引和位移)。它更像是最后三种模式,减去位移字段,加上间接寄存器、索引寄存器和基于缩放索引的寄存器。ARMv8 具有三种 RISC-V 寻址模式以及 PC 相对寻址、两个寄存器的总和以及两个寄存器的总和,其中一个寄存器乘以以字节为单位的操作数大小。它还具有自动递增和自动递减寻址功能,其中计算出的地址替换了用于形成地址的寄存器之一的内容。
- 操作数的类型和大小 - 与大多数 ISA 一样,80x86、ARMv8 和 RISC-V 支持 8 位(ASCII 字符)、16 位(Unicode 字符或半字)、32 位(整数或字)、64 位(双字或长整数)的操作数大小,以及 32 位(单精度)和 64 位(双精度)的 IEEE 754 浮点数。80x86 还支持 80 位浮点(扩展双精度)。
- 操作数的类型和大小 - 与大多数 ISA 一样,80x86、ARMv8 和 RISC-V 支持 8 位(ASCII 字符)、16 位(Unicode 字符或半字)、32 位(整数或字)、64 位(双字或长整数)的操作数大小,以及 32 位(单精度)和 64 位(双精度)的 IEEE 754 浮点数。80x86 还支持 80 位浮点(扩展双精度)。
- 控制流指令 — 几乎所有 ISA(包括这三个 ISA)都支持条件分支、无条件跳转、过程调用和返回。这三者都使用 PC 相对寻址,其中分支地址由添加到 PC 的地址字段指定。有一些细微的差异。RISC-V 条件分支(BE、BNE 等)测试寄存器的内容,80x86 和 ARMv8 分支测试设置为算术/逻辑运算副作用的条件代码位。ARMv8 和 RISC-V 过程调用将返回地址放在寄存器中,而 80x86 调用 (CALLF) 将返回地址放在内存中的堆栈上。
- 对 ISA 进行编码 - 编码有两种基本选择:固定长度和可变长度。所有 ARMv8 和 RISC-V 指令长度均为 32 位,简化了指令解码。图 1.7 显示了 RISC-V 指令格式。80x86 编码是可变长度的,范围从 1 到 18 个字节。可变长度指令比固定长度指令占用的空间更少,因此为 80x86 编译的程序通常比为 RISC-V 编译的相同程序小。请注意,前面提到的选择将影响指令编码为二进制表示的方式。例如,寄存器的数量和寻址模式的数量都对指令的大小有重大影响,因为寄存器字段和寻址模式字段可以在单个指令中多次出现。(请注意,ARMv8 和 RISC-V 后来提供了称为 Thumb-2 和 RV64IC 的扩展,它们分别提供 16 位和 32 位长度指令的混合,以减小程序大小。这些紧凑型 RISC 架构的代码大小小于 80x86 的代码大小。见附录 K。
除了ISA设计之外,计算机架构师面临的其他挑战在目前尤为严重,因为指令集之间的差异很小,并且存在不同的应用领域。因此,从本书的第四版开始,除了这个快速回顾之外,大部分指令集材料都可以在附录中找到(见附录 A 和 K)。
真正的计算机体系结构:设计组织和硬件以满足目标和功能要求
计算机的实现有两个组成部分:组织和硬件。术语组织包括计算机设计的高级方面,例如内存系统、内存互连以及内部处理器或 CPU(中央处理器 - 实现算术、逻辑、分支和数据传输)的设计。术语微架构也被用来代替组织。例如,具有相同指令集架构但组织不同的两个处理器是 AMD Opteron 和 Intel Core i7。两种处理器都实现了 80 x86 指令集,但它们具有非常不同的管道和缓存组织。
每个微处理器切换到多个处理器导致术语内核也被用于处理器。与其说多处理器微处理器,不如说多核这个词流行起来。鉴于几乎所有芯片都有多个处理器,中央处理器或CPU一词正在逐渐流行。
硬件是指计算机的具体情况,包括计算机的详细逻辑设计和封装技术。通常,一系列计算机包含具有相同指令集体系结构和非常相似的组织结构的计算机,但它们在详细的硬件实现上有所不同。例如,英特尔酷睿 i7(参见第 3 章)和英特尔至强 E7(参见第 5 章)几乎相同,但提供不同的时钟速率和不同的内存系统,使至强 E7 对服务器计算机更有效。
在本书中,“架构”一词涵盖了计算机设计的所有三个方面——指令集架构、组织或微架构以及硬件。
计算机架构师必须设计计算机以满足功能要求以及价格、功耗、性能和可用性目标。图 1.8 总结了在设计新计算机时要考虑的要求。通常,架构师还必须确定功能需求是什么,这可能是一项主要任务。这些要求可能是受市场启发的特定功能。应用软件通常通过确定计算机的使用方式来驱动某些功能需求的选择。如果存在用于特定指令集体系结构的大量软件,架构师可能会决定新计算机应实现现有指令集。特定类别应用程序的巨大市场的存在可能会鼓励设计人员纳入使计算机在该市场中具有竞争力的要求。后面的章节将深入探讨其中的许多要求和功能。
架构可能会持续数十年,例如,IBM 大型机的核心已经使用了 50 多年。架构师必须规划可以延长成功计算机寿命的技术更改。
为了规划计算机的发展,设计人员必须意识到实现技术的快速变化。五种实施技术以惊人的速度变化,对现代实施至关重要:
- 集成电路逻辑技术——从历史上看,晶体管密度每年增加约 35%,在四年内翻了两番。芯片尺寸的增加更难预测且速度较慢,每年从 10% 到 20% 不等。综合效应是芯片上晶体管数量的传统增长率约为每年40%-55%,或每18-24个月翻一番。这种趋势通常被称为摩尔定律。设备速度的扩展速度较慢,我们将在下面讨论。令人震惊的是,摩尔定律已经不复存在。每个芯片的器件数量仍在增加,但速度正在放缓。与摩尔定律时代不同,我们预计每一代新技术的翻倍时间都会延长。
- 半导体 DRAM(动态随机存取存储器)——该技术是主存储器的基础,我们将在第 2 章中讨论它。DRAM的增长速度已经大幅放缓,从过去每三年翻两番。8 Gb DRAM 于 2014 年出货,但 16 Gb DRAM 要到 2019 年才能达到这一状态,而且看起来不会有 32 Gb DRAM(Kim,2005 年)。第 2 章提到了其他几种技术,当 DRAM 达到容量壁垒时,这些技术可能会取代它。
- 半导体闪存(电可擦除可编程只读存储器)— 这种非易失性半导体存储器是 PMD 中的标准存储器件,其迅速普及推动了其容量的快速增长。近年来,每个闪存芯片的产能每年增加约50%-60%,大约每两年翻一番。目前,闪存每比特比DRAM便宜8-10倍。第 2 章介绍了闪存。
- 磁盘技术 - 在 1990 年之前,密度每年增加约 30%,在三年内翻了一番。此后每年上升到60%,1996年增加到每年100%。从2004年到2011年,它回落到每年40%左右,或每两年翻一番。最近,磁盘改进速度已放缓到每年不到 5%。增加磁盘容量的一种方法是在相同的面密度下添加更多盘片,但在 3.5 英寸外形规格磁盘的 1 英寸深度内已经有 7 个盘片。最多还有一两个盘子的空间。真正密度增加的最后希望是在每个磁盘读写头上使用一个小激光器将 30 nm 的光斑加热到 400°C,以便在冷却之前可以磁性写入。目前尚不清楚热辅助磁记录系统是否可以经济可靠地制造,尽管希捷宣布计划在2018年限量生产HAMR。HAMR是硬盘面密度持续提升的最后机会,现在每比特比闪存便宜 8-10 倍,比 DRAM 每比特便宜 200-300 倍。该技术是服务器和仓库级存储的核心,我们在附录 D 中详细讨论了这些趋势。
- 网络技术 — 网络性能既取决于交换机的性能,也取决于传输系统的性能。我们在附录 F 中讨论了网络趋势。
这些快速变化的技术塑造了计算机的设计,随着速度和技术的提高,计算机的使用寿命可能为 3-5 年。闪存等关键技术变化很大,设计人员必须为这些变化做好规划。事实上,设计人员经常为下一项技术进行设计,因为他们知道,当产品开始批量出货时,下一项技术可能是最具成本效益的,或者可能具有性能优势。传统上,成本的下降速度与密度增加的速度差不多。
尽管技术在不断改进,但这些增长的影响可能是离散的飞跃,因为达到了允许新功能的阈值。例如,当 MOS 技术在 1980 年代初达到一个点时,单个芯片上可以容纳 25,000 到 50,000 个晶体管,构建单芯片 32 位微处理器成为可能。到 1980 年代后期,第一级缓存可以放在芯片上。通过消除处理器内部以及处理器与缓存之间的芯片交叉,可以显著提高性价比和能耗。在技术达到一定程度之前,这种设计根本不可行。随着多核微处理器和每一代内核数量的增加,即使是服务器计算机也越来越多地朝着所有处理器的单一芯片发展。这种技术阈值并不罕见,并且对各种设计决策都有重大影响。
性能趋势:带宽与延迟的关系
正如我们将在第 1.8 节中看到的,带宽或吞吐量是在给定时间内完成的总工作量,例如磁盘传输的每秒兆字节数。相反,延迟或响应时间是事件开始和完成之间的时间,例如磁盘访问的毫秒数。图 1.9 绘制了微处理器、内存、网络和磁盘技术里程碑在带宽和延迟方面的相对改进。图 1.10 更详细地描述了示例和里程碑。
性能是微处理器和网络的主要差异化因素,因此它们获得了最大的收益:32,000–40,000
在延迟中。对于内存和磁盘来说,容量通常比性能更重要,因此容量提高了更多,但带宽增加了 400-2400,仍然比 8-9 # 的延迟增益大得多。
显然,在这些技术中,带宽已经超过了延迟,并且可能会继续这样做。一个简单的经验法则是,带宽至少增长延迟改善的平方。计算机设计人员应进行相应的计划。
内存层次结构设计
简介
平均内存访问时间=命中时间+丢失率*未命中惩罚
六种基本的缓存优化
- 增大块大小以降低未命中率 - 降低未命中率的最简单方法是利用空间局部性并增加块大小。较大的块可以减少强制失误,但也会增加失误惩罚。由于较大的块会减少标签的数量,因此它们可以略微降低静态功耗。较大的块大小也会增加容量或冲突未命中,尤其是在较小的缓存中。选择正确的块大小是一个复杂的权衡,取决于缓存的大小和未命中的惩罚
- 更大的缓存以降低未命中率 - 减少容量未命中率的明显方法是增加缓存容量。缺点包括较大的缓存内存可能更长的命中时间以及更高的成本和功耗。缓存越大,静态和动态功耗就越高
- 提高关联性以降低未命中率 - 显然,提高关联性可减少冲突未命中率。更高的关联性可能以增加命中时间为代价。正如我们很快就会看到的,关联性也会增加功耗
- 多级高速缓存可减少未命中惩罚——一个难题是使高速缓存命中时间变快,以跟上处理器的时钟频率,还是使高速缓存变大以缩小处理器访问和主内存访问之间的差距。在原始高速缓存和内存之间添加另一级高速缓存可以简化决策。一级高速缓存可以足够小以匹配快速的时钟周期时间,但二级(或三级)高速缓存可以足够大以捕获许多将转到主内存的访问。对二级高速缓存中未命中的关注导致更大的块、更大的容量和更高的关联性。多级高速缓存比单个聚合高速缓存更节能。如果 L1 和 L2 分别指一级和二级高速缓存,我们可以重新定义平均内存访问时间:
命中时间+未命中率*(命中时间+未命中率*未命中惩罚)
- 通过优先读取未命中而不是写入来减少未命中惩罚——写入缓冲区是实现此优化的理想位置。写入缓冲区会创建危害,因为它们保存读取未命中时所需位置的更新值——即通过内存读取后写入危害。一种解决方案是在读取未命中时检查写入缓冲区的内容。如果没有冲突,并且内存系统可用,则在写入之前发送读取可以减少未命中惩罚。大多数处理器将读取优先于写入。此选择对功耗影响很小。
- 避免在高速缓存索引期间进行地址转换以减少命中时间——高速缓存必须应对处理器从虚拟地址到物理地址的转换才能访问内存。(虚拟内存将在第 2.4 节和 B.4 节中介绍。)一种常见的优化方法是使用页偏移量(在虚拟地址和物理地址中相同的部分)对高速缓存进行索引,如附录 B 第 B.38 页所述。这种虚拟索引/物理标记方法会给 L1 高速缓存的大小和结构带来一些系统复杂性和/或限制,但从关键路径中移除转换旁路缓冲器 (TLB) 访问的优势大于劣势。
缓存性能的十项高级优化
前面的平均内存访问时间公式为我们提供了缓存优化的三个指标:命中时间、未命中率和未命中率。鉴于最近的趋势,我们将缓存带宽和功耗添加到此列表中。我们可以根据这些指标将我们检查的 10 种高级缓存优化分为五类:
- 缩短命中时间 - 小型而简单的一级缓存和路径预测,这两种技术通常还可以降低功耗
- 增加缓存带宽 - 流水线缓存、多组缓存和非阻塞缓存。这些技术对功耗的影响各不相同
- 减少未命中惩罚 - 关键词优先并合并写入缓冲区,这些优化对功耗影响不大
- 降低未命中率 - 编译器优化。显然,编译时的任何改进都会降低功耗
- 通过并行性降低未命中率或未命中率 - 硬件预取和编译器预取。这些优化通常会增加功耗,主要是因为未使用的预取数据
首次优化:小而简单的一级缓存,可减少命中时间和功耗
二次优化:减少命中时间的方式预测
第三种优化:流水线访问和多库缓存,增加带宽
第四个优化:非阻塞缓存,增加缓存带宽
第五个优化:关键词优先,提前重启,减少失误惩罚
第六次优化:合并写入缓冲区以减少未命中惩罚
第七次优化:编译器优化以降低未命中率
第八项优化:指令和数据的硬件预取,降低失误率或失误率
第九项优化:编译器控制的预取,以降低未命中率或未命中率
第十个优化:使用 HBM 扩展内存层次结构
依赖关系
利用 ILP 有两种基本可分离的方法:(1) 一种依靠硬件来帮助动态发现和利用并行性的方法,以及 (2) 一种依靠软件技术在编译时静态查找并行性的方法。
有三种不同类型的依赖关系:数据依赖关系(也称为真实数据依赖关系)、名称依赖关系和控件依赖关系。
数据依赖关系
如果满足以下任一条件,则指令 j 与指令 i 的数据相关:
- 指令 i 产生一个结果,该结果可由指令 j 使用
- 指令 j 依赖于指令 k,指令 k 依赖于指令 i
名称依赖关系
当两个指令使用相同的寄存器或内存位置(称为名称)时,就会发生名称依赖关系,但与该名称关联的指令之间没有数据流。在程序顺序上,指令 i 在指令 j 之前有两种类型的名称依赖关系:
- 当指令 j 写入指令 i 读取的寄存器或存储器位置时,指令 i 和指令 j 之间就会发生反依赖性
- 当指令 i 和指令 j 写入相同的寄存器或存储器位置时,就会发生输出依赖性。必须保留指令之间的顺序,以确保最终写入的值与指令 j 相对应。
危害
只要指令之间存在名称或数据依赖关系,并且它们足够接近,以至于执行期间的重叠会改变对依赖关系中涉及的操作数的访问顺序,就会存在危险
- RAW(先写后读)——j 在我写入源之前尝试读取源,因此 j 错误地获取了旧值。这种危险是最常见的类型,对应于真正的数据依赖性。必须保留程序顺序,以确保 j 从 i 接收到值
- WAW(write after write)— j 尝试在 i 写入操作数之前写入操作数。写入最终以错误的顺序执行,将 i 写入的值而不是 j 写入的值留在目标中。这种危险对应于输出依赖性。WAW 危险仅存在于写入多个管道阶段的管道中,或者即使前一条指令停滞也允许指令继续执行
- WAR(读后写)— j 尝试在目的地被 i 读取之前写入目的地,因此 i 错误地获取了新值。这种危险源于反依赖性(或名称依赖性)。在大多数静态问题管道(甚至更深的管道或浮点管道)中不会发生 WAR 危险,因为所有读取都是早期的(在附录 C 的管道中的 ID 中),而所有写入都是延迟的(在附录 C 的管道中的 WB 中)。当某些指令在指令流水线的早期写入结果,而其他指令在流水线的后期读取源时,或者当指令被重新排序时,就会发生 WAR 危险,正如我们将在本章中看到的那样
控制依赖关系
控制依赖关系决定了指令 i 相对于分支指令的顺序,以便指令 i 以正确的程序顺序执行,并且仅在应该执行时执行。除了程序的第一个基本块中的指令外,每条指令都依赖于某些分支集,并且通常,必须保留这些控制依赖关系以保持程序顺序。
控件依赖关系的最简单示例之一是 if 语句的 “then” 部分中语句对分支的依赖关系
用于公开 ILP 的基本编译器技术
- 基本流水线调度和循环展开
通过高级分支机构预测降低分支机构成本
由于需要通过分支危险和失速来强制控制依赖性,因此分支会损害管道性能。循环展开是减少分支危害数量的一种方法;我们还可以通过预测分支的行为方式来减少分支的性能损失。我们研究了简单的分支预测器,这些预测器要么依赖于编译时信息,要么依赖于观察到的单个分支的动态行为。随着流水线的深度和每个时钟的问题数的增加,动态指令的数量也在增加,更准确的分支预测的重要性也越来越大。
- 关联分支预测变量
- 锦标赛预测器:自适应地结合本地和全局预测器
- 标记 混合预测变量
通过动态调度克服数据危害
一个简单的静态调度流水线获取指令并发出它,除非管道中已有的指令与获取的指令之间存在数据依赖关系,而该依赖关系无法通过绕过或转发来隐藏。(转发逻辑可减少有效的管道延迟,以便某些依赖关系不会导致危险。如果存在无法隐藏的数据依赖关系,则危险检测硬件会从使用结果的指令开始停止管道。在清除依赖关系之前,不会获取或发出任何新指令。
在本节中,我们将探讨动态调度,这是一种硬件对指令执行进行重新排序的技术,以减少停顿,同时维护数据流和异常行为。动态调度具有多个优点。首先,它允许使用一个管道编译的代码在不同的管道上高效运行,无需拥有多个二进制文件并针对不同的微架构进行重新编译。
简单流水线技术的一个主要局限性是它们使用按顺序发出和执行指令:指令是按程序顺序发出的,如果指令在流水线中停滞不前,则以后的指令无法继续。因此,如果管道中两个间隔很近的指令之间存在依赖关系,则会导致危险,并导致停滞。如果有多个功能单元,这些单元可能会处于闲置状态。如果指令 j 依赖于一个长时间运行的指令 i,该指令当前正在管道中执行,那么 j 之后的所有指令都必须停止,直到 i 完成并且 j 可以执行。
- 使用 Tomasulo 方法的动态调度
基于硬件的推测
当我们试图利用更多的指令级并行性时,保持控制依赖性成为一个越来越大的负担。分支预测减少了可归因于分支的直接停顿,但对于每个时钟执行多条指令的处理器来说,仅仅准确预测分支可能不足以产生所需的指令级并行度。广泛发行的处理器可能需要在每个时钟周期执行一个分支,以保持最佳性能。因此,要利用更多的并行性,就需要我们克服控制依赖性的局限性。
克服控制依赖是通过推测分支的结果并执行程序来完成的,就好像我们的猜测是正确的一样。这种机制代表了对具有动态调度的分支预测的微妙但重要的扩展。特别是,在投机时,我们获取、发出和执行指令,就好像我们的分支预测总是正确的一样;动态调度仅获取和发出此类指令。当然,我们需要机制来处理推测不正确的情况。附录 H 讨论了支持编译器推测的各种机制。在本节中,我们将探讨硬件推测,它扩展了动态调度的思想。
基于硬件的推测结合了三个关键思想:(1)动态分支预测,以选择要执行的指令,(2)推测,以允许在解决控制依赖关系之前执行指令(能够消除错误推测序列的影响),以及(3)动态调度,以处理基本块的不同组合的调度。(相比之下,没有推测的动态调度仅部分重叠基本块,因为它要求在实际执行后续基本块中的任何指令之前解析分支。
使用多个问题和静态调度利用ILP
前面部分的技术可用于消除数据、控制停滞并实现理想的 CPI 为 1。为了进一步提高性能,我们希望将 CPI 降低到小于 1,但如果每个时钟周期只发出一条指令,则 CPI 不能降低到 1 以下。
在接下来的几节中讨论的多问题处理器的目标是允许在一个时钟周期内发出多条指令。多问题处理器有三种主要类型:
- 静态调度的超标量处理器
- VLIW(超长指令字)处理器
- 动态调度的超标量处理器
这两种类型的超标量处理器每个时钟发出不同数量的指令,如果它们是静态调度的,则使用按顺序执行,如果它们是动态调度的,则使用无序执行
相比之下,VLIW 处理器发出固定数量的指令,格式化为一个大指令或固定指令数据包,指令之间具有明确指示的指令之间的并行性。VLIW 处理器本质上是由编译器静态调度的。
尽管静态调度超标量在每个时钟发出的指令数量是可变的,而不是固定的,但它们实际上在概念上更接近 VLIW,因为这两种方法都依赖于编译器为处理器调度代码。由于随着问题宽度的增长,静态调度超标量的优势逐渐减弱,因此静态计划超标量主要用于较窄的问题宽度,通常只有两条指令。超过该宽度,大多数设计人员选择实现 VLIW 或动态调度的超标量。
使用动态调度、多个问题和推测来利用 ILP
到目前为止,我们已经了解了动态调度、多问题和投机的各个机制是如何工作的。在本节中,我们将这三者放在一起,从而产生了与现代微处理器非常相似的微架构。为简单起见,我们只考虑每个时钟发出两条指令的速率,但这些概念与每个时钟发出三条或更多指令的现代处理器没有什么不同。
在动态调度的处理器中,每个时钟发出多条指令(有或没有推测)非常复杂,原因很简单,因为多条指令可能相互依赖。因此,必须并行更新表以查找指令;否则,表将不正确,或者依赖关系可能会丢失。
在动态调度的处理器中,已经使用了两种不同的方法在每个时钟发出多个指令,并且这两种方法都依赖于密钥正在分配预留站和更新管道控制表的观察结果。一种方法是在半个时钟周期内运行此步骤,以便可以在一个时钟周期内处理两条指令;不幸的是,这种方法不能轻易地扩展到每个时钟处理四条指令。
指令传递的先进技术和预测
在高性能管道中,尤其是具有多个问题的管道中,仅正确预测分支是不够的;实际上,我们必须能够提供高带宽的指令流。在最近的多问题处理器中,这意味着每个时钟周期提供 4-8 条指令。我们首先研究增加指令传送带宽的方法。然后,我们转向实现高级推测技术的一系列关键问题,包括使用寄存器重命名与重新排序缓冲区,推测的侵略性,以及一种称为价值预测的技术,该技术试图预测计算结果,并可能进一步增强ILP。
增加指令获取带宽
多问题处理器将要求每个时钟周期获取的平均指令数至少与平均吞吐量一样大。当然,获取这些指令需要足够宽的指令缓存路径,但最困难的方面是处理分支。在本节中,我们将介绍两种处理分支的方法,然后讨论现代处理器如何集成指令预测和预取函数。
专用分支预测器:预测过程返回、间接跳转和循环分支
当我们试图增加推测的机会和准确性时,我们面临着预测间接跳转的挑战,即目标地址在运行时变化的跳转。高级语言程序将为间接过程调用、select 或 case 语句以及 FORTRAN 计算的 gotos 生成此类跳转,尽管许多间接跳转仅来自过程返回。例如,对于 SPEC95 基准测试,过程返回平均占分支的 15% 以上,间接跳跃占绝大多数。对于面向对象的语言,如 C++ 和 Java,过程返回更加频繁。因此,将重点放在程序返回上似乎是合适的。
尽管可以使用分支目标缓冲区预测过程返回,但如果从多个站点调用过程,并且来自一个站点的调用未及时聚类,则此类预测技术的准确性可能会很低。例如,在 SPEC CPU95 中,主动分支预测器对此类返回分支的准确率低于 60%。为了克服这个问题,一些设计使用一小块返回地址缓冲区作为堆栈运行。此结构缓存最新的返回地址,在调用时在堆栈上推送一个返回地址,并在返回时弹出一个返回地址。如果缓存足够大(即与最大调用深度一样大),它将完美地预测回报。图 3.28 显示了在许多 SPEC CPU95 基准测试中具有 0–16 个元素的这种返回缓冲区的性能。在第 3.10 节中检查 ILP 研究时,我们将使用类似的回报预测器。Intel Core 处理器和 AMD Phenom 处理器都有返回地址预测器。
在大型服务器应用程序中,各种函数调用和控制传输也会发生间接跳转。预测此类分支的目标并不像在过程返回中那么简单。一些处理器选择为所有间接跳跃添加专门的预测器,而其他处理器则依赖于分支目标缓冲区。
尽管像 gshare 这样的简单预测器在预测许多条件分支方面做得很好,但它并不是为预测循环分支而量身定制的,尤其是对于长时间运行的循环。正如我们之前所观察到的,英特尔酷睿i7 920使用了专门的环路分支预测器。随着标记混合预测器的出现,它们同样擅长预测循环分支,一些最近的设计者选择将资源放入更大的标记混合预测器中,而不是单独的循环分支预测器中。
集成指令提取单元
为了满足多问题处理器的需求,许多最近的设计人员选择将集成指令获取单元实现为一个单独的自主单元,将指令馈送到管道的其余部分。从本质上讲,这相当于认识到,鉴于多个问题的复杂性,将指令获取描述为简单的单管道阶段不再有效。
取而代之的是,最近的设计使用了集成指令获取单元,该单元集成了多种功能:
- 集成分支预测 - 分支预测器成为指令获取单元的一部分,并不断预测分支,从而驱动获取管道。
- 指令预取 - 要在每个时钟上传递多个指令,指令提取单元可能需要提前提取。该单元自主管理指令的预取(参见第 2 章,讨论执行此操作的技术),并将其与分支预测集成。
- 指令内存访问和缓冲 — 每个周期获取多条指令时,会遇到各种复杂性,包括获取多条指令可能需要访问多个缓存行的困难。指令提取单元封装了这种复杂性,使用预取来尝试隐藏交叉缓存块的成本。指令获取单元还提供缓冲,基本上充当按需单元,根据需要和所需数量向发出阶段提供指令。
推测:实现问题和扩展
在本节中,我们将探讨五个问题,这些问题涉及多重问题和推测中的设计权衡和挑战,首先是使用寄存器重命名,这种方法有时被用来代替重新排序缓冲区。然后,我们讨论了对控制流推测的一个重要可能的扩展:一个称为价值预测的想法。
推测支持:寄存器重命名与重新排序缓冲区
使用重新排序缓冲区 (ROB) 的一种替代方法是显式使用更大的物理寄存器集,并结合寄存器重命名。这种方法建立在Tomasulo算法中使用的重命名概念之上,并对其进行了扩展。在Tomasulo的算法中,架构上可见的寄存器的值(x0,. .R31 和 F0, . . .F31)在执行的任何时候都包含在寄存器集和预订站的某种组合中。随着投机的增加,寄存器值也可能暂时驻留在 ROB 中。无论哪种情况,如果处理器在一段时间内没有发出新指令,则所有现有指令都将提交,并且寄存器值将出现在寄存器文件中,该文件直接对应于架构上可见的寄存器。
在寄存器重命名方法中,一组扩展的物理寄存器用于保存架构上可见的寄存器和临时值。因此,扩展的登记册取代了ROB和预订站的大部分功能;只需要一个队列来确保指令按顺序完成。在指令发出期间,重命名过程将架构寄存器的名称映射到扩展寄存器集中的物理寄存器编号,为目标分配一个新的未使用的寄存器。通过重命名目标寄存器来避免 WAW 和 WAR 危害,并处理推测恢复
每个时钟出现更多问题的挑战
投机多少
通过多个分支进行投机
能源效率的投机和挑战
地址混叠预测
贯穿各领域的问题
硬件与软件的推测
本章中的硬件密集型推测方法和附录 H 中的软件方法提供了利用 ILP 的替代方法。下面列出了这些方法的一些权衡和限制:
- 为了进行广泛的推测,我们必须能够消除内存引用的歧义。对于包含指针的整数程序,此功能在编译时很难实现。在基于硬件的方案中,内存地址的动态运行时消歧是使用我们之前看到的 Tomasulo 算法的技术完成的。这种消除歧义允许我们在运行时将加载移动到存储之间。对推测内存引用的支持有助于克服编译器的保守性,但除非谨慎使用这些方法,否则恢复机制的开销可能会淹没优势。
- 当控制流不可预测,并且基于硬件的分支预测优于在编译时完成的基于软件的分支预测时,基于硬件的推测效果更好。这些属性适用于许多整数程序,其中动态预测变量的错误预测率通常小于静态预测变量错误预测率的一半。由于当预测不正确时,推测的指令可能会减慢计算速度,因此这种差异很大。这种差异的一个结果是,即使是静态调度的处理器通常也包括动态分支预测器。
- 基于硬件的推测即使对于推测的指令也是如此,也保持了完全精确的异常模型。最近基于软件的方法也增加了特殊支持,以实现这一点。
- 基于硬件的投机不需要补偿或记账代码,而这是雄心勃勃的软件投机机制所需要的。
- 基于编译器的方法可能受益于能够更深入地查看代码序列,从而比纯粹的硬件驱动方法更好地进行代码调度。
- 具有动态调度的基于硬件的推测不需要不同的代码序列即可为不同的实现良好的性能架构。虽然这种优势是最难量化的,但从长远来看,它可能是最重要的优势。有趣的是,这是 IBM 360/91 的动机之一。另一方面,较新的显式并行架构(如 IA-64)增加了灵活性,减少了代码序列中固有的硬件依赖性。
在硬件中支持推测的主要缺点是复杂性和所需的额外硬件资源。必须根据基于软件的方法的编译器的复杂性以及依赖于此类编译器的处理器中简化的数量和有用性来评估此硬件成本。
一些设计人员试图将动态方法和基于编译器的方法结合起来,以实现每种方法的最佳效果。这样的组合可以产生有趣而晦涩的互动。例如,如果条件移动与寄存器重命名相结合,则会出现微妙的副作用。被取消的条件移动仍必须将值复制到目标寄存器,因为它已在指令管道的前面重命名。这些微妙的相互作用使设计和验证过程复杂化,还可能降低性能。
英特尔安腾处理器是有史以来最雄心勃勃的计算机,基于对 ILP 和推测的软件支持而设计。它没有实现设计者的希望,特别是对于通用的、非科学的代码。由于第244页所描述的困难,设计人员利用ILP的雄心壮志被降低,大多数架构都选择了基于硬件的机制,每个时钟的发出率为三到四条指令。
推测执行和记忆系统
支持推测执行或条件指令的处理器固有的,是生成无效地址的可能性,如果没有推测执行,这些地址就不会发生。如果采取保护异常,这不仅是不正确的行为,而且推理执行的好处也会被错误的异常开销所淹没。因此,内存系统必须识别推测执行的指令和有条件执行的指令,并抑制相应的异常。
通过类似的推理,我们不能允许这样的指令导致缓存在未命中时停止,因为同样,不必要的停止可能会压倒推测的好处。因此,这些处理器必须与非阻塞缓存匹配。
实际上,DRAM的未命中惩罚是如此之大,以至于只有当下一级是片上缓存(L2或L3)时,才会处理推测的未命中。第 84 页的图 2.5 显示,对于一些表现良好的科学程序,编译器可以承受多个未完成的 L2 未命中,以有效地减少 L2 未命中的惩罚。同样,要做到这一点,缓存后面的内存系统必须在同时进行内存访问的数量方面与编译器的目标相匹配。
多线程:利用线程级并行性提高单处理器吞吐量
多线程是一种技术,其中多个线程共享一个处理器,而无需干预进程切换。在线程之间快速切换的能力使多线程能够用于隐藏管道和内存延迟。
多线程允许多个线程以重叠的方式共享单个处理器的功能单元。相比之下,利用线程级并行性 (TLP) 的更通用方法是使用具有多个独立线程同时并行运行的多处理器。但是,多线程不会像多处理器那样复制整个处理器。相反,多线程在一组线程之间共享大部分处理器内核,仅复制专用状态,例如寄存器和程序计数器。正如我们将在第 5 章中看到的那样,许多最近的处理器在单个芯片上集成了多个处理器内核,并在每个内核内提供多线程。
复制处理器内核的每线程状态意味着为每个线程创建单独的寄存器文件和单独的 PC。内存本身可以通过虚拟内存机制共享,该机制已经支持多次并发。此外,硬件必须支持相对较快地切换到不同线程的能力;特别是,线程开关应该比进程开关效率高得多,进程开关通常需要数百到数千个处理器周期。当然,对于多线程硬件来说,要实现性能提升,一个程序必须包含多个线程(我们有时说应用程序是多线程的),这些线程可以并发执行。这些线程由编译器(通常来自具有并行结构的语言)或程序员标识。
多线程处理有三种主要的硬件方法:细粒度、粗粒度和同时。细粒度多线程在每个时钟周期的线程之间切换,导致来自多个线程的指令的执行交错。这种交错通常以循环方式完成,跳过当时停滞的任何线程。细粒度多线程的一个关键优点是,它可以隐藏短停顿和长停顿引起的吞吐量损失,因为当一个线程停顿时,可以执行来自其他线程的指令,即使停顿只持续了几个周期。细粒度多线程的主要缺点是它减慢了单个线程的执行速度,因为准备执行而不会停顿的线程会被来自其他线程的指令延迟。它以多线程吞吐量的增加换取单个线程的性能损失(以延迟衡量)。
在细粒度的情况下,线程的交错可以消除完全空的插槽。此外,由于发出线程在每个时钟周期都会更改,因此可以隐藏较长的延迟操作。由于指令发出和执行是相互关联的,因此线程只能发出与已准备好的指令数量一样多的指令。对于较窄的问题宽度,这不是问题(一个周期要么被占用,要么没有被占用),这就是为什么细粒度多线程非常适合单个问题处理器,而 SMT 则毫无意义。事实上,在 Sun T2 中,每个时钟有两个问题,但它们来自不同的线程。这样就无需实施复杂的动态调度方法,而是依赖于使用更多线程隐藏延迟。
如果在多问题动态调度处理器之上实现细粒度线程,则结果为 SMT。 在所有现有的 SMT 实现中,所有问题都来自一个线程,尽管来自不同线程的指令可以在同一周期内启动执行,使用动态调度硬件来确定哪些指令已准备就绪。尽管图 3.31 大大简化了这些处理器的实际操作,但它确实说明了多线程在一般情况下和 SMT 在更广泛的动态调度处理器中的潜在性能优势。
同时多线程利用以下见解:动态调度的处理器已经具有支持该机制所需的许多硬件机制,包括大型虚拟寄存器集。多线程可以在无序处理器之上构建,方法是添加每个线程重命名表,保留单独的 PC,并提供来自多个线程的指令提交功能。
超标量处理器上同步多线程的有效性