Skip to content

第一章 - 量化设计与分析基础

约 6755 个字 预计阅读时间 23 分钟

引言

在过去一段时间,有两个重要的半导体工艺规律被提出:

  • 登纳德缩放比例定律 (Dennard scaling):因为晶体管尺寸的缩小,即使增加晶体管的数量,对于给定的硅面积,功率面积也是恒定的。

这一定律在 2004 年左右失效,因为无法在减小电流和降低电压的同时,仍然保持集成电路的可靠性。

  • 摩尔定律 (Moore's Law):芯片上可容纳的晶体管数量每隔两年翻一番。

这一定律在 2010 年后不再成立。

以下四个原因导致了处理器性能的提升速度放缓:

  • 由于摩尔定律的放缓和登纳德缩放比例定律的终结,晶体管不再大幅改进。
  • 微处理器的功耗预算不变。
  • 用多个高能效处理器代替了单个大功耗的处理器。
  • 多重处理已达到 Amdahl 定律的上限。

计算机的分类

由于上述变化,如今我们对计算机的看法也发生了变化。总的来说,我们将计算机设备分为五类,如下表:

物联网 / 嵌入式计算机

嵌入式计算机在日用电器中随处可见。物联网 (Internet of Things, IoT) 指的是通常以无线方式连接到互联网的嵌入式计算机。

个人移动设备

个人移动设备 (personal mobile device, PMD) 是指带有多媒体用户界面的无线设备,比如手机、平板计算机等。

PMD 中的处理器经常被视为嵌入式计算机,但我们将其看作一个单独的类别,这是因为 PMD 是可以运行外部开发软件的平台,它们与桌面计算机有许多共同特征。其它嵌入式设备在硬件和软件复杂性方面都有很大的限制。我们将能否运行第三方软件作为区分嵌入式计算机和非嵌入式计算机的标准。

相应性能和可预测性能是多媒体应用程序的关键特征。实时性能 (real-time performance) 需求是指应用程序的一个程序段有一个确定的最大执行时间。

桌面计算机

在整个价格与性能范围内,桌面计算机 (desktop computing) 市场趋向于寻求最优性价比 (price-performance)。

服务器

随着个人计算机的普及,服务器 (servers) 的角色逐渐变为提供更大规模、更可靠的文件和计算服务。

服务器的关键特征不同于桌面计算机:

  • 可用性:服务器往往需要长时间不间断地工作,且鉴于其承担的任务,单次宕机带来的损失总是巨大的。
  • 可扩展性:服务器系统经常需要扩展,以满足对其所支持服务的日益增长的需求,或者应对日益增加的功能需求。
  • 高吞吐能力:服务器的整体性能(单位时间内处理的事务数或提供的网页数)很重要,因为总体效率和成本效益是大多数服务器的关键指标。

集群 / 仓库级计算机

软件即服务 (SaaS) 应用(如搜索、社交网络、多人游戏等)的发展推动了一类被称作集群 (clusters) 的计算机的发展。集群是指一组桌面计算机或服务器通过局域网连接在一起,每个节点都运行自己的操作系统,节点之间使用网络协议进行通信。最大规模的集群称作仓库级计算机 (WSC),其设计方式使数万台服务器像一台服务器一样运行。

WSC 同样非常看重可用性。而 WSC 的可扩展性是由连接这些计算机的局域网实现的,而不是像服务器那样通过集成计算机硬件来实现。

超级计算机 (Supercomputers) 与 WSC 有一定的相似性,但超级计算机强调浮点性能,运行大型的、通信密集的批程序,这些程序可能会一次运行几个星期;而 WSC 强调交互式应用程序、大规模存储、可靠性和高互联网带宽。

并行度与并行体系结构的分类

在所有计算机类别中,多种级别的并行度已成为计算机设计的驱动力,而能耗和成本则是主要约束。

应用程序中主要有以下两种并行:

  • 数据集并行 (DLP):使许多数据项可以同时操作。
  • 任务级并行 (TLP):使创建的工作任务可以单独执行并且主要采用并行方式执行。

计算机硬件又以以下四种主要方式来利用这两种类型的应用并行:

  • 指令级并行 (instruction-level parallelism):在两个层面对数据级并行进行了利用,首先在编译器的帮助下,借助流水线之类的思想适度利用,其次借助推测执行 (speculative execution) 之类的思想进一步利用。
  • 向量体系结构、图形处理器 (graphic processor unit, GPU) 和多媒体指令集 (multimedia instruction set):将单条指令并行应用于一组数据,以利用数据集并行。
  • 线程级并行 (thread-level parallelism):在一种紧耦合硬件模型中利用数据集并行或任务及并行,这种模型允许并行线程之间进行交互。
  • 请求级并行 (request-level parallelism) 利用程序员或操作系统指定的大量解耦任务之间的并行性。

Michael Flynn 在研究并行计算工作量时,针对数据级并行和任务级并行提出了一种简单的分类方式,这种方式将计算机划分为以下四类:

  • 单指令流单数据流 (single instruction stream, single data stream, SISD):这个类别是单处理器,我们把它看作标准的顺序计算机,但可以利用指令级并行。
  • 单指令流多数据流 (single instruction stream, multiple data stream, SIMD):同一指令由多个使用不同数据流的处理器执行。这类计算机利用数据级并行,对多个数据项并行执行相同的操作。每个处理器都有自己的数据存储器,但只有一个指令存储器和控制处理器,用于提取和分派指令。
  • 多指令流单数据流 (multiple instruction stream, single data stream, MISD):到目前为止还没有这种类型的商用多处理器。
  • 多指令流多数据流 (multiple instruction stream, multiple data stream, MIMD):每个处理器都提取自己的指令,对自己的数据进行操作,其针对的是任务级并行。为实现这一目标,一些体系结构利用线程级并行,即紧耦合 MIMD 体系结构;一些体系结构利用请求级并行,即松耦合 MIMD 体系结构(常用于集群和仓库级计算机)。

计算机体系结构的定义

指令集体系结构

在几十年前,计算机体系结构的核心就是指令集体系结构 (instruction set architecture, ISA),即程序员可以看到的实际指令集。ISA 相当于软件和硬件之间的界线。

这一部分内容请参阅计算机组成 - 第二章 - 指令,在那里我们讨论了指令集设计的一般逻辑,并以 RISC-V 为例介绍了一个完整的指令集。

计算机体系结构

计算机的实现包括两个方面:组成和硬件。

组成 (organization) 包括了计算机设计的高阶内容,如存储器系统、存储器互联、内部处理器或 CPU 的设计。有时也使用微体系结构 (microarchitecture) 以此来指代这一部分内容。

由于单个微处理器上开始采用多个处理器,所以人们开始使用 (core) 一次来称呼处理器,用多核 (multicore) 处理器来称呼多处理器微处理器。

硬件 (hardware) 是指计算机的具体实现,包括计算机的详尽逻辑设计和封装技术。

在这节课中,计算机体系结构 (computer architecture) 涵盖了计算机设计的所有三个方面:

  • 指令集体系结构
  • 组成或微体系结构
  • 硬件

技术趋势

以下 5 种实现技术是现代计算机实现所不可或缺的:

  • 集成电路逻辑技术
  • 半导体 DRAM
  • 半导体闪存
  • 磁盘技术
  • 网络技术

性能趋势

带宽 (bandwidth) 和吞吐量 (throughput) 是指在给定时间内完成的总工作量。延迟 (latency) 和响应时间 (response time) 是指一个事件从开始到完成所经过的时间。

性能是微处理器和网络的主要区别,在过去几十年间取得了最大的改进。对存储器和磁盘来说,通量通常比性能更重要,所以容量增加得更多。

显然,在这些技术的发展过程中,带宽的改进速度超过延迟,而且这一趋势很可能会持续下去。一个简单的经验法则是:带宽的增加速度至少是延迟改进速度的平方。

晶体管性能与连线的发展

集成电路的制造工艺是用特征尺寸 (feature size),即一个晶体管或一条连线在 x 轴或 y 轴方向的最小尺寸来衡量的。当特征尺寸线性减小时,晶体管密度将呈二次方增长。

晶体管性能的提升相对复杂。大致来说,晶体管性能的提高与特征尺寸的减小呈线性关系。

当特征尺寸减小时,晶体管性能线性提升,而晶体管数目却呈二次方增加。

尽管晶体管的性能通常会随特征尺寸的减小而提升,但集成电路中的连线却不会如此。具体来说,一段连线的信号延迟与其电阻和电容的乘积成正比。而当特征尺寸减小时,连线会变短,但单位长度的电阻和电容都会变差。

一般来说,与晶体管性能相比,连线延迟方面的改进相对很小。因此在过去几年中,除了功耗限制之外,连线延迟已经成为大型集成电路的主要涉及障碍,而且往往比晶体管开关延迟还要关键。信号在连线上的传播延迟消耗了越来越多的时钟周期,而功耗对时钟周期的影响大于连线延迟。

集成电路中的功耗和能耗趋势

如今,对于几乎所有类型的计算机来说,能耗都是计算机设计人员面对的最大挑战。

功耗和能耗:系统视角

从系统架构师的角度来看,功耗和能耗有 3 个主要关注事项:

  1. 处理器所需的最大功耗
  2. 持续功耗,或热设计功耗 (thermal design power, TDP)
  3. 能耗和能效:功耗是单位时间的能耗,执行一项工作负载的能耗等于平均功耗乘以此项工作负载的执行时间。

相比功耗,能耗更适合用来对比处理器性能。能耗更低的处理器执行任务更高效。

微处理器内部的能耗和功耗

对 CMOS 芯片来说,传统的主要能耗源是开关晶体管,也称作动态能耗 (dynamic energy)。每个晶体管的能耗和该晶体管驱动的容性负载与电压平方的乘积成正比,即:

\[\text{能耗}_{\text{动态}} \propto \text{容性负载} \times \text{电压}^{2}\]

这个公式的计算结果是完整逻辑转换 \(0 \to 1 \to 0\)\(1 \to 0 \to 1\) 的能耗。那么一次转换(\(0 \to 1\)\(1 \to 0\))的能耗就是:

\[\text{能耗}_{\text{动态}} \propto \frac{1}{2} \times \text{容性负载} \times \text{电压}^{2}\]

每个晶体管所选哟的功耗就是一次转换的能耗与转换频率的乘积:

\[\text{功耗}_{\text{动态}} \propto \frac{1}{2} \times \text{容性负载} \times \text{电压}^{2} \times \text{开关频率}\]

对于一项固定任务,降低时钟频率可以降低功耗,但不会降低能耗。

显然,通过降低电压可以大幅降低动态功耗和能耗,这一点在过去数十年中已经得到的充分的应用。

根据上述公式,如果不能降低电压或提高每个芯片的功耗,那么可能就要减缓时钟频率的增长速度。这一趋势在过去二十年间已经出现。

现代微处理器也出现了很多新兴技术,以试图在时钟频率和电源电压保持不变的情况下提高能效:

  1. 以逸待劳:关闭非活动模块的时钟,以降低能耗和动态功耗。
  2. 动态电压-频率调整 (dynamic voltage-frequency scaling, DVFS):根据设备实际承担的任务情况,降低运行的电压和频率。
  3. 针对典型情景的设计:设计专门的低功耗模式。
  4. 超频:在超频模式中,芯片可以判定在少数几个核上以较高时钟频率短时运行时安全的,直到温度开始上升为止。

尽管通常认为动态功耗是 CMOS 中功耗的主要来源,但由于即使晶体管处于关闭状态也存在泄漏电流,所以静态功耗也逐渐成为一个重要问题:

\[\text{功耗}_{\text{静态}} \propto \text{电流}_{\text{静态}} \times \text{电压}\]

也就是说,静态功耗与期间数目成正比。

因此,如果增加晶体管数目,那么在空闲状态也会增加功耗。一个自然的设计是关闭非活动模块的电源,即电源门控 (power gating),以控制由泄漏电流导致的损失。

最后,由于处理器只是系统整体能耗中的一部分,所以如果使用一个速度较快但能效较低的处理器,使系统的其它部分能够进入睡眠模式,可能有助于降低整体能耗。这种策略称作竞相暂停 (rase-to-halt)。

计算机体系结构因为能耗限制而发生的变化

在当下,许多微处理器的晶体管数量是如此之多,以至于为了满足给定的能耗预算而不能同时开启所有的晶体管。这种现象称作暗硅 (dark silicon)。

因此,计算机架构师转向了一个新的设计原理:将任务的平均能耗降至最低。

成本趋势

时间、产量和大众化的影响

即使基本的实现技术没有取得任何重大进步,计算机组件的制造成本也会随时间推移而降低。成本下降背后的基本原理是学习曲线 (learning curve),即制造成本随时间的推移而降低。学习曲线本身是根据良率 (yield) 的变化测得的。当良率提升,成本就能降低。

产量是决定成本的第二个重要因素。产量的提高减少了完成学习曲线所需的时间,同时提高购买和制造效率。一些设计人员根据经验估计,产量没增加一倍,成本会下降大约 10%。

大众化商品 (commodity) 是指由多家供应商大量出售且基本相同的产品。这种商品的市场竞争非常激烈,从而缩小成本与售价之间的距离,并降低成本。

集成电路的成本

随着个人移动设备越来越依赖整体片上系统 (systems on a chip, SOC),集成电路的成本已经成为个人移动设备成本的主题。

基本的硅制造工艺在过去数十年间没有发生变化:对晶圆 (wafer) 进行测试,并切割成镜片 (die) 进行封装。因此,一个已封装集成电路的成本为:

\[\text{集成电路的成本} = \frac{\text{晶片成本} + \text{晶片测试成本} + \text{封装与最终测试成本}}{\text{最终测试良率}}\]

单个晶片成本的预测可以根据以下公式:

\[\text{晶片成本} = \frac{\text{晶圆成本}}{\text{每个晶圆上的晶片数} \times \text{晶片良率}}\]

每个晶圆上的晶片数大约等于晶圆面积除以晶片面积,一个相对准确的估算公式是:

\[\text{每个晶圆上的晶片数} = \frac{\pi \times \left( \frac{\text{晶圆直径}}{2} \right)^{2}}{\text{晶片面积}} - \frac{\pi \times \text{晶圆直径}}{\sqrt{2 \times \text{晶片面积}}}\]

另一方面,我们还需要估算晶片的良率,公式如下:

\[\text{晶片良率} = \text{晶圆良率} \times \frac{1}{(1 + \text{单位面积上的缺陷} \times \text{晶片面积})^{N}}\]

晶圆的良率考虑了完全损坏的晶圆,我们一般直接假定为 \(100\%\)

对于计算机设计人员来说,制造工艺决定了晶圆成本、晶圆良率和单位面积上的缺陷数,所以设计人员唯一能够控制的就是晶片面积。

可信任度

如何判断一个系统的运行是否正常,这是一个难题。随着互联网服务的普及,基础设施供应商开始提供服务等级协议 (service level agreement, SLA) 或服务等级目标 (service level objective, SLO),以保证其服务是可靠的。因此,我们可以使用 SLA 来判断系统是正常运行还是已经宕机。

系统在 SLA 规定的两种服务状态之间切换:

  1. 服务完成:即提供了指定服务。
  2. 服务中断:即所提供的服务与 SLA 不一致。 、 两种状态之间的转换由故障 (failures) 或恢复 (restorations) 导致。对这两种转换进行量化,即可以得到可信任度的两种主要度量。

  3. 模块可靠性 (module reliability) 是对从参考初始时刻开始的连续的服务完成情况的度量。因此平均无故障时间 (mean time to failure, MTTF) 是一种可靠性度量,其倒数即为故障率,通常以运行 10 亿小时发生的故障树来表示,被称作 FIT (failures in time)。服务中断用平均修复时间 (mean time to repair, MTTR) 来度量。平均故障间隔时间 (mean time between failures, MTBF) 就是 MTTF 与 MTTR 之和。

  4. 模块可用性 (module availability) 是指在服务完成与服务中断两种状态之间切换时,对服务完成情况的度量。有如下公式:
\[\text{模块可用性} = \frac{\text{MTTF}}{\text{MTTF} + \text{MTTR}}\]

设磁盘子系统的组件及 MTTF 如下:

  • 10 个磁盘,各自的等级为 1000000 小时 MTTF
  • 1 个 ATA控制器,500000 小时 MTTF
  • 1 个电源,200000 小时 MTTF
  • 1 个风扇,200000 小时 MTTF
  • 1 跟 ATA 电缆,1000000 小时 MTTF

假设生存期呈指数分布,各故障相互独立。试计算整个系统的 MTTF。

故障率之和为:

\[\text{故障率}_{\text{系统}} = 10 \times \frac{1}{1000000} + \frac{1}{500000} + \frac{1}{200000} + \frac{1}{200000} + \frac{1}{1000000} = \frac{23000}{1000000000}\]

\(23000\) FIT。MTTF 即为其倒数:

\[\text{MTTF}_{\text{系统}} = \frac{1}{\text{故障率}_{\text{系统}}} = \frac{1000000000}{23000} \approx 43478 \mathrm{h}\]

应对故障的主要方法是冗余,可以是时间冗余(重复操作以查看是否仍然存在错误)或资源冗余(当一个组件发生故障时由其他组件接管)。

沿用前例的参数,现在我们添加一个冗余电源。假设操作人员平均需要 \(24 \mathrm{h}\) 才能修复电源,试计算现在整个系统的可靠性。

由于我们有两个电源且故障独立,所以在一个电源发生故障之前的平均时间为 \(\frac{\text{MTTF}_{\text{电源}}}{2}\)。发生第二个故障的概率有一个很好的近似,用 MTTR 除以另一个电源的 MTTF。因此电源对的 MTTF 如下式:

\[\text{MTTF}_{\text{电源对}} = \frac{\frac{\text{MTTF}_{\text{电源}}}{2}}{\frac{\text{MTTR}_{\text{电源}}}{\text{MTTF}_{\text{电源}}}} = \frac{\text{MTTF}^{2}_{\text{电源}}}{2 \times \text{MTTR}_{\text{电源}}}\]

代入数据可以求得:

\[\text{MTTF}_{\text{电源对}} = \frac{200000^{2}}{2 \times 24} \approx 833333333\]

这是单个电源可靠度的大约 4150 倍。

性能的测量、报告和汇总

对于不同的计算用户,其关心的性能特征不同。一些用户关心的是响应时间 (response time),或称执行时间 (execution time),即一个事件从启动到完成的时间。另一些用户关注的是吞吐量 (throughput),即给定时间内完成的总工作量。

在对比不同的设计时,我们通常需要比较其性能的差距,这一般是通过比较执行时间得到的。具体来说,计算机 X 的性能是计算机 Y 的 \(n\) 倍对应下式:

\[n = \frac{\text{执行时间}_{Y}}{\text{执行时间}_{X}} = \frac{\frac{1}{\text{性能}_{Y}}}{\frac{1}{\text{性能}_{X}}} = \frac{\text{性能}_{X}}{\text{性能}_{Y}}\]

然而,执行时间也有不同的定义方式。最直接的定义称作挂钟时间 (wall-clock time)、响应时间或已用时间 (elapsed time),也就是完成一项任务的总延迟。另一个定义是 CPU 时间 (CPU time),即处理器执行计算的时间,而不包含等待输入输出或运行其它程序的时间。

基准测试

性能的最佳基准测试方法是采用实际的应用程序。常见的基准测试有:

  1. 桌面基准测试
  2. 服务器基准测试

报告性能测试结果

在报告性能测试结果时,应当遵循一个重要的原则,即可再现性 (reproducibility)。

性能结果汇总

一旦我们选用一种基准测试套件来测量性能,就希望能够用一个数值来汇总套件的性能结果。计算汇总结果的一种简单方法是对比套件中各个程序执行时间的算术平均值。另一种方法是为每个基准测试增加一个加权因子,以加权算术平均值作为总结性能的唯一数值。

当然,也可以不选择权重,而是以基准计算机为依据,对执行时间进行归一化。我们将基准计算机上的执行时间除以评估计算机上的执行时间,就可以得到一个与性能成正比的壁纸。SPEC(标准性能评估机构)就是使用这种方法,它将这个比值称作 SPECRatio。这是一个特别有用的特性,

例如假定在进行基准测试时,计算机 A 的 SPECRatio 是计算机 B 的 \(1.25\) 倍,于是可以得到如下关系:

\[1.25 = \frac{\text{SPECRatio}_{A}}{\text{SPECRatio}_{B}} = \frac{\frac{\text{执行时间}_{\text{基准}}}{\text{执行时间}_{A}}}{\frac{\text{执行时间}_{\text{基准}}}{\text{执行时间}_{B}}} = \frac{\text{执行时间}_{B}}{\text{执行时间}_{A}} = \frac{\text{性能}_{A}}{\text{性能}_{B}}\]

因为 SPECRatio 是一个比值,而不是绝对执行时间,所以必须用几何平均值来计算其均值。

计算机设计的量化原理

充分利用并行

充分利用并行是提高性能的重要方法之一,这在各个层次上都是适用的。

局部性原理

一个重要的程序特性是局部性原理 (principle of locality):程序常常复用其最近用过的数据和指令。

时间局部性 (temporal locality) 是指最近访问过的内容很可能会在短期内被再次访问。空间局部性 (spatial locality) 是指地址向邻近的项往往会在相近的时间被用到。

重点关注常见情形

如果某一情形会频繁出现,那对其进行改进会产生更为显著的效果。

Amdahl 定律

Amdahl 定律定义了使用特定功能可获得的加速比 (speedup)。假定我们可以对某一计算机进行某种改进,从而提高它的性能,则加速比的定义为:

\[\text{加速比} = \frac{\text{整个任务在采用该项改进时的性能}}{\text{整个任务在未采用该项改进时的性能}} = \frac{\text{整个任务在未采用该改进时的执行时间}}{\text{整个任务在采用该改进时的执行时间}}\]

加速比告诉我们,在改进后的计算机上运行一个任务比在原计算机上快多少。

加速比取决于下面两个因素:

  1. 原计算机计算时间中可改进部分所占的比例。我们称这个值为改进比例 (enhanced fraction)
  2. 通过改进执行模式得到的改进,也就是说在为整个程序使用这一执行模式时,任务的运行速度会提高多少倍。我们称这个值为改进加速比 (enhanced speedup)

于是我们有:

\[\text{新执行时间} = \text{原执行时间} \times \left( (1 - \text{改进比例}) + \frac{\text{改进比例}}{\text{改进加速比}} \right)\]

总加速比是这两个执行时间之比:

\[\text{总加速比} = \frac{\text{原执行时间}}{\text{新执行时间}} = \frac{1}{(1 - \text{改进比例}) + \frac{\text{改进比例}}{\text{改进加速比}}}\]

Amdahl 定律表明,使用某种快速执行模式获得的性能改进受限于可使用此种模式的时间比例。同时,它也阐述了汇报递减规律:如果仅改进一部分计算的性能,那么在增加改进时,所获得的加速比增量会逐渐减小,而且最后会达到一个上线。

处理器性能公式

基本所有计算机都有一个以固定频率运行的时钟,于是我们就有一个离散的时间事件,称作时钟周期 (clock cycle)。

程序的 CPU 时间计算如下:

\[\text{CPU 时间} = \text{程序的 CPU 时钟周期数} \times \text{时钟周期时间} = \frac{\text{程序的 CPU 时钟周期数}}{\text{时钟频率}}\]

除了执行一个程序所需的时钟周期数之外,我们还可以计算所执行的指令数 (instruction count, IC)。然后进一步就可以计算每条指令的时钟周期数 (clock cycles per instruction, CPI) 的平均值,或者其倒数每时钟周期指令数 (instructions per clock)。

CPI 的计算公式为:

\[\text{CPI} = \frac{\text{程序的 CPU 时钟周期数}}{\text{指令数}}\]

通过变换以上公式中的指令数,可以得到:

\[\text{CPU 时间} = \text{指令数} \times \text{CPI} \times \text{时钟周期时间}\]