| 1.2.6 并行度与并行体系结构的分类
应用程序中主要有两种并行:
所有计算机可以根据指令流及数据流的并行情况划分为:
| 1.3 计算机体系结构
见附录A
| 1.4.1 带宽胜过延迟
带宽提升的速度远大于延迟改进的速度
| 1.9 计算机设计的量化原理
计算机设计的三个基本原则:
加速比 = 原执行时间 采用改进后的执行时间 加速比 = \frac{原执行时间}{采用改进后的执行时间} 加速比=采用改进后的执行时间原执行时间
新执行时间 = 原执行时间 × [ ( 1 − 升级比例 ) + 升级比例 升级加速比 ] 新执行时间 = 原执行时间 \times [(1-升级比例)+\frac{升级比例}{升级加速比}] 新执行时间=原执行时间×[(1−升级比例)+升级加速比升级比例]
总加速比 = 原执行时间 新执行时间 = 1 ( 1 − 升级比例 ) + 升级比例 升级加速比 总加速比 = \frac{原执行时间}{新执行时间}=\frac{1}{(1-升级比例)+\frac{升级比例}{升级加速比}} 总加速比=新执行时间原执行时间=(1−升级比例)+升级加速比升级比例1
| 3.1 指令级并行
现代处理器通过流水线来实现指令级并行(ILP),提高性能。流水化处理器的CPI为:
流水线 C P I = 理想流水线 C P I + 结构化冒险停顿 + 数据冒险停顿 + 控制冒险停顿 流水线CPI=理想流水线CPI+结构化冒险停顿+数据冒险停顿+控制冒险停顿 流水线CPI=理想流水线CPI+结构化冒险停顿+数据冒险停顿+控制冒险停顿
停顿的单位是每条指令。主要的ILP技术有:
技术 | 降低CPI的哪一部分 | 基于硬件/软件 |
---|---|---|
转发 | 数据冒险停顿 | 硬件 |
基本动态调度(记分牌) | 数据冒险停顿 | 硬件 |
采用重命名的动态调度(Tomaluso) | 数据冒险停顿 | 硬件 |
延迟分支和基本分支预测 | 控制冒险停顿 | 硬件 |
动态分支预测 | 控制冒险停顿 | 硬件 |
循环展开 | 控制冒险停顿 | 软件 |
编译器流水线调度 | 数据冒险停顿 | 软件 |
流水线中最常见的冒险就是数据冒险,数据冒险是由相关性(依赖)导致的,三种相关性:
相关只是指令之间的关系,不一定在流水线中产生冒险,取决于流水线的具体实现结构。
| 3.2 循环展开
循环展开是一种提高指令级并行度的技术,采用循环展开时要进行以下的决策和变换:
| 3.4-3.5 动态调度&Tomasulo算法
动态调度方式更加灵活,允许指令以不同的顺序执行,减少停顿。由硬件重新安排指令的执行,可以允许代码在不同流水线上高效执行,并可以处理编译时不知道的相关性(涉及存储器引用的),以及缓存缺失等情况。
在附录C中介绍的记分牌算法是一种动态调度算法,允许指令乱序执行。记分牌会在指令的各个阶段分别检查各种数据冒险和结构冒险,通过停顿避免冒险。
Tomasulo算法与记分牌算法采用类似的思想,记录指令的执行状态,检查冒险。不同之处是Tomasulo采用寄存器重命名消除了WAR和WAW这两种假数据依赖,消除了相应的两种数据冒险。并且Tomasulo算法中,一个功能部件有多个缓冲,使用同一个功能单元的指令可以在功能单元被占用时在保留站等待,减少了结构冒险带来的停顿。
Tomasulo算法的实现结构
Tomasolu算法的实现结构如下图:
保留站、寄存器结果状态表、指令状态表
Tomasulo算法中,指令的执行有三个阶段:发射,执行,写回。指令状态表如下图:
在记分牌中,每一条配置通路只能存放一条指令,Tomasulo算法为每一条通路配置了一组缓冲,对于同一个运算单元,可以缓冲多条指令,在运算单元被占用时,后续指令可以在保留站等待。保留站可以将能读取的数据直接记录在保留站中,并且对于未就绪的数据,只要计算结束就捕捉广播数据,用保留站的编号而不是寄存器编号来标记数据源,从而实现了寄存器重命名。
和记分牌一样,Tomasulo算法也要记录寄存器结果状态,并记录寄存器更新的数据来源。数据来源选择最新的指令的数据。
Tomasulo算法的缺陷
|Tomasulo算法填表
Tomasulo算法在填表时,要注意操作数直接填写可以读取到的值。并且如果当前周期操作数op在写回,当前周期发射的指令如果需要op,就直接在保留站中读入op,而不是像记分牌那样要下一周期才可以读。写回后(写回的那个周期时刻的表),寄存器结果状态表也要记录相应的值。与记分牌相同,在指令写回周期,保留站关于这一条指令的信息在填表时就可以删除了。
|5.4 目录一致性协议与监听一致性协议
多核处理器可能既有共享级别的缓存,又有专用级别的缓存。多个处理器如果共享存储器上的数据,就可能在自己专有的缓存上缓存共享数据,不同的处理器在自己的缓存中可能存有同一数据的不同值,这就是缓存一致性问题。
保证缓存一致性的方式是使用一致性协议,共有两种一致性协议:
这两种协议都是写入失效协议,处理器执行写入操作时使其他副本失效。
监听一致性协议通常是通过有限状态控制器实施的,控制器可以改变所选缓存块的状态,并使用总线访问数据或使其失效。通过向总线发送信号使其他CPU的该块失效,也通过发送信号告知其他CPU自己发生读写缺失。
目录式一致性协议中,每个处理器都有一个目录,目录中保存了每个可缓存块的状态,信息包括哪些缓存拥有这个块的副本,是否需要更新等等。存储器的每一块都在目录中有对应的一项,每个目录项由访问状态和位向量组成,位向量记录了各个处理器是否有这个块的副本。目录一致性协议不通过广播告知其他处理器一个块失效,而是根据位向量,通知相应的CPU该块失效或完成更新该块的工作。并且由块所在的存储器所属的CPU作为宿主与需要沟通的处理器沟通,完成写失效通知和写回的操作。
两种方法的比较
监听法基于总线,通过广播信号来实现写失效,优点是不需要额外的存储空间维护一致性信息,缺点是可扩展性差,处理器数量越多,总线通信的压力就越大。
目录法采用集中式的目录维护一致性信息,增加了存储开销。但一致性信息是集中式的存储在目录中,目录结构本身是分布式的,因此具有可拓展性。目录法最大的优点是可以实现在分布式的系统中,不需要总线,具有扩展性。
|A.2 指令集体系结构的分类
根据存储类型分类,有三类指令集体系结构:
|A.3-A.6 指令集体系结构的特征
|RISC-V体系结构
以RISC-V64G为例,介绍该指令集体系结构的上述特征。
寄存器:RV64G有32个64位通用寄存器,还有32个64位的浮点寄存器,以及一些特殊用途的寄存器。
操作数:RV64G支持字节,半字,字,双字和单/双精度的浮点。
寻址方式:数据寻址的方式只有立即数寻址和偏移量寻址。偏移量为0时实现的即为寄存器间接寻址。RV64G使用64位的地址,小端法存储。访存不需要对齐,不过使用不对齐的访存会很慢。
指令集编码:定长编码。
|B.2 评价缓存性能
缓存性能
评价缓存性能常使用存储器停顿时间:
另外一个度量方式是使用存储器平均访问时间:
计算缓存带来的加速比时,可以计算使用缓存和不使用缓存的CPI,然后得到加速比。CPI执行公式只考虑存储器停顿,不使用缓存则缺失率为100%。
缓存考虑的四个问题
|B.3 评价缓存性能
6种基本的缓存优化方式:
|C.1 流水化的基本实现
将指令的执行过程划分为5个周期,在每个周期开始一条新的指令来实现指令的流水化,并采用以下几点:
流水化可以提高CPU指令吞吐量,但不能缩短单条指令执行时间。因为时钟速度必须大于最慢的流水级,并且流水线寄存器引入了延迟。
|C.2 流水化的阻碍-流水线冒险
流水线化的指令执行主要受到流水线冒险的阻碍,包含以下三种冒险,相应的解决方式有:
|C.3 流水化的实现
MIPS将分支计算和检测移动到ID阶段,期望减少分支冒险导致的停顿。
如果在ID阶段就完成分支计算,会导致一些数据冒险产生更多停顿,因此RISC-V设计在EX阶段完成分支判断,这样如果没有分支预测,会浪费两条指令,相当于产生两个停顿。RISC-V使用动态分支预测,不使用延迟槽,因为分支延迟并不总是可行,并且分支判断在EX阶段完成,在ID阶段根据预测的结果进行跳转,EX阶段进行验证。
|C.7 基本动态调度-记分牌
动态调度流水线中,指令按序发射,乱序执行,实现方式是使用记分牌。记分牌全面负责指令发射与执行,包括所有冒险检测任务。乱序执行会导致原来顺序执行流水线中不存在的WAR和WAW冒险出现,这些冒险都由记分牌来检测和处理。每条指令都会进入记分牌,有一条记录,记分牌会判断什么时候能读取操作数并执行,还会控制指令什么时候能写回目标寄存器。每个功能部件在记分牌中有一条数据通路(一个记录的位置)。
指令在流水线中完成有四个步骤:
记分牌有三个部分:
|记分牌填表
填表时,在指令读取阶段,Rj,Rk仍为准备好读取的状态,进入执行阶段后,设置为已读取。进入写回阶段时,记分牌中该指令的功能单元状态表,寄存器结果状态表的相应位置清空(但使用该功能部件的下一条指令还不能在这一周期就发射,尽管在表中这一条目是空的),同时需要读取该部件的操作数的指令的Qj,Qk也清空,Rj,Rk转为YES状态,表示准备好可以读取,但是要下一时刻才可以读取。填表的时候要注意,clki的表中是clki结束时的状态,所以不能一个指令写回时清空了功能单元状态,下一个使用该功能单元的指令在同一个周期就发射。
如下图例,第一条LD在clk4就写回了,此时Integer部件条目已经空了,但是下一条LD在clk4不能发射,因为clk4第一条LD写回,并清空条目是这一周期发生的事情。