0%

计组复习笔记(三)

处理器

ALU used for

  1. Load/Store: F = add
  2. Branch: F = subtract
  3. R-type: F depends on funct field

11

流水线

提高吞吐率,并未减少单一指令的执行时间(延迟latency)

吞吐率 TP:单位时间内流水线所完成的任务数量或输出结果的数量

$TP=n/T_k=n/[(n+k-1)*δt]$,n为任务数,$T_k$是处理完n个任务所用的时间

加速比 S:完成同样一批任务,顺序执行所用的时间与使用流水线所用的时间之比

$S=T_0/T_k$

效率 E:流水线上的设备利用率,即时空图上,N个任务占用的时空区与K个流水段占用的总时空区之比。由于流水线有建立时间和排空时间,各段并不总是满负荷工作的。

E=n个任务占用的时空区/k个流水段占用的时空区=n/(n-k+1)

在时空图上体现为执行所有指令需要的时间和实际用的时间,多余的时间由建立时间和排空时间造成

5个处理步骤:IF,ID,EX,MEM,WB

冒险

结构冒险

硬件占用:内存读写—IM,DM分开

数据冒险

拿错数据

  1. 前推/旁路
  2. 重新安排代码避免阻塞

C code for A = B + E; C = B + F

1
2
3
4
5
6
7
lw	$t1, 0($t0)
lw $t2, 4($t0)
add $t3, $t1, $t2
sw $t3, 12($t0)
lw $t4, 8($t0)
add $t5, $t1, $t4
sw $t5, 16($t0)

重新安排代码:

1
2
3
4
5
6
7
lw	$t1, 0($t0)
lw $t2, 4($t0)
lw $t4, 8($t0)
add $t3, $t1, $t2
sw $t3, 12($t0)
add $t5, $t1, $t4
sw $t5, 16($t0)

控制冒险

取错指令

  1. 阻塞
  2. 分支预测

静态预测

动态预测

当预测错误时,流水线控制必须确保被错误预测的分支后面的指令执行不会生效,并且在正确的分支地址处重新开始启动流水线。

流水线数据通路

流水线寄存器

IF/ID,ID/EX,EX/MEM,MEM/WB

12

最终的数据通路与控制

13

数据冒险:旁路与阻塞

冒险条件

前提:写操作(EX/MEM.RegWrite, MEM/WB.RegWrite有效),写目的寄存器不能是$zero

1a. EX/MEM.RegisterRd = ID/EX.RegisterRs≠ 0 ForwardA = 10

1b. EX/MEM.RegisterRd = ID/EX.RegisterRt≠ 0 ForwardB = 10

2a. MEM/WB.RegisterRd = ID/EX.RegisterRs≠ 0 ForwardA = 01

2b. MEM/WB.RegisterRd = ID/EX.RegisterRt≠ 0 ForwardB = 01

1—Fwd from EX/MEM pipeline reg

2—Fwd from MEM/WB pipeline reg

ForwardA=0:第一个ALU操作数来自寄存器,ForwardB同理

旁路单元

14

01选通MEM/WB;10选通EX/MEM

==为什么有两个Rt啊?还有下面加的红色语句我也没有理解目的所在==

更复杂的潜在数据冒险:比如一个寄存器对多个数字进行求和运算,一系列连续的指令将会读写到同一寄存器:

1
2
3
add $1,$1,$2
add $1,$1,$3
add $1,$1,$4

第二条指令的EX/MEM数据才是最新的。因此,改变MEM冒险的控制策略:

MEM hazard

if (MEM/WB.RegWrite and (MEM/WB.RegisterRd ≠ 0)
and not (EX/MEM.RegWrite and (EX/MEM.RegisterRd ≠ 0)
and (EX/MEM.RegisterRd = ID/EX.RegisterRs))
​ and (MEM/WB.RegisterRd = ID/EX.RegisterRs))
ForwardA = 01

if (MEM/WB.RegWrite and (MEM/WB.RegisterRd ≠ 0)
and not (EX/MEM.RegWrite and (EX/MEM.RegisterRd ≠ 0)
and (EX/MEM.RegisterRd = ID/EX.RegisterRt))
​ and (MEM/WB.RegisterRd = ID/EX.RegisterRt))
ForwardB = 01

Load-Use冒险检测单元

工作在ID级,从而可以在装载指令与紧随其后需要它的结果的指令间插入阻塞

阻塞条件:ID/EX.MemRead and ((ID/EX.RegisterRt = IF/ID.RegisterRs) or (ID/EX.RegisterRt = IF/ID.RegisterRt))

插入空指令:把ID/EX流水线寄存器的EX、MEM、WB级的控制信号都置为0.仍向前传递,但控制信号为0不会进行Reg和MEM的写操作。(事实上只需将RegWrite和MenWrite置为0)

15

通路

16

冒险检测控制单元控制PC和IF/ID流水线寄存器的写入,以及在实际控制信号与全0中进行选择的多选器。若冒险条件为真,阻塞并清除所有控制字段。

控制冒险

增加寄存器比较电路,如果参与比较的两个寄存器,是两步之前的ALU结果,可以通过旁路解决冒险。如果参与比较的两个寄存器其中有一个,是前一步的ALU结果或是两步之前load的结果,需要一个阻塞。如果参与比较的两个寄存器其中有一个,是前一步的load的结果,需要两个阻塞。

动态分支预测

分支预测缓存Branch prediction buffer (aka branch history table):一小块按照分支指令的低位地址索引的存储器区,其中包括一位或多位数据用以说明最近是否发生过分支。

2位预测位

17

依然需要花费一个时钟周期的开销,去计算分支目标地址。使用延迟分支或分支目标地址缓存

异常

(另一种形式的控制冒险,机制相同,不同的是由异常重置控制信号)

异常程序计数器EPC:保存出错指令的地址+4

协处理器CP0

Jump to handler at 8000 00180

记录引起异常的原因的两种方法

  1. Cause寄存器:有一个字段记录引起异常的原因
  2. 向量中断,控制权转移到由异常原因决定的地址处

18

从MEM/WB寄存器WB部分出来的向上向左的那个信号,有点小错误,应该只向Registers,是一个写寄存器的控制信号。

多重中断,硬件对异常进行排序从而使得最先发生异常的指令被中断。优先级最高的异常处理完后,继续处理后面的异常。

非精确中断/非精确异常:在流水线中,将每一个异常与导致该异常的指令对应起来难度很大,EPC中放入相近的值,由操作系统确定精确位置。精确异常是为了支持虚拟存储器。

指令级并行

增加流水线的指令级并行程度:

  1. 增加流水线的深度—-更多的重叠
  2. 复制计算机内部部件的数量—每个流水既可以启动多条指令—-多发射multiple issue

多发射

CPI可能小于1,可使用IPC

静态多发射(在编译时)

动态多发射(在执行时)

发射槽 issue slot

Speculation 推测:编译器或处理器推测指令结果以消除其他指令对该结果的依赖。

推测错误时需要回卷。 指令重排、缓存结果

静态多发射处理器

使用编译器封装指令并处理冒险,若无可同时发射的,用nop代替

发射包 issue packet:在一个时空周期内发射的多条指令的集合。可有编译器静态生成或处理器动态生成。对一个周期内能发射的多条指令有所限制。

超长指令字VLIW

例:Two-issue packets

One ALU/branch instruction

One load/store instruction

数据通路

19

数据冒险:

EX数据:同一个包中,can’t use ALU result in load/store

load-use:会增加延迟

调度

Loop: lw \$t0,0(\$s1) # \$t0=array element
​ addu \$t0, \$t0,\$s2 # add scalar in \$s2
​ sw \$t0,0(\$s1) # store result
​ addi \$s1,\$s1,–4 # decrement pointer
​ bne \$s1,\$zero, Loop # branch $s1!=0

ALU/branch Load/store cycle
Loop: nop lw t0, 0($s1) 1
addi s1, $s1,–4 nop 2
addu t0, $t0, $s2 nop 3
bne s1, $zero, Loop sw \$t0, 4($s1) 4

循环展开(循环体复制4份):

ALU/branch Load/store cycle
Loop: addi s1, $s1,–16 lw \$t0, 0($s1) 1
nop lw t1, 12($s1) 2
addu t0, t0, $s2 lw \$t2, 8($s1) 3
addu t1, t1, $s2 lw \$t3, 4($s1) 4
addu t2, t2, $s2 sw \$t0, 16($s1) 5
addu t3, t4, $s2 sw \$t1, 12($s1) 6
nop sw t2, 8($s1) 7
bne s1, $zero, Loop sw \$t3, 4($s1) 8

寄存器重命名——引入临时寄存器,消除虚假的数据依赖(反相关)

标红处是16而不是0,是因为第一行\$t0取的是\$s1未减去16处的值,从第二行开始,通过旁路技术,$s1已减去16

动态多发射处理器

也叫超标量处理器

指令顺序发射,乱序执行,顺序提交。处理器决定每个周期几条指令,硬件保证正确性。

流水线被划分为:取指与发射单元、多个功能单元、一个提交单元(含重排序缓冲区)。每个功能单元有自己的缓冲区(保留站)用于保存操作数和操作。

20

寄存器重命名

保留站和重排序缓冲区提供寄存器重命名机制。发射指令时,它先被复制到合适的功能单元的保留站。如果操作数在寄存器堆中或重排序缓冲区中可用,那么立即数被复制到保留站中。否则该指令一直缓存在保留站中。若指令已发射,那么操作数对应的寄存器的值可以被覆盖。如果操作数不在寄存器堆中或重排序缓冲区中,那么他应该是某个功能单元的结果,硬件帮助定位该功能单元,计算出结果时直接从功能单元复制到保留站,跳过寄存器堆。

推测

Predict branch and continue issuing

Don’t commit until branch outcome determined

Load speculation

Avoid load and cache miss delay

  1. Predict the effective address
  2. Predict loaded value
  3. Load before completing outstanding stores
  4. Bypass stored values to load unit

Don’t commit load until speculation cleared

为什么需要动态调度?

  1. 并不是所有的阻塞都可以预知。动态调度在一些指令阻塞时调度其他指令,以掩盖阻塞。
  2. 对于分支指令,若采用动态推测而不是用动态调度,会极大限制指令级并行度。
  3. 流水线延迟和发射宽度根据处理器的具体实现的不同有很大差别。

多发射的阻碍:窗口期有限、内存访问延迟、带宽受限

动态调度和推测消耗能源

指令集、数据通路和控制的设计之间相互影响


预测和推测之间有什么区别?

分支预测由处理器完成,以试图确定在条件跳转之后执行将继续的位置,以便它可以从存储器读取下一条指令。

推测执行更进一步,并确定执行下一条指令的结果。如果分支预测是正确的,则使用结果,否则将其丢弃。即使代码中没有实际的条件分支,也可以应用推测执行。处理器可以从通常将连续执行的若干指令确定结果,但是可以例如通过算术溢出中断来停止执行。