计算机系统原理

文章内容:计算机系统原理 PPT概括&个人理解而成的笔记
十来道单选 若干个简答题
今年好像考试改成了闭卷 建议关注下平时分 大作业有很大变动(变得很简单)
改成闭卷了 等林老师说一下重点吧!
书1-5章 6章直接看PPT
单选十几个 简答题若干
第一章: 十分具体的实例不考 知道概念 会算
第二章: 掌握常见指令格式 and or xor 其中每块内容的含义符号拓展 jump指令范围 寻址问题
编译汇编 一般性了解
第三章: 加减乘除 不直接考电路设计 了解大概结构就行
第四章: 处理器 单周期CPU 数据通路 控制信号 多周期不考
给一张架构图 要增加指令时 要调整哪些部件***
流水线 控制信号 分支旁路预测 冒险+停顿
知道概念:多发射 异常
第五章:存储技术 DRAM SRAM cache相关计算 关联方式 计算过程 汉明码
虚拟存储page fault tlb 存储层次的一般框架 实例不要求

考试内容:要记的内容 汇编指令转机器码 补码表示 指令格式 浮点数格式 (单双精度) 五级流水线
不需要记的:指令的操作码是多少 寄存器的编号 非MIPS系统的所有内容

加油考!
img
常用的内容:
bit 位
byte 字节 8位
word 字 在MPIS中为 4个字节 32位
GiB MiB KiB 以2为底数
如:1KB=10$^3$=1000, 1MB=10$6$=1000000=1000KB,1GB=10$9$=1000000000=1000MB,而 1KiB=2$10$=1024,1MiB=2$20$=1048576=1024KiB

ch1

key principle: 计算机体系结构的7个伟大思想 之后会逐渐展开!
抽象简化设计
加速大概率事件
并行提高性能
流水线提高性能
预测提高性能
存储层次
冗余提高可靠性
冯诺依曼计算机制造的三个基本原则之一:输入设备 输出设备 运算器 存储器 控制器(冯诺依曼架构)
你的程序之下:应用软件 系统软件 操作系统 硬件
编码层级:高级语言 汇编语言 二进制代码
使用者的接口实现设备 存储部分 网络部分
输入输出 存储 控制 运算
CPU: cache memory SRAM 速度快容量小(静态)
Datapath:数据通路
Control:
抽象:处理复杂的系统?
ISA 软硬件之间的接口(指令集体系结构)
寄存器(32位)> cache > 内存 > 硬盘
存储 volatile 易失性 非易失性存储器 二级存储器()
网络:局域 广域
进入具体内容:

计算机性能评估:

response time:响应时间 对用户而言的时间
throughput:吞吐率 单位时间内的总工作量
具体问题具体分析 涉及任务调度?
性能定义:时间倒数(快几倍说的是运行时间改善)
相对性能? 两个时间比一下就差不多了

关注CPU时间:用户CPU时间 系统cpu时间

影响性能的内容: 算法(影响IC CPI也有可能影响到) 编程语言(IC CPI) 编译器(IC CPI) 指令集(IC CPI T$_c$)

CPU时间的基本单元:时钟周期
clock period 一个时钟周期的时间
1/CP=CPU频率(rate,frequency)
CPU时间 = 周期数 * 周期长 (也就是 一个程序耗费的周期数除以频率:时钟周期/时钟频率=CPU时间)
CPU频率 1s内有多少个时钟周期(每个周期的持续时间是频率的倒数)
Insturuction count :指令数目
CPI :CPU时间/指令数目 (每条指令的运行周期)
CPI*指令数目*时钟周期=时间
img
对于不同指令集而言CPI也不太一样 甚至同一指令集的不同类型的指令的CPI也不太一样 img
img

功耗内容?
篇幅不大: Power = Capativeload * Voltage^2 * Frequency
功耗墙:热散不出去了 电压也不能再降了
PPT 57 after

平板上仍包含部分笔记待迁移

ch2

指令们:算术运算 逻辑运算 条件分支 无条件跳转 数据传送 伪指令

算术运算:
1.Key idea 简单+重复
img
R型指令: 包含所有不需要立即数 不需要target offset 内存访问

This group contains all instructions that do not require an
immediate value, target offset, memory address
displacement, or memory address to specify an operand
(i.e. 算术 逻辑 移位 寄存器跳转等所有操作数都在寄存器之内的指令)
2.Key idea 越小越快
指令的操作数用的寄存器都存储在 32*32位的寄存器文件中:img
(频繁访问的东西最好不要放在memory中而是放在寄存器内以加速性能)
从主存中取数 load save 每个地址都确认一个字节 所用到的word都是在内存中对齐的 也就是地址一定是4的倍数 (毕竟一个word是4个字节)
访问方式:基址+偏移
3.Key idea make the common case fast
MIPS大端序存储:
img

指令格式

img

要求记住指令类型和分段的长度和寄存器的编号
$zero 硬连线为0的寄存器 MIPS中没有赋值为0 只能加两个0 赋值到某个寄存器中

各种类型的数

Unsigned Binary Integers(32位无符号整数)

0000 0000 0000 0000 0000 0000 0000 1101$_2$ 0 - 4294967295

二进制 十进制 八进制 十六进制(a-f)转换

2 8 16 直接把若干数字压缩转换或者解压转换即可
2-10进制? 整数? 除二取余 上右下左
小数?乘2取整 上左下右 (小数可能会出现循环情况 此时只取一个近似值)

有符号整数

补码存储 一个数X原值 加上2^$n-1$或者正数和0不变 负数(首先符号位不变)取原码的反码+1(求两次补码就变成了自己的原码)或者 负数直接加2^$n$之后直接把二进制码作为它的补码img
a与-a 的补码关系相互为模2$^n$的补 -a = -a+2$^n$
补码位数扩展?跟随符号位(比如addi lb lh beq bne)

浮点数的移码

img
对于原码而言 不管三七二十一 直接加一个bias(也就是2^$n-1$)然后再转换为二进制码 (就是方便比大小)

R型指令

img
img

img
PC+4相对寻址 i-型指令 (请注意:L1<<2)(立即数L1固定是18位 加了末位两个0)

I型指令

PPT56-59
一个load指令
P18
offset 偏移!!!一般都是8的若干倍
4.Key idea good design demands good compromises
img
除了000000,00001* 和0100**以外的操作码都是给I型指令用的
img
img
取元素按照字节取 一般要乘以4(int 型)
逻辑移位操作 都当做无符号来移位 左移右移都补零
a NOR a ==非a

J型指令

j L1 j用6位 其余26位都是L1 但是用到28位(末位两位都是0)
Jal L1跳转并且记下当前地址 ($ra = PC + 4)
PPT上 跳转指令 J
伪直接寻址 地址是32位 但是实际j指令中只有26位能拿来表示地址怎么办?首先左移两位(地址都是4的倍数)之后在最前面补上当前指令+4后的最高位地址
img

伪指令 Blt branch not eq 实际上和Bne和SLT等价
Move
Beqz


比较 slt slti sltiu
边界检查简易法

过程调用 传参 四个寄存器
程序调用栈
jal mark-position 把下一条指令的地址拿来覆写$ra 这样可以跳回来


对寄存器调用的约定
$a0–$a3: arguments (reg’s 4–7)
$v0, $v1: result values (reg’s 2 and 3) 返回值直接用!
$t0–$t9: temporaries可以改的 调用过程中的暂用值
Can be overwritten by callee
$s0–$s7: saved可以传回来的值
Must be saved/restored by callee
$gp: global pointer for static data (reg 28)静态数据放在了内存里面 这是放的位置
$sp: stack pointer (reg 29)栈顶
$fp: frame pointer (reg 30)
$ra: return address (reg 31)
例子

$ra $v $r 调用者一定要保存!在栈内 $t也有可能要保存(如果return后仍要使用$t类)
$s类由被调用者去管

img
系统调用栈是向低地址增加的
img
超级经典的阶乘调用!!
img
11.7
帧指针$fp栈中活跃记录的开始部分(上一个子程序的栈末尾**)

字节/半字的操作
*较难的部分 哪一些要保存 哪一些不要保存

交换寄存器中的数字 逻辑异或

32位常数的放置 过大的部分
img
img
2相对地址 (当前指令吓一条到目标的位置之差后除以4)
20000绝对地址 (除以4)
太远的跳转地址够不着怎么办?
img
beq用j来代换
同步方式:

自己看例子
指令集待复习

ch.3 arithmetic

算术问题
加法
分辨溢出? 最高位是否变化
减法

  1. 加一个数的码的补码
    分辨溢出?同理!正减负变负了?溢出了!!
    加法器:
    计算时间 门的速度
    sum 6个门延迟
    carryout 2个

补码加减计算公式:
[-B${bu}$]=[B$$]+1

乘除
img
对被乘数 不断移位加入寄存器 但是是否写入受乘数控制 所以会慢许多
img
img
因而开发了如上的快速乘法器
专门安排了两个寄存器hi lo 在mult操作后 hi lo 存储乘积
mul就不存lohi了 直接把后32位存
除法
不断减就行 但是减的时候需要判断(也即试商)
有符号的除法 会有余数 此时要求余数符号与被除数符号一致
浮点数的表示 使用科学记数法
1.xxxxxxx*2$^yyyyy$
img
bias 是移码 使得原本只能是正数的exponent可以为负数 两端值可以不用
img
img
Fraction 小数部分有前导的1,计算的时候相当于整个数字前面加上一个小数点的二进制表示
指数最小 尾数是零时特殊解释 此时为0.0而不是1.0 当然可以无限逼近零
指数最大 尾数为0,此时为无穷(有正负) 如果同样条件下尾数不为0,此时为NaN
对接 小的向大的看齐 运算 规范化检查 最后舍入再规范化
img
指数相加 记得额外减去一次偏置!!
浮点数运算的专属寄存器:$f0-$f31
round 舍入 四舍五入 恰好是五 一半时间 向上取整 向下取整
额外的精度位 精度以下下第三位 粘滞位 表示有无舍弃
img

ch4

CPU
img
红圈的地方要加多路选择器
写入寄存器需要写信号!!
所有的部件运行都在时钟控制下
img
建立时间 保证源信号稳定 保持时间 信号写入无异常
img
上升边缘+write信号 才能写入
img
时钟周期由最慢的指令和部件决定(最长延迟路径+建立时间+保持时间+时钟偏移)

  1. 指令fetch
  2. 寄存器堆

  3. img
    ALU控制 两级控制 根据操作码 产生两位的ALU控制信号(根据操作码)
    img
    分级控制 不仅根据ALUop 还根据功能码

img
控制中心产生的各种信号 :

  1. 写入的寄存器是rt还是rd(load就是rt R-type就是rd分别对应信号0 1)
  2. 寄存器写信号(是否需要写入东西覆盖寄存器)
  3. AILUSrc 控制第二个操作数来自寄存器或者立即数(0 1)
  4. PCSrc 控制PC的来源是PC+4还是branch(0 1)
  5. MenRead 控制是否读入外部内存(0 1)
  6. MemWrite 控制是否写入外部内存(0 1)
  7. MemToReg 控制要写到寄存器的数据来源是ALU的输出还是从外部内存读入的(0 1)
  8. branch 是否是分支指令
  9. ALUop1:
  10. ALUop2:
    img
    (需要练习!!!!!)
    img
    实现Jump 指令
    26位地址左移两位 最高四位再copy PC+4 跳转最后再加一个二选一
    pipelining 提高性能
    img
    读是在后100ps
    写是在前100ps 刚写完就可以读

结构冒险:

额定的资源忙碌而产生等待 (产生空泡)一开始是设计的时候就考虑的

数据冒险:

数据相关性
img
流水线对编程者是不可见的 如何避免这种数据冒险?自动插入空操作 尽量把WB和ID嵌合
旁路 目标值在EX阶段末尾已经确定 但是没有写到寄存器 这时可以拉一条旁路信号送到下一条指令的EX阶段 当然这并不能解决所有的情况 有的部分是在MEM阶段才有目标值 所以需要用一条空指令
软件可以调度指令来更好地避免空泡(把空泡换成另一条无关的指令)
两条指令是读数据或存数据 可以换

控制冒险:

并不总是顺序执行的+跳转指令
流水线要取指令 面对控制跳转 没办法按照流水线立即嵌入下一条指令
1. 可以在reg阶段把跳转指令的判断产生都在一个stage里面做完 完成阶段然后就能知道跳转位置了 但还是要一个空操作
2. 也可以做分支预测 做指令预取 可以先假设不跳转 立即取n+1条指令开始做 第n条真正判断后 再决定第n+2条指令 和 第n+1条指令的存废 预测错误 就相当于没有预测
静态预测方法思想:往后跳的概率大 往前跳的概率小
动态预测方法思想:记录分支前一次的跳转情况 并假设仍然这样跳来预取
img
小习题:MiB KiB MB KB 前者2的若干次方 后者10的若干次方
img
流水线开始的时候一条通路中分为5个阶段:IF ID EX MEM WB每个部分都在执行一条命令 如何实现这些部分的并发? 比如读写寄存器和跳转地址这两条往回走的线路(其他正着往回走没什么问题)
一个时钟周期前半段用来写回去 后半段用来读取
有的信息采用的是前一阶段的输出 必须把这个信息带走或者保存一下 存到灰色部分中:img
(阶段之间增加的一组临时寄存器 我们是看不到的)
命名规则:阶段之间夹着 easy! 但是作为一组寄存器如何表示其中的每个寄存器? 规则 xxx.A xxx.B xxx.C
一些妥协? 这一组寄存器查询会稍稍变慢
改进的CPI = 1
单周期图:
有地方不对!写寄存器写的寄存器名字没有传递下去会写到错误的地方去。
有的时候某个阶段根本用不上 但是仍然要占位做
控制器 要实现对每一条指令的控制信号都是独立存储使用
分一下每一个控制信号:

  1. 无控制
  2. 无控制
  3. ALUOp ALUSrc RegDist
  4. MemRead MemWrite branch
  5. MemToReg Reg-Write
    img

减少冒险而产生的停顿?

  1. 硬件方法(需要有检测的手段)

    1. 旁路?有点意思
      img
      下一条指令从前一条指令的输出中取值 对于一个ALU来说 它的输入可以从它的输出的寄存器组中来(因为输出的寄存器组就是前一个指令的运算结果 直接拿过来用了)
      上面这张图中 第一条指令和第二条第三条指令存在数据冒险! 如果有就可以从前一条或者前两条指令的输出中取值 怎么取? 从后两个阶段的寄存器组中取值!
    2. 怎么检测?
      img
      而且前一条指令要写入寄存器!才会产生数据冲突(RegWrite=1)而且如果读或者写的是0 也不产生冲突 排除这种情况
      因此增添了旁路单元
      img
      img
    3. 双重数据冲突
      上面两条指令都写入了某个或者使用某个寄存器 我们优先取最新的!(要看书?)
    4. load-use hazard
      取数据指令 + 立即计算该数据 = 额外停顿一次
      why?不是有旁路吗? 实际上这是因为load不能立即拿到结果 差了一个时钟周期 因此需要插入空指令 当然没有旁路还是有用的 没有这个就会停顿两个周期而不是一个了
      这个东西怎么检测?
      img
      插入空指令?
      img
      控制信号置为零 + 阻止指令地址更新
      flush信号 把ID/EX的控制信号置为零 阻止IM/Reg 的更新和$PC的更新
      因此增加hazard detection unit
      img
      增加了 PCWrite 和IF/IDwrite 信号来控制更新与否
    5. 分支冒险
      输入条件跳转指令一般在DM阶段后才能知道要不要跳转 跳转到哪里 这期间去紧跟的下面几条指令立即开始执行 有可能是错误的指令 后面的三条指令都要废掉!(也就是控制写入的信号都变成0)会造成性能的极大下降(三个时钟周期)
      旁路还不太够 因为分支判断在ID阶段就要计算了 要一套旁路和检测

    检测方法:判断分支要用的寄存器是不是前面一条的指令的输出!如果是,必须停顿一次 如果是前2个以上 使用旁路即可

    lw 会产生取用冲突 必须停顿 beq也会有冲突 如果lw后面紧跟beq会产生冲突 因此要停顿两个周期
    能不能少停顿?

    1. 分支判断 和目标地址计算 早一点ID阶段能不能就把它做完 后者可以的
      前者要增加一些硬件 判断逻辑:取异或如果都是0 就相等
      额外的问题:旁路传到的是EX阶段 但是分支跳转在ID阶段就要用:要么停顿一下 要么就旁路到ID
      img
    2. 分支调度
      延迟分支:大部分分支都要延迟一个周期 正好把空着的这个槽执行另一条指令(前提是不产生依赖冲突)
      动态预测:
      根据运行中跳转与否的实际情况来预测 始终跟随上一次的跳转情况(用一个history table 也叫branch prediction buffer)
      img
      一位预测器的一些问题?两层循环时必然出现两次预测错误(一次进入 一次出去) 造成很大的负担
      换成两位预测器: 强发生 弱发生 弱不发生 强不发生 根据实际发生与否才会把发生状态改变一个 这样内循环预测错误就少了一个
      有可能把跳转的地址也存在缓存里面 这样可以减少等待取地址的周期
  2. 软件方法

    1. 编译时改换次序
  3. 异常(exception)处理和中断(interrupt)处理

    1. 异常:程序执行时由于错误或事件导致程序不正常运行(CPU内部)
      ex:溢出 操作码问题 参数错误 syscall
      两个硬件实现的寄存器
      EPC: 异常发生时的PC地址+4
      cause:异常类型
      异常发生前面的指令要执行完 发生的指令和后面的指令要终止(不能写回)(使用EX.flush,IF.flush,ID.flush)
      同时在跳转指令部分自动选择进入80000180 也就是异常处理的第一条指令 这时EPC中的内容被立即存到另一个地方(防止覆盖)
      img
    2. 中断:程序执行时由于事件导致程序不正常运行(CPU外部)
      ex:I/O设备读写发出的中断
      指令级并行 (多发射流水线提升通道数0) CPI降到小于一 IPC 每个时钟周期执行的指令数
      静态和动态多发射,分别由编译器和CPU运行时决定
      静态 :编译器来优化内容 硬件要增加一倍 比如读寄存器的时候从读两个变成读四个 其中碰到的冲突由编译器调度解决
      img
      并行程度低 进行循环展开来暴露更多并行度 减少了跳转的情况!
      但是要行循环展开来暴露更多并行度 减少了跳转的情况! 可以进行寄存器的重命名
      img
      动态 :img

有一部分笔记在平板上
img

Tag 地址的高位 地址的后几位直接用来定位缓存中存储的位置 也就是index(在哪个块里面) 每一次访问都是把二进制串直接给cache先在cache里面寻找 第一次访问 发现不是vaild 那就是miss 把数据存进去 更新Tag 和Valid位 在第一次访问miss后 再通知CPU访问一次cache 之后的访问中如果tag和字串的内容不相同 那就还是miss 要考的!
img
img
读一个word 的时候会读一个块大小的数据 块大一点 可以一次取出多个word 减少miss的次数 但是miss的代价会很大(毕竟要额外等一等再去取来若干的word) 当然可以去early restart(读到最重要的word后直接开始) 但是会造成更加复杂的设计
影响的有流水线的两个阶段: IF MEM
指令cache 和数据cache是分开的!!
miss了? 那只能停顿了!
write back ? 写回内存还是缓存? 可能会有两个不一样版本的数据:
解决:只更新cache里面的数据?X
wtite through :也写回内存 (造成写数据的时间变长)
write buffer:要写的数据先放到缓冲区里面,等写满再一起写回去
write back: 写回的时候如果数据命中 只更新cache里面的数据 (造成数据暂时不一致) 最终cache还是要把数据写回内存 (另外用一个dirty bit来判断有没有更新过)如果来了一个新的数据覆盖在了dirty位为1的地址上,那么把原来的数据写回内存后,再将新的数据写回内存(甚至可以再次使用write buffer 把数据再次扣下来)
(笑死了 多核多线程的时候就需要有锁机制了)
img
写的时候有可能出现缓存miss 要么就 write through 取来的东西不分配缓存或分配缓存都可以 要么就write-back 一般要分配缓存地址
下面这张是好图!
img

img

可以提高总线带宽 or 内存分布到四个bank里面构成数据交错 取的时候可以并行 取bank1 bank2 bank3 bank4 当然也和bank的分布有关
评估CPU缓存的性能:分别看I-cache和D-cache数据缺失率的占比
img
平均时间? AMAT
一般时间+缺失率*缺失损害
直接映射缓存设计:(实际上就是一路的组相连)
全相连设计:(block num路组相连)
n路组相连:所有cahce块分为若干组
搜索的时候只需要在某一个组中比较n个块:介于全相连和完全映射之间
img
(8 entries +8路组相连 = 全相连)
img
直接映射:块为4 直接模4后放块
组相连的index 就是组号!
img
LRU:最近最少使用 踢出最早被用的
img
多层的cache:
ppt:58-59
考量: L1cache 的主要目标是提高访问速度,而L2cache的主要目标是降低延迟对全局的影响
一些CPU的高级优化:
乱序执行 找没有依赖的指令率先执行

故障与依赖

MTTF :平均故障时间
MTTR :平均恢复时间
平均可用时间: MTTF/(MTTF+MTTR)
汉明码:

  1. 奇偶校验位:奇数个1的个数是1,偶数个1的个数是0
    汉明距离:
    两个位串的汉明距离是 不同位数的个数
    SEC编码:
    img
    在原有的8位上再附加4位 参见图片 但是如果有
    img
    纠错码的位数和数据位数不是线性相关的

物理内存与虚拟内存:
所有东西都在硬盘上 系统会有很多程序 实际上的内存是共用的 对于一个程序而言 它的内存是私有的也就是虚拟的 (和物理内存有联系)
虚拟内存和硬盘管理的方式?分页 取一个page
要找的页 内存里面没有 就叫做页缺失 page fault 代价太大
img
建立映射
编辑 编译 汇编 链接 装入
每条指令和操作数的地址都是虚拟地址 在链接时确定
装入时生成页表来建立 虚拟地址和物理地址之间的映射
固定大小?例如4K
img
页号 + 页内偏移
虚拟内存映射:
全相连设计
页替换以降低缺失率
程序访问内存时实际上是先访问页表 然后 在访问指向的物理地址
img
有意思的idea 对换区
页表寄存器指向页表的基地址 根据页号做索引找到对应的虚拟页 在找到对应的物理页
替换: LRU策略
>> 寄存器的编号不要记
>> 各种数据的表示要记 编码要记
加入referrence bit 用过了就置位 定期置位为0 在准备踢出时 找为零的页
写入策略只用 write-back
页表有多大?
32位虚拟地址 4KiB 的页 每个页表通道4字节
总size?:
img
TLB : Translation Lookaside Buffer 为了避免每次访问内存实际上总共访问了两次
页表的"cache" 在cpu内部 专门存储TLB 存储页表访问最频繁的条目 访问内存时先访问TLB miss后再访问页表
16-512PTEs 局部性特别好(
TLB 缺失?
如果在页表里面
img
上面是一张关键的图
img
内存与页交换频繁发生:抖动 thrashing
working set :工作集

TLB:一般大小 32-64个页条目 TLB适当大一点比较好

冷启动 第一次访问的时候会比较慢
capacity miss: 容量不够用
conflict miss: 冲突
PPT117以前

posted @ 2024-10-23 09:31  My_Dearest  阅读(207)  评论(0)    收藏  举报