一、计算机系统结构的基本概念
计算机系统结构的概念
计算机系统的层次结构
在上述6级层次结构中,通常L1~L3是解释的方法实现; 而L4~L6则是用翻译的方法实现
计算机系统结构的定义
计算机系统结构是程序员所看到的计算机属性,即概念性结构与功能特性。
透明性(transparent)---看不见底层
- 指令集系统
- 组成
- 硬件
计算机系统结构概念的实质是确定计算机系统中软、硬件的界面,界面之上是软件实现的功能,界面之下是硬件和固件实现的功能。
计算机组成和计算机实现
计算机组成--指的是计算机系统结构的逻辑实现,包含物理机器级中的数据流和控制流的组成以及逻辑设计。 着眼于物理机器级内各事件的排序方式与控制方式、各部件的功能以及各部件之间的联系。
计算机实现--指的是计算机组成的物理实现,包括处理机和主存等部件的物理结构,器件的集成度和速度,模块、插件、底板的划分与连接,信号传输,电源、冷却及整机装配技术等。着眼于器件技术和微组装技术。
一个系统结构可以采用不同的计算机组成
一个计算机组成可以采用不同的计算机实现
定量分析技术
以经常性时间为重点
在计算机系统设计中经常要在不同的方法之间进行折中,这是按照对经常发生的事件采用优化方法的原则进行选择,因为这样能够得到更多的总体上的改进。这里优化是指分配更多的资源、达到更高的性能或者分配更多的电能等
Amdahl定律
CPU性能公式
执行一个程序所需的CPU时间可以这样计算:
CPU时间=执行程序所需的时钟周期数*时钟周期时间
其中,时钟周期时间是系统频率的倒数
映入新的参数CPI(Cycles Per Instruction,即每条指令的平均时钟周期数):
CPI=执行程序所需的时钟周期数/所执行的指令条数
则有以下的CPU性能公式:
CPU时间=IC*CPI*时钟周期时间
其中,IC为所执行的指令条数
CPU设计中还经常用到下面计算CPU时钟周期总数的方法:
程序的局部性原理
指程序执行时所访问的存储器地址分布不是随机的,而是相对簇聚
程序执行时间的90%都是在执行程序中10%的代码
局部性包括时间局部性和空间局部性。时间局部性是指程序即将用到的信息很可能就是目前正在使用的信息。空间局部性是指程序即将用到的信息很可能与目前正在使用的信息在空间上相邻或临近
计算机系统的性能测评
执行时间和吞吐率
基准测试程序
性能比较
计算机体系结构的发展
冯诺依曼结构
由运算器、控制器、存储器、输入设备和输出设备5部分构成
存储程序原理的基本点是指令驱动。指令预先存放在计算机存储器中,计算机一旦启动,就能按照程序指定的逻辑顺序执行这些程序,自动完成由程序所描述的处理工作
(1)对输入/输出方式的改进
(2)采用并行处理技术
(3)存储组织结构的发展
(4)指令集的发展
软件对系统结构的影响
系列机
模拟和仿真
模拟是指用软件的方法在一台现有的计算机(成为宿主机host)上实现另一台计算机(称为宿主机)的指令集。通常用解释的方法来实现,即虚拟机的每一条指令都用宿主机的一段程序进行解释执行。为了使虚拟机的应用程序能在宿主机上运行,除了模拟虚拟机的指令集外,还要模拟其存储系统、I/O系统和操作系统等。由于模拟是采用纯软件解释执行的方法,因此运行速度较慢,性能较差。
仿真是指一台现有计算机(称为宿主机)上的微程序去解释实现另一台计算机(成为目标机)的指令集。这个微程序是专门为实现目标机指令集而设计的,称为仿真微程序。同样除了仿真目标机的指令集外,还需要仿真其存储系统,I/O系统和控制台操作等。
统一高级语言
器件发展对系统结构的影响
超大规模集成电路(Very Large Scale Integration,VLSI)
应用对系统结构的影响
并行性
4个定量原理
1.以经常性事件为重点
在计算机系统的设计中经常要在不同的方法之间进行折中,这时要按照对经常发生的情况采用优化方法的原则进行选择,因为这样能得到更多的总体上的改进。这里优化是指分配更多的资源、达到更高的性能或者分配更多的电能等。
2.Amdahl定律
加快某部件执行速度所能获得的系统性能加速比,受限于该部件的执行时间占系统中总执行时间的百分比。
3.CPU性能公式
执行一个程序所需的CPU时间可以这样来计算:CPU时间=执行程序所需的时钟周期数×时钟周期时间
4.程序的局部性原理
时间局部性和空间局部性
二、计算机指令集结构
指令集结构的分类
堆栈结构
累加器结构
通用存储器结构(RM寄存器-存储器结构、RR寄存器-寄存器结构、MM)
对于不同类型的指令集结构,其操作数的位置、个数以及操作数的给出方式(显式或隐式)也会不同。显式给出的是用指令字中的操作数字段给出,隐式给出的则是使用约定好的单元
下图中浅色表示操作数,深色表示结果,TOS(Top Of Stack)表示栈顶
a.在堆栈结构中,操作数都是隐式的,即堆栈的栈顶和次栈顶中的数据,运算后把结果写入栈顶。在这种结构中,只能通过push/pop指令访问存储器
b.在累加器结构中,一个操作数是隐式的,即累加器;另一个操作数则是显式给出,这是一个存储单元,运算结果送回累加器。
在通用寄存器结构中,所有操作数都是显式地给出,它们或者是有一个操作数来自存储器中的某个单元(c.),或者都是来自通用寄存器组(d.),结果写入通用寄存器组
寻址方式
一种指令集结构如何确定所要访问的数据的地址
指令集结构的功能设计
实际上就是确定软硬件功能分配,即确定哪些基本功能应该由硬件实现,哪些功能由软件实现比较合适。
在确定哪些功能用硬件实现时,主要考虑:速度、成本与灵活性。用硬件实现的特点是速度快、成本高、灵活性差,用软件来实现的特点是速度慢、价格便宜、灵活性好。一般来说,选择出现频率高的基本功能能用硬件来实现
对指令集的基本要求是:完整性、规整性、高效率和兼容性
CISC
面向目标程序增强指令功能
面向高级语言的优化实现来改进指令集
面向操作系统的优化实现改进指令集
RISC
控制指令
操作数的类型和大小
指令格式的设计
MIPS
三、流水线技术
流水线的基本概念
把一个重复的过程分解为若干个子过程,每个子过程由专门的功能部件来实现。把多个处理过程在时间上错开,依次通过各功能段,这样每个子过程就可以与其他子过程并行进行。这就是流水线技术(pipelining)。流水线中的每个过程及其功能部件称为流水线的级或段,段与段相互连接形成流水线。流水线的段数称为流水线的深度。
依靠并行工作缩短程序执行时间
时间长的段将成为流水线的瓶颈
流水寄存器的作用:在相邻的两段之间传送数据,以保证提供后面要用到的数据,并把各段的处理工作相互隔离
通过时间:第一个任务从进入流水线到流出结果所需的时间
排空时间:最后一个任务从进入流水线到流出结果所需的时间
流水线的分类
单功能与多功能
静态与动态
部件级(运算)、处理机级(指令)、处理机间
线性与非线性
按序与乱序
流水香的性能指标
吞吐量
加速比
效率
流水线性能分析举例
效率可理解(大概是这个意思):带颜色的方格/整个(也就是段*最后一个任务结束的时间)
总结
(1)选择适合于流水线工作的算法
先计算A1+B1、A2+B2、A3+B3和A4+B4;
在计算(A1+B1)*(A2+B2)和(A3+B3)*(A4+B4);
然后求总的乘积结果
(2)画出时空图
该流水线的效率不高
总结
(1)选择适合于流水线工作的算法
先计算A1*B1、A2*B2、A3*B3和A4*B4;
在计算(A1*B1)+(A2*B2)和(A3*B3)+(A4*B4);
然后求总的累加结果
(2)画出时空图
做题方法
求TP、S、ETP=n(任务数)/Tk(处理完成n个任务所用的时间)
TP=(产生结果的个数)/(时空图最后一个任务完成的横坐标)
上图中就是TP=7/18
S=Ts(不使用流水线所用的总时间)/Tk(使用流水线所用的总时间)
S=(图中带颜色方格总个数)/(时空图中最后一个任务完成的横坐标)
上图中就是S=28
/18
E=(n个任务实际占用的时空区)/(k个段总的时空区)
E=(图中带颜色方格总个数)/(横纵坐标相乘,段*时间)
上图中就是E=(4*4+3*4)/(5*18)
流水线设计中的若干问题
瓶颈问题
理想情况下,流水线爱你在工作时,其中的任务是同步地每一个时钟周期往前流动一段;
当流水线各段不均匀时,机器的时钟周期取决于瓶颈段的延迟时间;
在设计流水线时,要尽可能使各段时间相等
额外开销
指流水寄存器延迟和时钟偏移开销
- 流水寄存器需要建立时间和传输延迟
建立时间:在触发写操作的时钟信号到达之前,寄存器输入必须保持稳定的时间;
传输延迟:时钟信号到达后到寄存器输出可用的时间
- 时钟偏移开销
流水线中,时钟到达各流水寄存器的最大差值时间(时钟到达各流水寄存器的时间不是完全相同)
流水线技术带来的问题
流水线并不能减少(而是一般是增加)单条指令的执行时间,但却能提高吞吐率;
增加流水线的深度(段数)可以提高流水线的性能;
流水线的深度受限于流水线的额外开销;
当时钟周期小到与额外开销相同时,流水已没意义。因为这时在每一个时钟周期中已没有时间来做有用的工作
流水线的相关与冲突
经典的5段流水线
两种描述方式
采用流水线方式实现时,应解决一下几个问题:
- 要保证不会在同一个时钟周期要求同一个功能段做两件不通的工作
例如,不能要求ALU同时做有效地址计算和算术运算;
- 避免IF段的访存(取指令)与MEM段的访存(读/写数据)发生冲突
必须采用分离的指令存储器和数据存储器;
一般采用分离的指令Cache和数据Cache
- ID段和WB段都要访问同一寄存器文件的冲突
把写操作安排在时钟的前半拍完成,把读操作安排在后半拍完成;
- 考虑PC的问题
流水线为了能够每个时钟周期启动一条新的指令,就必须在每个时钟周期进行PC值的加4操作,并保留新的PC值。这种操作必须在IF段完成,以便为取下一条指令做好准备。故需设置专门的加法器;
但分支指令也可能改变PC的值,而是在MEM段进行,这会导致冲突
相关与流水冲突
相关
两条指令之间存在某种依赖关系
对于两条指令i(在前)和j(在后)
数据相关
(真数据相关)
i写,j读(先写后读)
(1)指令j使用指令i产生的结果
(2)指令j与指令k相关,而指令k又与指令i数据相关(数据相关具有传递性)
当数据的流动是经过寄存器时,相关的检测比较直观和容易,因为寄存器是统一命名,同一寄存器在所有指令中的名称都是唯一的。
而当数据的流动是经过存储器时,检测就比较复杂了,因为相同形式的地址其有效地址未必相同,形式不同的地址其有效地址却可能相同。
名相关
i读,j写---反相关(先读后写)
名指的是指令所访问的寄存器或存储单元的名称。如果两条指令使用相同的名,但是它们之间并没有数据流动,则称这两条指令存在名相关。
(1)反相关
如果指令j写的名与指令i读的名相同,则称指令i和j发生了反相关
(2)输出相关
如果指令j和指令i写相同的名,则称指令i和j发生了输出相关
与真数据相关不同,名相关的两条指令之间并没有数据的传送,只是使用了相同的名而已。如果把其中一条指令所使用的名换成别的,并不影响另外一条指令的正确执行。因此可以通过改变指令中操作数的名来消除名相关,这就是换名技术。对于寄存器操作数进行换名称称为寄存器换名。这个过程既可以用编译器静态实现,也可以用硬件动态实现。
控制相关
分支指令引起的相关
它需要根据分支指令的执行结果来确定后续指令是否执行。
控制相关带来了以下两个限制:
(1)与一条分支指令控制相关的指令不能被移到该分支之前,否则这些指令就不受该分支控制了
(2)如果一条指令与某分支指令不存在控制相关,就不能把该指令移到分支之后
流水线冲突
(一)
结构冲突:因硬件资源满足不了指令重叠执行的要求而发生的冲突
(对功能部件进行流水或重复设置资源)
1.插入暂停周期 “气泡”
(在前一条指令访问存储器时将流水线停顿一个时钟周期,推迟后面取指令的操作)
2.设置相互独立的指令存储器(或Cache)和数据存储器(或Cache)
(二)
数据冲突:当指令在流水线中重叠执行时,因需要用到前面指令的执行结果而发生的冲突
(1)
RAW(写后读)---真数据相关
WAW(写后写)--上面的5段流水线不会发生写后写冲突(只在WB段写寄存器)--输出相关
WAR(读后写)--上面的5段流水线不会发生(读操作(在ID段)在写操作(WB段)前)--反相关
(2)通过定向技术(旁路或短路)---解决写后读(RAW) 减少数据冲突引起的停顿(并不是所有的数据冲突都可以用定向技术来解决)
(3)
需要停顿的数据冲突
load增加流水线互锁硬件,插入“暂停”
无法将LD指令的结果定向到DADD指令
(4)依靠编译器解决数据冲突(指令调度或流水线调度--让编译器重新组织指令顺序来消除冲突)
(三)
控制冲突:流水线遇到分支指令和其他会改变PC值的指令所引起的冲突
处理分支指令最简单的方法是“冻结”或“排空”流水线。即一旦在流水线的译码段ID检测到分支指令,就暂停执行其后的所有指令,直到分支指令到达MEM段、确定是否成功并计算出新的PC值为止。如果分支成功,则按照新的PC值取指令,图3.29所示。在这种情况下,分支指令给流水线带来了3个时钟周期的延迟。
分支延迟
为了减少分支延迟,可采取以下措施
(1)在流水线中尽早判断出分支转移是否成功
(2)尽早计算出分支目标地址
预测分支成功、预测分支失败、延迟分支(延迟槽)
(1)预测分支失败
采取这种方法处理分支指令的后续指令时,要保证分支结果出来之前不能改变处理机的状态,以便一旦猜错时处理机能够回退到原先的状态。
(2)预测分支成功
注:在确定分支是否成功之前就能得到分支的目标地址
(3)延迟分支
主要思想是在分支指令的后面加上几条指令(如m条),然后把它们看成是一个整体。不管分支是否成功,都要按照顺序执行这些指令。分支指令后面的这m条指令的位置被称为延迟槽
延迟分支实际上是用延迟槽中的指令来掩盖分支延迟。
选择放入延迟槽中的指令是由编译器完成的。实际上延迟分支能否带来好处完全取决于编译器能否把有用的指令调度到延迟槽中,这也是一种指令调度技术。常用的调度方法有3种:从前调度、从目标处调度、从失败处调度
(a)从前调度,把位于分支指令之前的一条独立指令移到延迟槽
(b)从目标处调度,把目标处的指令复制到延迟槽
(实际上是猜测到分支是成功的,所以分支成功概率高时采用)
(c)从失败处调度
需要注意,当猜测错误时,要保证(b)、(c)中调度到延迟槽中的指令的执行不会影响程序的正确性(当然,延迟槽中的指令是无用的)
上述方法受到两方面的限制,一方面是可以被放入延迟槽中的指令要满足一定的条件,另一方面是编译器预测分支转移方向的能力。为了提高编译器在延迟槽中放入有用指令的能力,许多处理机采用了分支取消机制。在这种机制中,分支指令隐含了预测的分支执行方向。当分支的实际执行方向和事先所预测的一样时执行分支延迟槽中的指令,否则就将分支延迟槽中的指令转化成一个空操作。
下图中预测分支成功的情况一下,实际上分支失败,延迟槽中的为空操作
流水线的实现
MIPS的一种简单实现
5个时钟周期:取指令、指令译码/读寄存器、执行/有效地址计算、存储器访问/分支完成和写回。
NPC--存放下一条指令的地址
IR--指令存储器,存放当前正在处理的指令
A--第一操作数寄存器,存放从通用句存起组读出来的操作数
B--第二操作数寄存器,存放从通用句存起组读出来的另一个操作数
Imm--存放符号扩展后的立即数操作数
cond--存放条件判定的结果。为“真”表示分支成功
ALUo--存放ALU的运算结果
LMD--存放load指令从存储器读出的数据
向量处理机
横向(水平)处理方式
纵向(垂直)处理方式
纵横(分组)处理方式
向量处理机的结构
以CRAY-1为例,分析寄存器-寄存器型向量处理机
括号中的数字为其流水经过的时间,每拍为一个时钟周期,即12.5ns
提高向量处理机性能的方法
设置多个功能部件
链接技术
分段开采技术
四、指令级并行
指令集并行的概念
指令集并行ILP
数据相关限制了所能开发的ILP,如何克服这些限制?从以下两个方面:
(1)保持相关,但避免发生冲突
(2)通过代码变换,消除相关
指令调度就是一种用来避免冲突的主要方法,它并不改变相关。依靠编译器静态进行指令调度的方法;动态调度代码的硬件方法。
指令的动态调度
静态调度的流水线依靠编译器对代码进行静态调度,以减少相关和冲突。---在编译期间进行代码的调度和优化,通过把相关的指令拉开距离来减少可能得停顿。
动态调度则是在程序的执行过程中,依靠专门的硬件对代码进行调度。----保持数据流和异常行为的情况下,通过硬件对指令执行顺序进行重新安排,减少数据相关导致的停顿。
动态调度的优点:
(1)能够处理一些编译时情况不明的相关(如涉及存储器访问的相关),并简化了编译器
(2)能够使本来是面向某一流水线优化编译的代码在其他流水线(动态调度)上也能高效地执行
动态调度的基本思想
为了支持乱序执行,将5段流水线的译码(ID)段细分为以下两个阶段:
(1)流出:指令译码并检查是否存在结构冲突。如果不存在结构冲突,就将指令流出
(2)读操作数:等待数据冲突消失(如果有),然后度读操作数
指令的流出还是按序流出,即按程序顺序流出,但是,它们在读操作数段可能停顿和互相跨越,因而进入执行阶段时就已经是乱序的了。
那乱序执行就可能发生WAR和WAW冲突
Tomasulo算法
Tomasulo算法具有以下两个特点:
(1)冲突检测和指令执行控制是分布的(通过保留站和CDB实现)
每个功能部件的保留站中的信息决定了什么时候指令可以在该功能部件开始执行
(2)计算结果通过CDB直接从产生它的保留站传送到所有需要它的功能部件,而不用经过寄存器
指令执行的步骤:
(1)流出:从指令队列的头部取一条指令
如果该指令的操作所要求的保留站有空闲,就把该指令送到该保留站(设为r)
如果其操作数在寄存器中已经就绪,就将这些操作数送入保留站r;没有就绪,就把产生该操作数的保留站的标识送入保留站r
一旦被记录的保留站完成计算,它直接把数据送给保留站r
(寄存器换名和对操作数进行缓冲,消除WAR冲突)
完成对目标寄存器的预约工作
(消除了WAW冲突)
如果没有空闲的保留站,指令就不能流出
(发生了结构冲突)
(2)执行
当两个操作数都就绪后,本保留站就用相应的功能部件开始执行指令规定的操作。
load和store指令的执行需要两个步骤:计算有效地址(要等到基地址寄存器就绪);把有效地址放入load或store缓冲器
(3)写结果
功能部件计算完毕后,就将计算结果放到CDB上,所有等到该计算结果的寄存器和保留站(包括store缓冲器)都同时从CDB上获得所需要的信息
动态分支预测技术
采用分支历史表BHT
采用分支目标缓冲器BTB
基于硬件的前瞻执行
实现前瞻的关键思想:
允许指令乱序执行,但必须顺序确认
Tomasulo算法中保留站换名功能是由ROB完成的
前瞻执行
- 通过ROB实现了指令的顺序完成
- 能够实现精确异常
- 很容易推广到整数寄存器和整数功能单元上
- 主要缺点:所需的硬件太复杂
多指令流出技术
基于静态调度的多流出技术
基于动态调度的多流出技术
做一下假设:
超长指令字技术
多流出处理收到的限制
- 程序所固有的指令级并行性
- 硬件实现上的困难
- 超标量和超长指令字处理器固有的技术限制
超流水线处理机
循环展开和指令调度
循环展开和指令调度的基本方法
将该程序翻译成MIPS汇编语言代码:
假设R1的初值是指向第一个元素,8(R2)指向最后一个元素
展开后没有调度的代码如下:
对指令序列进行优化调度,以减少空转周期
静态超标量处理机种的循环展开
五、存储系统
存储系统的层次结构
容量、速度、价格
程序访问的局部性原理
存储系统的多级层级结构
存储系统的性能参数
存储容量S
平均价格C
命中率H
不命中率
平均访问时间
其中,常称为不命中开销,它是指从向M2发出请求到把整个数据块调入M1所需的时间
平均访存时间
三级存储结构
Cache(高速缓冲存储器)
主存储器
磁盘存储器(辅存)
“Cache--主存“”层次:弥补主存速度的不足
“主存--辅存”层析:弥补主存容量的不足
存储层次的4个问题
映像规则:当把一个块调入高一层(靠近CPU)存储器时,可以放在哪些位置上?
查找算法:当所要访问的块在高一层存储器中时,如何找到该块?
替换算法:当发生不命中率而且高一层存储器已满时,应替换哪一块?
写策略:当进行写访问时,应进行哪些操作?
Cache基本知识
主存地址
块地址 | 块内位移 |
主存块地址(块号)用于查找该块在Cache中的位置
块内位移用于确定所访问的数据在该块中的位置
映像规则
查找算法
查找目录表
根据映像规则不同,一个主存块可能映射到Cache中的一个或多个Cache块位置,候选位置
当CPU访问该主存块时,必须且只需查找它的候选位置的目录项(标识)。如果有标识匹配(即相同)的项,且其有效位为“1”,则它对应的Cache块即是要找的块
Cache工作过程
标识tag
| 索引index
=组数(组相联) | 块内位移 2^(块内位移)=块大小 |
例:容量为8KB的直接映像Cache,块大小为32B,共有256个块。
=256 index=8位
2^(块内位移)=32 块内位移=5位