# 性能

性能=1执行时间性能=\frac{1}{执行时间}
X 是 Y 的 n 倍快:性能x性能y=n\frac{性能x}{性能y}=n
我们用 CPU (执行) 时间来反映在 CPU 花费时间,而非 CPU 工作时间
程序CPU执行时间=程序的CPU时钟周期数时钟频率程序CPU执行时间=\frac{程序的CPU时钟周期数}{时钟频率}
提升到原来多少是指原来的多少倍
CPI 每条指令所需平均时钟周期
CPU时间=\frac{指令数*CPI}

# 指令:计算机的语言

32 个寄存器
2 ** 30 的存储字

# 数据传送指令

lw s1,20__ __sw ` 1,20( $`s2) 值得注意的是,字是 32 位,不同于 x86
lh 半字以及 lhu 半字无符号 ,一个进行符号扩充,一个进行无符号扩充
sh
lb 下载一个字节 对应 lbu
sb
ll 说是取数,不知道是啥,原子交换第一部分,load linked word
sc store condition word 是上一个的反过来。想起来了,这个是锁的问题。。。

# 逻辑运算

and
or 注意这都是 R 型指令
andi
sll shift left logical
srl

# 分支语句

beq .1,.2,50 这个 pc=50 * 4+4+pc
bne
slt .1,.2,.3 set less than 如果.2 小于.3 那么.1 是 1,反之为 0
sltu
slti
sltiu

# 跳转语句

j 2500
jr register
jal 2500 jump and link ra 寄存器存储 pc+4 地址
# 表示一行的注释

# 关于寄存器

大量寄存器可能使时钟周期变长
字起始地址应该是 4 的倍数,这是对齐限制
将不常使用的变量存回寄存器叫做寄存器换出
相比存储器,寄存器吞吐率高,访问时间短
$s0~$s7 映射到寄存器 16~23
$t0~$t7 映射到 8~15

# 指令

oprsrtrdshamtfunct
6 位5 位5 位5 位5 位6 位

R 型指令如上 rs 或 rt 可以等于 rd

oprsrtconstant/address
6 位5 位5 位16 位

常数绝对值不得超过 2 ** 15
对应的 op 不知道要不要考,暂且不写

mips 里面没有 not,但有 nor(或非)not(a or b) nor a,0 就是对 a 取反,xor(异或)
做运算时,如果是加法(包括无符号加法) 这类,16 位立即数会符号扩充,如果是异或这类,会零扩充

# 决策指令

beq r1,r2,L1
bne 这两个叫条件分支
没有分支目标 / 分支标签的指令序列叫做基本块。编译最初阶段任务是分解基本块出来
注意没有小于则分支,大于则分支这类说法,因为 slt 可以满足需求 bne

# 过程

过程约定:
a0~a3: 传递参数的四个寄存器
v0~v1: 返回结果的两个值寄存器
ra: 返回地址寄存器
jal 会让下一条指令链接到 ra 上
PC 全名 program counter 程序计数器
mips 里的 push 是自己先向下移动 sp,再存入数据在 sp 指向块
在过程中,t0t9 随便使用,s0s7 则需要复原。
不调用其他过程的过程叫叶过程
由于再次调用原因,我们每个程序一般都要 push ra 和 a0 的,具体如下

1
2
3
4
5
6
7
8
addi $sp,-8
sw $ra,4($sp)
sw $a0,0($sp)
之后复原
lw $a0,4($sp)
lw $a0,0(sp)
addi $sp,8
jr $ra

不过过程不要求保留 a0a3,要求保留 ra,sp,s0s7 还有 sp 之上的栈,这些要求不变
栈中包含过程中所需寄存器和局部变量的片段叫做过程帧或活动记录。帧指针指向一开始 sp 还未保存时的地方

# 加锁

交换原语,寄存器把 1 与存储器的 0 交换,视为加锁,如果换出来的是 1,是为解锁失败

1
2
3
addi $t0,$zero,1
ll $t1,0($s1)
sc $t0,0($t1)//存成返回1,失败返回0,重复循环

# 运算

# 溢出

add、addi、sub 溢出时会产生异常(也叫中断)(EPC)
无符号不会溢出,c 语言忽略溢出采用的是无符号
ALU 算术逻辑单元
饱和操作指溢出后直接变成最大值
检测溢出时有符号检测两个数符号和和的符号,无符号检测一个数的取反和和的大小
$k0 $k1 是用来溢出处理后返回指令地址的

# 加快乘除法

这章注意 143 和 138 的图,可能要画的

# 乘法指令

mult multu
mips 通过 Hi 和 Lo 这两个寄存器存储积,mflo 和 mfhi 可以将积取出,可以通过检查 hi 来判断是否溢出
可通过并行加快

# 除法指令

div
divu
除数开始时置于左 32 位,右移变小,检测是否可以减去,然后判断该位为 0 或 1(通过减后大于 0 小于 0 判断小于则加回去),商左移,末置位不断赋 1 或 0
除法的改进版相比于乘法余数向左移(最终存储值),这是因为控制单元在右边,通过右边产生 0 或 1 来出现商。
有符号数余数的设置要让商的绝对值不变化,余数应该与被除数的符号相同 (笔者猜测)。

忽略了除数位 0,忽略溢出,通过 hi 和 lo 来判断吧(mflo 和 mfhi)注意余数是 hi

# 浮点运算

科学计数法,没有前导零且小数点左边只有一位有效位叫做规格化数。
二进制数科学计数法1.0211.0*2^{-1} 浮点数表示
浮点表示:
注意这个尾数第一位表示的是 0.5,也就是前导位 1 是自带的

前导位 0 的表示是通过把指数位设为 0 来表示的,0 这个数是所有位都为 0 表示
无穷大数设置指数位最大,尾数为 0,尾数不为 0 则为 NaN(非数(由 0/0 或无穷减无穷产生))

sexponentfraction
1 位8 位23 位

还是可能会出现上溢,在指数级容纳不下,还有下溢,就是指数级 10^(-38) 达不到的地方
double (两个字大小) 表示,

sexponentfraction
1 位11 位52 位

精度到达2103082*10^{308}
采用带偏阶(或移码)记数法(biased notation). 意思是指数的真实值是减去这个 bias,单精度 bias 是 127,双精度是 1023,为啥向下取整我不知道(可能是 255 表示无穷吧,1-254 的指数才是正常指数,但是你看这张图多奇怪
![[Pasted image 20241220195351.png]])
0.7510-0.75_{10} 的单精度格式为 1 01111110 10000000000000000000000

# 浮点加法

会出现保留位的说法,先将指数小的向指数大的对齐,然后舍去到大数所能包容的有效位,有效位此时是规格化科学计数法的有效位,规格化后检查上溢和下溢 (-126~127 其实就是有效指数位),然后舍成有效位,再规格化,具体计算看 151 和 152 页,注意写的时候注意写清下标是2_{2} 还是_

# 浮点乘法

较为简单,自行看 p155,当然尾数乘法就是乘出来的最高位肯定是前导 1

# 浮点数指令

add.s(单精度加) add.d(双精度加)
sub.s sub.d
mul.s mul.d 莫名没了个 t 也是坑人
div.s div.d
c.x.s c.x.s 就是比较 x 可以是 eq、neq、lt、le、gt、ge 感觉不会考,不用 rd 来接受返回值的操作,值存储在浮点标志中
bclt 和 bclf 真分支跳转和假分支跳转 浮点标志是 c.x.s 这些给出的
有 $f0, $f1, $f2 这类浮点寄存器,两个寄存器构成一个双精度 0 和 1 构成一个(偶 - 奇搭配) 还有 lwcl 和 swcl ,写到这我就忘了汇编的是啥了。。。。
注意没有浮点常数,一般直接常数放在内存取出来

# 浮点数算术精度

保护位 (guard) 舍入位 (round) 保护位在前舍入位在后
保护位原来在这里,有几种舍入策略,round up ,round down ,truncation, 向最近偶数舍入

  • 保护位舍入,就是看有效位后面两位,0-49 舍去,51-99 入位。
    浮点数精确性由尾数最低位的单位 (ulp)(unit in the last place) 给出,这个方法保证误差在半个 ulp 以内
    粘贴位就是在舍入位后多一位,表示舍入位后是否全为 0,如果不全为 0,则置 1,保护位和舍入位
    运算时这些位都会用到,最后一步才会真正舍去,详情见 p163

# 处理器

存储访问指令和算术逻辑指令分支指令通过 ALU 实现
图得看 p183
选择不同来源数据使用多路选择器(multiplexor)。例如决定 pc+4 还是分支目的地址
控制单元 (control unit),给出 multiplexor 的选择信号
mips 数据通路包含两种单元:处理数据值的单元和存储状态的单元
处理数据值的单元是组合逻辑单元 (conbinational element), 输出只取决于当前输入。ALU 就是这类。
有内部存储功能的单元是状态单元 (state element) 也叫时序 (sequential) 部件,指令存储器、数据存储器、寄存器都是状态单元。一个状态单元至少有两个输入和一个输出。两个输入时待写入数据值和决定何时写入的时钟信号。

# 时钟策略

采用边沿触发时钟 (edge-triggered clocking) 方法,书上假定上升沿发生变化(也可以下降沿)。 |-|_ 这个横线是上划线。。。, 若某状态单元在时钟边沿进行写入,那可以忽略控制信号。如果不是每个周期都进行修改,则要显式的写控制信号。写控制信号和时钟信号都是输入信号,必须稳定等到时钟沿到来才改变状态。
有效 (asserted) 表示信号为逻辑高或真
无效 (deasserted) 表示信号为逻辑低或假

# 建立数据通路

指令存储器,程序计数器,ALU,加法器(计算 pc,可以用 ALU)
寄存器堆存放 32 个传统用寄存器。地址偏移还要有个 sign-extend 单元来符号拓展
注意寄存器堆的输入信号和输出信号同时变换,所以读出同一时钟周期是不可能相互影响到的,所以读出的只会是写入之前的数据,不过可以在末尾读入,也就是一个时钟周期读写嘛

计算分支指令的基地址是下一条指令的地址。
分支发生 branch taken 分支未发生 branch not taken
跳转指令将 26 位左移 2 位后,代替 PC 的低 28 位。
ALU 的控制信号是 4 位,控制单元的输入是 func 字段和 2 位的 ALUop,op 决定操作是由 00 (加法)、01 (beq 的减法)、10(指令的 func 字段)(R 型指令的选择)来决定操作,输出的就是上面讲的 4 位控制信号。6 种组合看 p193。

# 七个 1 位控制信号

对着书上的图 p196 看看位置

信号名置无效时(0)效果置有效时(1)的效果
RegDst写入寄存器时,目标寄存器编号来自 rt 字段写入寄存器时,目标寄存器编号是 rd 字段 (15:11)
RegWrite数据写入由写入寄存器输入端口指定的寄存器
ALUSrc第二个 ALU 操作数来自寄存器堆第二个输出第二个 ALU 操作数是指令低 16 位的符号拓展
PCSrcPC 使用 PC+4 更新PC 使用分支目标地址更新
MemRead输入地址对应的数据输出到读数据输出端口
MemWrite将写入数据输入端的数据写入地址输入端指定的存储单元
MemtoReg写入寄存器数据来自于 ALU写入寄存器数据来自数据存储器

控制信号的输入和输出看 p200-201

# 流水线

指令执行时流水线=指令执行时非流水线流水线级数指令执行时间_{流水线}=\frac{指令执行时间_{非流水线}}{流水线级数} 这个公式要在程序指令多时成立

# 面向流水线的设计

为什么 mips 适合流水线:

  • 所有指令长度相同
  • 指令格式少,并且每条指令寄存器字段位置相同 (对称性),确定取指类型同时开始读取寄存器堆
  • 存储器操作数仅出现在 load 和 store,不可以直接访问内存
  • 所有操作数都必须在存储器对齐

# 数据冒险

有三种冒险类型

  1. 结构冒险:就是两条指令同时访问一个硬件
  2. 数据冒险:取数指令取的数是之前的目标,通过增加硬件来提前得到缺少运算项,这个方法叫做前推 (forwarding) 或者叫做旁路 (bypassing)
    取数 - 使用型数据冒险 (load-use data hazard) 上一个指令 lw,下一个指令就用,这会导致
    流水线阻塞(pipeline stall) 或叫做空泡 (bubble)
  3. 控制冒险:决策依赖于一条指令的结果,而其他指令正在执行。就是要看第一条指令结果再决定是否进行下一步,其实就是 beq 是否跳转
    解决方法是:阻塞(stall) 或者预测(predict)(通常预测分支不发生如果真发生的话会产生阻塞) 或延迟决定(就是用不相关的指令先搪塞着(调节指令顺序))

阻塞对性能影响可以看 p210

# 流水线小结

流水线不能减少单条指令执行时间(也叫延迟(latency)),流水线指示提高了吞吐率(throughput)。

# 流水线数据通路与控制

数据通路有五个部分:

  • IF:取指令
  • ID:指令译码,读寄存器堆
  • EX: 执行或计算地址
  • MEM:访问数据存储器
  • WB:写回
    每两个阶段中间有一个流水线寄存器,IF/ID 这种,store 指令最后 WB 啥也不做,但是也没有优化空间。
    每一个逻辑单元都只能在一个流水线中使用,否则会产生结构冒险,因此这些单元及其控制可以和一个流水级相关联
    流水线可以看 p216-220
    多时钟周期图在 p223,不过不知道要不要画。。。,单时钟周期就是电路图上面加了个表,在 p224

# 流水线数据冒险:旁路与阻塞

sub 指令的结果被下一条指令用到,旁路条件:
1a. EX/MEM.RigisterRd=ID/EX.RegisterRs(Rd 不等于 0&&regwrite=1)
1b.EX/MEM.RigisterRd=ID/EX.RegisterRt
2a. MEM/WB.RigisterRd=ID/EX.RegisterRs
2b. MEM/WB.RigisterRd=ID/EX.RegisterRd
这个表明流水线下 sub 这类指令会影响下面两条指令 1 和 2 的区别在于下一条还是下面第二条指令
为了这个旁路,我们亲爱的 ID/EX 流水线寄存器还多了个 5 位的 rs 字段,之前是直接保存 rs 的值的,现在 key 也要保存了。
这个具体操作还是得看 p231,信号看 p233

EX 冒险MEM 冒险
1.a:forwardA=102.a:ForwardA=01
1.bfowardB=102.b:ForwardB=01

A 和 B 其实是第一(二)个 ALU 操作数来源于哪里的问题,00 代表来自寄存器堆。
如果出现 add s1,s1,1;add s1,s1,1;add s1,s1,1 时,从 MEM/WB 去取,详情看 P233,因为 MEM 级是最新的,EX/MEM 最新的还没写进去。
# 问了老师可能书上是错的,因为 EX 是最新的

sw 和 lw 的冒险看 ppt,不过只能避免一次阻塞,也就是说有冲突必有一空泡

# 冒险与阻塞

load 指令必须阻塞一个时钟周期,这个检测叫冒险检测,检测如下:

1
2
if(ID/EX.MemRead and ((ID/EX.Rt=IF/IF.Rs)or(ID/EX.Rt=IF/ID.Rt)))
stall the pipeline

人话就是如果读的话,然后 ID/EX 的存储寄存器等于下一指令的运算寄存器就停。
阻塞的办法就是保持 PC 和 IF/ID 流水线寄存器不变。
EX 开始的部分都是 nop,将 EX、MEM 和 WB 级的 9 个控制信号清除(置 0)。方法是将 ID/EX 流水线寄存器的这三个控制信号置为 0。
这导致这个指令 IF 级在第三个时钟周期,ID 级在第五个时钟周期

# 控制冒险或分支冒险

看 p238,

# 假定分支不发生

丢弃指令就是把控制信号置 0,要改变 IF、ID 和 EX 级的三条控制信号,而不是单单 ID 级的

# 缩短分支延迟

将分支执行到 ID 级,通过逻辑门的异或来判断。
为了在 IF 级清除指令,我们加入 IF.Flush 的控制信号,将 IF/ID 流水线寄存器的指令字段置为 0

# 动态分支预测 (dynamic branch prediction)

采用分支预测缓存 (cache) 或叫做分支历史记录表 (history table), 一位数据表示最近是否发生,但是一个总是发生分支第一次和最后一次会错误。
因而采用两位预测位,具体实现看 p241-242

# 异常

控制最难部分之一是实现异常和中断。很多操作系统不区分异常和中断,但 mips 中异常是任何意外的改变,无论内外,中断是由外部引起的事件。具体看 p245 的分类
I/O 设备请求错误就是中断,像算法溢出之类就是异常(不过感觉不是很清楚)

异常发生时在 EPC (exception pc) 保存出错指令的地址,将控制权转交给操作系统的特定地址。两种方法表示异常原因,一个是 Cause 寄存器,一个是向量中断(vectored interrupt),在向量中断中,控制权转移到由异常原因决定的地址处。
多个异常在同一时钟周期同时发生先处理最早发生的异常,注意此处 EX 的异常与下一指令的 ID 异常为同一时钟周期,而不是 IF

# 指令级并行

# 多发射(multiple issue)

每一阶段有多个状态单元和组合逻辑单元
分为静态多发射(static):决策在编译阶段做出 和动态多发射:决策在执行阶段做出

# 推测(speculation)

交换指令顺序,可能会导致原本不异常的地方异常。

# 静态多发射处理器

使用编译器帮助打包多条指令并处理冒险。在给定时钟周期发射多条指令,也称为发射包(issue packet). 可将发社保看作允许同时执行多个操作的一条指令:超长指令字(Very Long Instruction Word,VLIW)
一般是双发射。(两个指令一次打包。)组合逻辑单元基本都要加倍
详细过程看 p252
这个编译器又能处理一个包的各种冒险 (不包括包与包之间的),又要减少 load 的使用延迟对打包后的 ALU 的影响,真强大。
答题看 p253-254

另一种更高性能编译技术是循环展开 (loop unrolling)
此时需要寄存器重命名来消除一些虚假的数据相关,也叫反相关(antidependence),或者名字相关

# 动态多发射处理器

也叫超标量处理器(superscalar)
采用动态流水线调度 (dynamic pipeline scheduling)

# 能耗效率

每块芯片集成多个处理器,要比复杂处理器功耗要好。

# 存储器存储结构

局部性原理:

  • 时间局部性 (temporal locality): 某个数据时间上访问间隔短
  • 空间局部性(spatial locality):空间上间距短
    用局部性原理组织成存储器层次结构
    高级存储器靠近处理器较贵。
    我们将两级层次结构中存储信息的最小单元称为块(block) 或行(line)
    如果高层存储器没有找到所需数据那么这次数据请求称为一次缺失。
    命中率(hit rate)
    缺失率(1 - 命中率)
    hit time
    miss penalty
    cache 由 SRAM (静态随机存取存储器) 实现
    memory 由 DRAM 实现

# SRAM

空闲模式下需要最小功率保持电荷,不需要刷新,对任何数据的访问时间是固定的,供电状态下数值不变

# DRAM

使用电容保存电荷,因为电容保存,所以不能长久地保持数据,需要周期性地刷新,这也是动态的原因

有 DDR(双数据速率)这个型号。这个是时钟上升下降沿都输入输出信息
DDR4 这种可对 4 个 bank 发送一个地址同时访问,用轮转方式对这四个 bank 访问可以提供四倍带宽,也称地址交叉
书上讲的不明所以,建议看 ppt

# 闪存

写操作会产生损耗,所以会有控制器将已经很多次地块重映射到写入次数较少的块中。俗称损耗均衡 (wear leveling) 技术

# 磁盘存储器

一个磁盘具有一组瓷盘片,绕轴每分钟转动近 10000 圈。每层表面有一个包含小型电磁线圈的读写磁头。

每个磁盘表面划分为同心圆盘,称为磁道,每个磁道被划分为存储信息的扇区。扇区容量 0.5KiB~4Kib.
访问数据三步骤:

  • 寻道。找到适当磁道
  • 等待要访问扇区转动到读写头下面,等待时间称为旋转延迟
  • 传输时间
    传输时间计算得看 ppt

# cache 基本原理

cache 大小不含标记位和有效位,具体算大小位数看 p292. 标记字段大小是 32-n(块的个数)-m(一块中字的个数)-2(默认字的字节偏移量)
cache 的有效大小位数2n2m322^{n}*2^{m}*32
总位数等于2n(块大小+标记字段大小+有效位字段大小)2^{n}*(块大小+标记字段大小+有效位字段大小) 别忘了这个有效位 1 位
地址映射看 p293,是向下取整。

如果仅仅增加块大小,会导致 miss penalty 的增加。
解决方法就是加快传输速率,减少这个延迟可以隐藏一些传输时间,最简单方法就是提前重启(early restart),即块中所需的字一旦返回就马上继续执行。不过这个问题在于字的分布不确定,同时若下一条指令请求另一块中的字,那么处理器就无法访问 cache。还有一种方法是关键字有限,在 p295;

# cache 缺失处理(cache miss)

cache 缺失处理由两部分共同完成:处理器控制单元,以及一个进行初始化主存访问和重新填充 cache 的独立控制器。cache 缺失引起流水线阻塞,阻塞整个处理器,冻结所有内容。我们假定顺序执行处理器。

乱序执行(out-of-order) 处理器在等待缺失处理同时仍能执行部分指令

指令 cache 缺失处理步骤:

  1. PC 原始值 (PC-4) 送到存储器中
  2. 通知主存执行一次读操作,并等待主存访问完成
  3. 写 cache 项,将从主存读回数据写入 cache 存放数据的部分。并将地址高位写入标记字段,设置有效位。
  4. 重启执行执行第一步,重新取指,这次该指令在 cache 中.
    数据缺失同理。

# 写操作处理

为保持 cache 和 memory 的一致性,我们采用两种办法:

  • write-through(写直达)直接将更改的字写入 cache 和 memory 中
    • 可以使用 (write buffer), 如果存储器完成写操作速度慢于产生写操作速度,那么没有作用。
  • write-back (写回),被替换时才要写道较低层存储结构。下面各种时 cache 缺失策略
  • 写分配,在 cache 中分配一块
  • 写不分配,只更新主存,不写入 cache 中。
    写直达比写回安全,因为写直达有内存备份,而写回没有,所以写回必须得判断 cache 是否命中再完成写操作,而写直达不需要,因为缺失就再次更改 cache。

# 小结

cache 性能可通过增加主存带宽:增加存储器位宽和交叉存取。
计算性能看 p301
平均存储器访问时间 (Average Memory Access Time,AMAT):
AMAT = 命中时间 + 缺失率 * 缺失代价

# 灵活放置块

全相联:块可以放在 cache 任何位置,适用块数较少的 cache
组相联:介于直接映射和全相联之间。每个块有 n 个可放位置叫做 n 路组相联 cache。(n 也称为相联度)
降低缺失率但是增加了命中时间。
采用更换最少被访问的块的规则更新组。
相同容量和相同块大小下,相联度其实也就一路到二路好点,缺失率降低了 15%,其余基本改善空间不大。

# 在组相联中找 cache 块

标记索引块偏移

这个是查找的信息。每组采用并行检索标记号。需要 n 个比较器和一个 n 选 1 的多路选择器。

# 替换块

采用 LRU(Least recently used)法,最久没有被使用的块。
组相联 n 越大,标记字段大小越大,因为索引其实不占 cache 大小。

# 使用多级 cache 减少损失代价

采用 L1 和 L2cache,多级 cache 性能看 p307
主存缺失代价为100ns0.25ns时钟周期=400个时钟周期\frac{100ns}{0.25\frac{ns}{时钟周期}}=400个时钟周期 这种形式
L1cache 致力于减少命中时间,L2cache 致力于改善缺失率
快排比基数排序要快因为 cache 缺失率低。

L2cache 的局部缺失率挺高的,但是全局缺失率低。

# 可信性问题

冗余技术。
失效定义:两种状态:

  • 服务完成:交付的服务于需求不符。
  • 服务中断:交付的服务与需求不符。
    失效导致状态 1 到状态 2 的转换。状态 2 到状态 1 称为恢复。
    平均无故障时间(Mean Time To Failure,MTTF)是一个可靠性度量方法。年失效率(Annual Failure Rate,AFR)指在给定 MTTF 下,一年内预期的器件失效比例。
    服务中断用平均修复时间(Mean Time To Repair,MTTR) 来度量。平均失效间隔(Mean time Between Failure,MTBF)=MTTF+MTTR。
    可用性指系统正常工作时间连续两次服务中断间隔时间中所占的比例:
    可用性 =MTTFMTTF+MTTR\frac{MTTF}{MTTF+MTTR}
    用术语故障(fault)来表示一个器件的失效,用三种方式可以提高系统的 MTTF:
  • 故障避免技术:合理构建系统
  • 故障容忍技术:荣誉措施
  • 故障预测技术:在器件失效前进行替换

# 纠正一位错、检测两位错的汉明编码(SEC/DED)

parity 校验码检测 1 位错误,称为 1 位错误检测编码(1 表示奇数,0 表示偶数)。汉明纠错码(Hamming Error Correcting Code,ECC)。
我们采用额外的校验位确定单个错误的位置。具体看 p315
校验位 1、2、4、8(编号二进制第 logn+1 位为 1)。此外,我们可以通过增加 1 位来导致码字中的最小汉明距离变到 4。可以纠正 1 位错检测 2 位错。这个增加的校验位取决于前面的奇偶纠错校验位和原数据位的奇偶产生的偶校验
以下是出现的四种情况(H 位纠错码组的奇偶性,全局奇偶校验位为 p):

  1. H 为偶,p 为偶,无错误发生
  2. H 为奇,P 为奇,出现一个可纠正错误。
  3. H 为偶,P 为奇,p 错了
  4. H 为奇,p 为偶,常出现两位错
    纠错位2p>=p+d+12^{p}>=p+d+1

# 虚拟机

操作系统虚拟机能与硬件匹配。
支持虚拟机的软件称为虚拟机监视器 (Virtual Machine Monitor,VMM) 或者管理程序 (hypervisor):VMM 是虚拟机技术核心。底层硬件平台叫主机(host),其资源被客户端(guest)虚拟机共享。
虚拟机保护功能不错,同时,商业意义上,它也有其他两个重要优势:

  • 软件管理:提供一个可以运行完整软件栈的抽象
  • 硬件管理:允许独立软件栈在共享硬件的同时独立运行,合并了服务器的数量。
    每个客户端只能达到用户级,VMM 能达到更高级,从而保证特权指令执行

# 虚拟存储器(virtual memory)

虚拟存储器中,块称为页,访问缺失叫做缺页。虚拟地址,由软件和硬件结合转化为物理地址。
在虚拟存储器中,地址被划分为虚拟页号(virtual page number)和页偏移(page offset),页偏移与物理地址一致,在低位。缺页改进方法看 p321

# 页的存放和查找

页表(page table),存放在主存中,用虚拟地址中的页号作为索引,这个页表位置由页表寄存器给出。每个虚拟机由一块页表

页表每一 entry 都有一个有效位。由于页表表示了所有虚拟页映射,所以不用标志位。看 p324 这张图。

如果虚拟也有效位无效,会出现缺页故障,那么内存要去硬盘找到该页。这个交换空间是在进程开始时在闪存或磁盘上创建的交换区 (swap space), 不管存在主存还是磁盘上,页大小相等。

LRU 替换策略

写回机制,替换时写回磁盘。页表中加个脏页。

# 加快地址转换:TLB

cache 快表 (Translation-Lookaside Buffer,TLB),TLB 中由脏位和引用位等状态位。每次访问先在 TLB 查找虚拟页号。命中的话物理页号形成地址,引用位被置位,写操作还是设置脏位。TLB 缺失要判断时页缺失还是 TLB 缺失。引用位其实就是用来 LRU 的。
TLB 换项时将引用位和脏位换到页表里(写回操作在 TLB 缺失时再写,会很高效)
TLB 采用全相联,同时随机选择替换表项。
看 p330 和 ppt
还有 p331

虚拟地址索引 cache 块,标记 TLB,可以直接知道 cache 块中有没有所需内容。

TLB 的写访问位能让一个恶意进程不能写另一个用户进程的地址空间,写访问位由 VMM 控制。
进程切换时,TLB 一定要切换成另一个表的表项。或者用进程标识符和任务标识符

# 处理 TLB 缺失和缺页

  • 页在主存,创建表项
  • 不在主存,控制权交给操作系统处理缺页
    出现 TLB 缺失和缺页要使用异常机制,EPC 记录程序计数器的值
    异常必须在同一时钟周期的末尾被判定。
    使主存写控制线无效。
    异常处理时禁止其他异常。
    页缺失时被引用的页号被保存在 BADVaddr 的特殊寄存器里。
    TLB 缺失表项插入过程看 p336,有点麻烦 处理时并不会检查表项是否有效,直接会插入。

# 小结

虚拟存储器允许单个程序地址空间拓展到主存界限之外。增大 memory 的表面大小(apparent size)
采用技术降低缺失率:

  • 增大页容量
  • 全相联
  • LRU 和访问位之类技术决定选择替换哪一页

# 存储器框架

cache 容量增加,相连度提高对性能改进作用很小,其余看 p339 吧,感觉没啥。
页表采用的是全相联全映射
cache 替换策略:相联度较高的采用随机法,较低的采用 LRU(近似实现)
写直达比写回好实现。缺失代价小:不用把整块写回更低级存储系统

# 3C 模型

  • 强制缺失(compulsory miss)也称冷启动 (cold-start miss):
    从未出现过的块的第一次访问缺失
  • 容量缺失 (capacity miss) :cache 某个块被替换后再次访问的缺失
  • 冲突缺失(conflict miss)也称碰撞缺失 (collision miss):
    多个块竞争同一组,全相联不存在这个问题。
    强制缺失可以增大块来解决
    容量缺失增大容量
    看 p343 的表

# 有限状态机控制简单的 cache

有限状态机通常假定那些没有明确置为有效的信号设置为无效信号。有限状态机实现看 p345,由一个组合逻辑和一个保持当前状态的寄存器实现。称为阻塞性(blocking)cache。

# 一个简单 cache 控制器的有限状态机

cache 控制器的 4 个状态:

  • 空闲:
  • 标记比较:
  • 写回:将 128 位的块写回存储器(DRAM 控制器通常是 128 位)
  • 分配:
    懒得写了看 p346 吧,都要等待准备好信号。标记比较状态可以和 cache 访问分离,以及价格写缓冲可以改进时钟周期

# cache 一致性

多核多处理器,多个处理器共享一个公共的物理地址空间。但是 cache 各自拥有
一致性和连贯性:

  • 单个 CPU 写后读的就是写过的
  • 一个写操作后其他 CPU 在一定间隔后可以得到写过的
  • 写操作是串行执行的,不会出现同时写入
    实现一致性的基本方案:
  • 迁移(migration):数据项移入本地 cache,这样可以不用访问共享寄存器
  • 复制(replication):共享数据被同时读取时,cache 在本地对数据项做备份,减少读取竞争
    cache 一致性协议:最常用的是监听 (snooping) 协议。cache 保留数据块共享状态的副本,不集中保存状态。所有 cache 控制器对广播介质(总线或者网络)进行监视或者监听,来确保是否由总线或交换机上的数据块副本。

# 监听协议

写无效协议 (write invalidate protocol) 处理器写操作前令其他副本无效。此时其他处理器读时需要重新请求新的数据副本,这时仍有效的 CPU 数据副本就会响应。
不过写操作处理器要独占访问,采用 random rule。

# I/O

打印机采用轮询(polling)方式,其他基本采用中断,较慢的情况下

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

小丑鱼 微信支付

微信支付

小丑鱼 支付宝

支付宝

小丑鱼 贝宝

贝宝