全文是学习计算机体系结构 量化研究方法(第5版)中文版 时的笔记摘抄,如有错误,请阅读原书,还有错误,请阅读英文原书。
引言
指令级并行(ILP)的汇报降低,单处理器发展缓慢,引入了计算机体系结构的一个新的时代,线程级并行(TLP)。
TLP意味着存在多个程序计数器,因此主要通过MIMD加以开发。
这一章的重点是多处理器——由紧耦合处理器组成的计算机,这些处理器的协调与使用由单一处理器系统控制,通过共享地址空间来共享处理器。
- 两种不同的软件模型来开发TLP:
- 并行处理
运行一组紧密耦合的线程,协同完成同一任务 - 多重编程
执行可能由一或多为用户发起的多个相对独立的进程,这是一种请求级并行形式
- 并行处理
根据所包含的处理器数量,将共享存储器的多处理器分为两类(按照存储器组织方式来称呼多处理器的):
- 对称(共享存储器)多处理器(SMP),或集中式共享存储器多处理器
- 核心数量较少,通常不超过8个
- SMP体系结构有时也称为一致存储器访问(UMA)多处理器
- 所有处理器访问存储器的延迟都是一致的
- 分布式共享存储器多处理器(DSM)
- 为了支持更多处理器,存储器必须分散在处理器之间,而不是集中式的;否则,存储器系统就无法在不大幅延长访问延迟的情况下为大量处理器提供带宽支持
- DSM多处理器也称为NUMA(非一致存储器访问)
- 因为他的访问时间取决于数据字在存储器中的位置
在SMP和DSM这两种体系结构中,线程之间的通信是通过共享地址空间完成的,与SMP和DSM相关联的共享存储器一词,指的是共享地址空间这一事实。
5.2 集中式共享存储器体系结构(SMP)
多处理器缓存一致性问题
执行下面一串事件后,会发现处理器B中的内容和共享存储器中x的内容不一致!
时间 | 事件 | 处理器A中的内容 | 处理器B中的内容 | 位置x的存储内容 |
---|---|---|---|---|
0 | 1 | |||
1 | 处理器A读x | 1 | 1 | |
2 | 处理器B读x | 1 | 1 | 1 |
3 | 处理器A将0存到x | 0 | 1 | 0 |
存在一致性问题是因为既拥有全局状态(主要有主存储器决定),又拥有本地状态(由各个缓存确定,它是每个处理器核心专用的)
- 通俗的说如果在每次读取某一数据项时都会返回该数据项的最新写入值,那就说这个存储系统是一致的
这个定义包含存储器系统行为的两个方面:- 一致性(coherence)
它确定了读取操作可能返回什么值 - 连贯性(consistency)
它确定了一个写入值什么时候被读取操作返回
- 一致性(coherence)
- 如果存储系统满足以下条件,则说它是一致的:
- 处理器P读取位置X,若在此之前是由P对X进行写入,且中间没有其他处理器对位置X执行写入操作,则此读取操作总是返回P写入的值;
- 一个处理器向位置X执行写入操作后,另一个处理器读取该位置,若中间时间间隔足够长,且没有其他处理器写入位置X,则此读取操作总是返回写入值;
- 对同一位置执行的写入操作被串行化。也就是说,对所有处理器看来,任意两个处理器对相同位置的两次写入操作是相同顺序。
- 第一个特性只是保持了程序顺序——即使在单处理器中,也希望具备这一特性
- 第二个特性定义了一致性存储器视图的含义:如果处理器可能持续读取到一个旧数据值,我们就能明确的说该处理器是不一致的;
- 第三个特性被称为写入操作串行化。
- 尽管三条属性足以确保一致性,但是什么时候可以看到写入值也是一个很重要的问题
- 写入值在多久之后必须能被读取操作读到,这一问题由存储器连贯性模型回答(5.6节)。
一致性的基本实现方案
- 缓存一致性协议分为两类:
- 目录式
特定物理存储器块的共享状态保存的位置称为目录。
SMP中,可以使用一个集中目录;
在DSM中,单个目录会生成单个争用点,使用分布式目录; - 监听式
如果一个缓存拥有某一物理存储器块中的数据副本,它就可以跟踪该块的共享状态,而不是将共享状态保存在同一个目录中。
SMP中,所有缓存通过某种广播介质访问,所有缓存控制器都监听这一介质,以确定自己是否拥有该总线或交换访问上所请求块的副本。
监听一致性协议
- 两种方法可以满足一致性需求:
- 写入失效协议
确保处理器在写入某一数据项之前,获取对该数据项的独占访问;
因为它在执行写入操作时会使其他副本失效,不存在该数据项的其他可读或可写副本。
一个例子:
时间 处理器活动 总线活动 处理器A中的内容 处理器B中的内容 位置x的存储内容 0 0 1 处理器A读x 缓存中没有x的内容 0 0 2 处理器B读x 缓存中没有x的内容 0 0 0 3 处理器A将1存到x 对x失效 1 0 4 处理器B读x 缓存中没有x的内容 1 1 1 - 写入更新或写入广播协议
在写入一个数据项时更新该数据的所有缓存副本;
由于要将写入操作更新到共享缓存项上,占用相当多的带宽,效果不好
- 写入失效协议
基本实现技术
- 实现失效协议的关键在于使用总线或其他广播介质来执行失效操作。
- 为了执行一项失效操作,处理器只获得总线访问,并在总线上广播要使其失效的地址
- 所有处理器持续监听该总线,检查总线上的地址是否在自己的缓存中
- 如果在,则使缓存中相应数据失效
- 在写入一个共享块时,执行写入操作的处理器必须先获取总线访问权限来广播使其失效
- 如果两个处理器尝试同时写入块,会在争用总线时串行安排他们的广播失效操作
- 如果他们写的是同一块,那由总线实现写入操作的串行化
- 所有一致性机制都需要某种方法来串行化对同一缓存块的访问,具体方式可以是串行化对通信介质的访问,也可以是对另一共享结构访问的串行化
在发生缓存缺失时定位数据项的问题
- 对于是直写缓存,在存储器中的即为数据最新值
- 对于写回缓存,数据项的最新值可能在专用缓存中,写回缓存为缓存缺失和写入操作使用相同的监听机制:
- 每个处理器都监听放在共享总线上的所有地址
- 如果处理器发现自己拥有被请求缓存块的脏副本,他会提供该缓存块以回应读取请求,并终止存储器访问。
由于必须从另一个处理器的专用缓存(L1或L2)提取缓存块,所以增加了复杂性,这一提取过程花费的时间通常长于从L3进行提取的时间。
由于写回缓存对存储器带宽的需求较低,所以他可以支持更多、更快速的处理器。 - 通常的缓存标记可以用来实施监听过程,每个块的有效位使失效操作的实施非常轻松;
- 若要跟踪缓存块是否被共享,可以为每个缓存块添加一个相关状态位,就像有效位和重写位一样
- 对处于共享状态的块进行写入时,该缓存在总线上生成时效操作,将这个块标记为独占
- 如果一个缓存块只有唯一副本,则拥有该唯一副本的核心通常被称为该缓存块的拥有者。
示例协议
- 监听一致性协议通常是通过在每个核心中整合有限状态控制器来实施的。
- 这个控制器回应由核心中的处理器和由总线(或其他广播介质)发出的请求,改变所选缓存块的状态,并使用总线访问数据或使其失效。
- 实现监听协议时可以使用任意互连网络,只要其能够像所有一致性控制器及其相关专用缓存进行广播即可。
- 简单协议有三种状态: 无效、共享、已修改
- 无效表明专用缓存中的块可能被共享;
- 共享表明专用缓存中的块被共享;
- 已修改表明已经在专用缓存中更新了这个块;(隐含表明这个块是独占的)
- 一个写回缓存的、写入失效协议的例子(MSI):
- P267
- 这个协议假定所有操作具有原子性
基本一致性协议的扩展
- MESI 向MSI协议添加了“独占”(Exclusive)状态
- 独占表示缓存块仅驻存在一个缓存中,而且是清洁的
- 清洁代表——与共享缓存中的一致(
个人理解,可能不对)
- 清洁代表——与共享缓存中的一致(
- 添加这一状态的好处在于:
- 在由同一核心对于独占状态的块进行后续写入时,不需要访问总线,也不会生成失效操作,因为处理器知道这个块在这个本地缓存中是独占的,处理器只是将状态改为已修改。
- 独占表示缓存块仅驻存在一个缓存中,而且是清洁的
- MOESI 向MESI协议添加了“拥有”(Owned)状态
- 略
对称共享存储器多处理器(SMP)与监听协议的局限性
5.4 分布式共享存储器(DSM)和目录式一致性
- 目录中保存了每个可缓存块的状态,这个目录中的信息包括哪些缓存(或缓存集合)拥有这个块的副本,它是否需要更新,等
- 在一个拥有共享最外层缓存(即L3)的多核心中,实现目录机制比较容易:
只需要为每个L3块保存一个位向量,其大小等于核心的数目。
这个位向量表示哪些专用缓存的L3中可能拥有一个块的副本,失效操作仅会发送给这些缓存。
如果L3是包含性的,那这一方法对单个多核心是非常有效的,在Intel i7中就是采用了这一机制。
- 在一个拥有共享最外层缓存(即L3)的多核心中,实现目录机制比较容易:
- 分布式目录:
- 目录与存储器分布在一起,使不同一致性请求可以进入不同目录,就像不同存储器请求进入不同存储器一样。
- 特性: 块的共享状态总是放在单个已知位置
- 每个目录负责跟踪一些缓存,这些缓存共享该节点内部部分存储器的存储器地址
- 一致性机制可能会维护多核心节点内部的目录信息,并处理所需要的一致性操作
- 最简单的目录实现方法是将每个存储器块与目录中的一项相关联。
- 在这种实现方式中,信息量与存储器块数和节点数的乘积成正比,其中一个节点就是在内部实施一致性的单个多核心处理器或一小组处理器。
目录式缓存一致性协议 : 基础知识
- 和监听式协议一样,目录式也必须实现两种主要操作:
- 处理读取缺失
- 处理共享、清洁缓存块的写入操作
- 缓存块的状态:
- 共享
一或者多个节点缓存了这个块,存储器的值是最新的 - 未缓存
所有节点都没有这个缓存块的副本 - 已修改
只有一个节点有这个缓存块的副本,它已经对这个块进行了写操作,所以存储器的值已过期。这个处理器被称为这个块的拥有者。
- 共享
- 跟踪哪些节点拥有这个块的副本:
- 每个存储器保存一个位向量
- 当这个块被共享时,这个向量的每一位指明相应的原处理器芯片是否拥有这个块的副本
- 当这个块被独占时,这个位向量用来跟踪块的拥有者
- 每个存储器保存一个位向量
- 跟踪各个缓存中每个缓存块的状态:
- 用于定位一个数据项独占副本并使其失效的过程时,目录式协议需要在发出请求的节点与目录之间进行通信,在目录与一或多个远程节点进行通信;而 监听式协议中,这两个步骤通过向所有节点进行广播而结合在一起。
- 消息节点:
- 本地节点
发出请求的节点 - 主节点
一个地址的存储器位置及目录项所在的节点
物理地址空间是静态分布的,所以事先知道哪个节点中包含给定物理地址的存储器和目录。例如:高阶位可以提供节点编号,低阶位可以提供节点上存储器内的偏移;
本地节点也可能是主节点;当主节点是本地节点时,由于副本可能存储于第三节点上(称为远程节点),所以必须访问该目录。 - 远程节点
拥有缓存块副本的节点,这一副本可能独占,也可能共享。
远程节点也可能与本地节点或主节点相同。
- 本地节点
- 发向目录的一条消息会导致两种不同类型的操作:
- 更新目录状态
- 发送附加消息以满足请求
目录式协议举例
- 存储器块可能未由任何节点缓存,也可能缓存于多个节点中并可读(共享),也可能仅在一个节点中独占缓存并可写
- 目录还会跟踪拥有某一缓存块副本的节点的集合,我们使用名为共享器的集合来执行这一功能
目录接收三种不同请求:读取缺失、写入缺失、数据写回。
每个状态下接收的目录请求消息和采取的操作如下:
- 块处于未缓存状态时(存储器中的副本就是当前值):
- 读取缺失
从存储器想发出请求的节点发送其请求的数据,请求者成为唯一的共节点;块的状态变为共享。 - 写入缺失
向发送请求的节点传送取值,该节点变为共享节点。
然后 这个块变为独占状态,表明缓存了唯一有效副本;共享器指明其拥有者的身份。
- 读取缺失
- 块处于共享状态时(存储器的值是最新的):
- 读取缺失
从存储器向发出请求的节点发送其请求的数据,请求者被添加到共享集合中 - 写入缺失
向请求节点发送取值。
向共享者集合中的所有节点发送失效消息,共享者集合将包含发出请求的节点的身份,这个块的状态变为独占状态。
- 读取缺失
- 当块处于独占状态时(这个块的值保存在一个节点的缓存中,这个节点由共享者集合识别):
- 读取缺失
向拥有者发送数据提取消息,他会将拥有者缓存中这个快的状态转变为共享;
拥有者将数据发送给目录,再在这里将其写到存储器中,并发给提出请求的处理器。
将发出请求的节点的身份添加到共享者集合中,这个集合中仍然包含拥有者处理器的身份(这个处理器仍然拥有可读副本) - 数据写回
拥有者正在替换这个块,因此必须将其写回。
这个写回操作会更新存储器副本(主目录实际上变为拥有者),这个块现在为被缓存,共享者集合为空。 - 写入缺失
这个块有一个新的拥有者。
向旧拥有者发送一条消息,将其缓存中的这个块失效,并将值发送给目录,从目录中发送给提出请求的节点,这个节点现在编程新的拥有者。
共享者被设定为新拥有者的身份,这个块仍然保持独占状态。
- 读取缺失