--- title: "《计组》存储系统" date: 2023-07-17T20:39:45+08:00 --- ## 存储器的分类 ### 计算机中的作用分类 * 主存储器【主存】 * 用于存放计算机运行期间所需的程序和数据 * 容量小 * 存取速度快 * 价格较高 * 辅助存储器【辅存/外存】 * 用于存放当前暂时不用的程序和数据以及一些需要永久性保存的信息 * 辅存的内容需要调入主存后才能被CPU访问 * 容量大 * 存取速度慢 * 单位成本低 * 高速缓存存储器【Cache】 * 位于主存和CPU之间 * 用来存放当前CPU经常使用的指令和数据,以便CPU能高速地访问他们 * 现代计算机通常将其制作在CPU中 * 存储容量小 * 存储容量小 * 价格高 ### 存储介质分类 * 磁表面存储器 * 磁盘 * 磁芯存储器 * 半导体存储器 * MOS型存储器 * 双极型存储器 * 光存储器 * 光盘 ### 存取方式分类 * 随机存储器【RAM】 * 存储器的任何一个存储单元都可以随机存取 * 存取时间与存储单元的物理位置无关 * 主要用于做主存或高速缓冲存储器 * 读写方便、使用灵活 * 分为静态RAM和动态RAM * 主要为用户编程设置 * 只读存储器【ROM】 * 存储器的内容只能随机读出而不能写入 * 信息一旦写入就不变,断电后也不消失 * 通常用于存放固定不变的程序、常数和汉字字库 * ROM与RAM一起统一构成主存的地址域 * ROM和RAM的存取方式均为随机存取 * 操作系统的内存储器既又RAM也有ROM * 广义上的ROM现代可以通过电擦除进行写入 * ROM存放系统程序,标准子程序和各类常数 * 串行访问存储器 * 直接存取存储器【磁盘、光盘】 * 既不是随机存取也不是按顺序存取 * 顺序存取存储器【磁带】 * 存取速度慢 * 只能按某种顺序存取 ### 信息可保持性分类 * 易失性存储器 * 断电后,存储信息消失【RAM】 * 非易失性存储器 * 断电后,信息仍保留【如ROM,磁表面存储器,光存储器】 ### 其余考点 * 主存储器即主存,存储指令和数据,由RAM和ROM实现 * 主存储器在PC外,按地址访问 * 控制存储器用来存放实现指令系统的所有微指令,由ROM实现 * 控制存储器在CPU的控制器内,按照微指令的地址访问 ## 存储器性能指标 * 存储容量 * 存储容量 = 存储字数 * 字长 * 存储字数表示存储器的地址空间大小【MAR】 * 字长表示一次存取操作的数据量【MDR】 * 1G = 1024M;1M = 1024K * $1S = 10^3ms【毫秒】 = 10^6us【微秒】 = 10^9ns【纳秒】 = 10^{12}ps【皮秒】$ * 单位成本 * 每位价格 = 总成本/总容量 * 存取速度 * 数据传输率 = 数据的宽度/存储周期 * 数据传输率中的K,M是10的次方而不是2的次方,只有存储容量是2的次方 * 存储周期大于存取时间,因为由一段恢复内部状态的复原时间 * 存取时间$T_a$ = 从启动一次存储器到完成该操作所经历的时间 * 存取周期$T_m$ = 存储器进行一次完整的读写操作所需的全部时间、 * 主存带宽$B_m$ = 数据传输率 = 每秒从主存进出信息的最大数量 = 单位$\frac{字}{秒}$ ## 多级层次的存储系统 ![](../../images/408/《计组》存储系统/多级层次的存储系统.jpg) * 层次结构:Cache$\rightarrow$主存层和主存$\rightarrow$辅存 * 前者解决CPU和主存速度不一致的问题 * 后者解决存储系统的容量问题 * 层次思想 * 上一层的存储器作为低一层存储器的高速缓存 * 上一层的内容是下一层内容的一部分 * Cache和主存能与CPU直接交换信息 * 辅存要通过主存与CPU交换信息 * 主存与CPU、Cache、辅存都能交换信息 * 主存和Cache之间的数据调动是由硬件自动完成的,对所有程序员透明 * 主存和辅存之间的数据调动是由操作和OS共同完成的【换入换出技术】,对应用程序员透明 ## 主存储器 ### 存储芯片/主存储器内部结构 * 存储器芯片的组成 * 存储体 + IO/读写电路+地址译码器+片选控制信号+读写控制信号 * 读RD/写WR控制线:决定芯片进行读还是写操作 * 片选线CS:确定哪个存储芯片被选中,可用于容量扩充 * 引脚最低数目 = 片选线(1) + 控制线(2,读RD写WR) + 数据线 + 地址线 ![](../../images/408/《计组》存储系统/存储器芯片的组成.jpg) * 主存储器的组成部分 * 数据线的宽度 = MDR的宽度 = 存储字长 * 地址线的宽度 = MAR的宽度 = 存储字数 * 如下图的总容量为$2^{36} \times 64位 = 2^{39}B$ ![](../../images/408/《计组》存储系统/主存储器的组成部分.jpg) ### 存储体的组成元素 * 存储体 + 存储单元 + 存储元 * 总容量 = 存储字数 + 存储字长 ![](../../images/408/《计组》存储系统/存储体的组成元素.jpg) ### 寻址方式 * 题目上未明确按字编址,则默认按字节编址【一字节8位】 * 32位的计算机:32位(bit) = 4字节(byte) = 1字(word) * 64位的计算机中:64位(bit) = 8字节(byte) = 1字(word) * 字存储单元 * 存放一个机器字的存储单元,相应的单元地址叫字地址 * 字节存储单元 * 存放一个字节的存储单元,相应地址称为字节地址 * 按字寻址的计算机 * 计算机中可编程的最小单位是字存储单元, * 按字节寻址的计算机 * 计算机中可编程的最小单位是字节 * 一个机器字可包含数个字节,所以一个存储单元也可以包含数个能够单独编制的字节地址 * 例子: * 一个16位二进制的字存储单元可存放两个字节,可以按字编址,也可以按字节编制,用字节编址时,16位的存储单元占两个字节地址 ### 地址复用技术 * 引入原因 * DRAM芯片容量大,地址位数多,出于减少地址引脚线的目的引入 * DRAM因为分两次发送,长度相同,因此地址线可以复用,线数减少了一半 * 引脚数 = 地址线减半 + 数据线不变 + 行通选(1) + 列通选(1) + 读写控制线(2) * 片选线用行通选线替代 * DRAM采用地址复用技术【计算引脚时需注意】,SRAM不采用 ### SRAM和DRAM的对比 ||SRAM【Static Random Access Memory】|DRAM【Dynamic Random Access Memory】| |---|---|---| |主要用途|Cache|主机内存| |存储信息|触发器,双稳态电路|电容| |破坏性读出|非|是| |需要刷新|不要|需要| |送行列地址|同时送|分两次送| |运行速度|快|慢| |集成度|低|高| |存储成本|高|低| ### 只读存储器【ROM】 * ROM的特点 * 结构简单,位密度比可读写存储器高 * 具有非易失性,可靠性高 * ROM的类型 * 掩模式只读存储器 【EROM】 * 内容在生产过程中写入,可靠性高,集成度高,价格便宜但灵活性差 * 一次可编程只读存储器【PROM】 * 用于用户实现一次性编程 * 可擦除可编程只读存储器【EPROM】 * 用于用户实现多次性编程,可多次改写,但次数有限,写入时间过长 * Flash存储器 * 既可在不加电的情况下长期保存信息,又能在线进行快速擦除和重写 * U盘就是基于Flash的只读存储器 * 价格便宜,集成度高,电可擦除重写且擦除重写速度快 * 固态硬盘【SSD】 * SSD即闪存,一种非易失性存储器,采用随机访问方式 * 可长期保存信息,快速擦除和重写,相比传统硬盘也有读写速度快、低功耗的特性,但价格较高 ### DRAM刷新 * 刷新 * DRAM电容的电荷维持时间短,即使电源不断电,信息也会自动消失 * 因而每隔一段时间必须刷新,一般取2ms,即刷新周期(再生周期) * DRAM的刷新以行为单位 * 一次完整的刷新只需要占用一个存储周期 * 假设例子 * 刷新周期为2ms,存取周期为0.5us;刷新时间 = 存取周期,因为刷新的过程与与一次存取相同,只是没有在总线上输入输出 * 存取周期>真正用于存取的时间,因为存取周期内,存取操作结束后依旧要一些时间来改变状态 * 对$128\times128$的矩阵的存储芯片进行刷新,按存储单元(1B/单元)分为128行128列,即$128\times128\times1B/单元 = 2^{14}个单元\times1B/单元 = 16KB内存$ * 如果为64$\times64$的矩阵,则为$64\times64\times1B/单元 = 2^{12}个单元\times1B/单元 = 4KB内存$ #### 集中刷新 * 在规定的一个刷新周期内,对全部存储单元集中一段时间逐行进行刷新,此时必须停止读/写操作 * 刷新流程 * 用0.5us*128 = 64us的时间对128行进行逐行刷新 * 由于这64us的时间内不能进行读/写操作,故称为死时间或访存死区 * 由于存取周期为0.5us,刷新周期为2ms,即4000个存取周期 * 刷新与存取不能并行原因 * 内存只有一套地址译码和片选装置,刷新与存取有相似的过程 * 刷新时需要选中一行,即占用片选线,地址线,地址译码器 * 同理,刷新操作之间也不能够并行 ![](../../images/408/《计组》存储系统/集中刷新.png) #### 分散刷新 * 对每行存储单元的刷新分散到每个存取周期内完成 * 把机器的存取周期tc分成两段,前半段tM用来读/写或维持信息,后半段tR用来刷新 * 刷新过程 * 每个存取操作后绑定一个刷新操作,延长存取周期 * 存取周期变成0.5us + 0.5us = 1us * 此时由于与存取操作绑定,无需专门给出一段时间刷新 * 每有128个读取操作就会刷新0~127行一遍,即每隔128us就可以将存储芯片全部刷新一遍【刷新周期为1us$\times$128 = 128us远远短于2ms】 * 不存在停止读/写的死时间,但存取周期变长,整个系统速度都降低了 * 分散刷新的刷新周期为128us,但其实无需如此频繁,产生了浪费 ![](../../images/408/《计组》存储系统/分散刷新.png) #### 异步刷新 * 可以缩短死时间【仍存在】,又能充分利用最大刷新间隔为2ms的特点 * 刷新过程 * 在2ms内对128行各刷新一遍,即每隔15.6us刷新一行(2000us/128$\approx$15.6us),而每行刷新的时间仍未0.5us * 刷新一行只需停止一个存取周期 * 但对每行而言,刷新间隔仍为2ms,而死时间为0.5us * 对每一段而言是集中式刷新,对整体而言是分散式刷新 * 特点 * 将DRAM的刷新安排在CPU对指令的译码阶段,此阶段CPU不访问存储器 * 克服了分散刷新需独占0.5us用于刷新的缺点 * 是存储周期加长且降低系统速度的缺点,又不会出现集中刷新的访存死区问题 * 根本上提高了整机的工作效率 ![](../../images/408/《计组》存储系统/分散刷新.png) ### 多模块存储器 * 多模块存储器 * 一种空间并行技术,利用多个结构完全相同的存储模块的并行工作来提高存储器的吞吐率 * 单体并行存储器 * 存储器中只有一个存储体,每个存储单元存储m个字,总线宽也为m个字,地址必须顺序排列并处于同一存储单元 * 过程 * 在一个存取周期内,从同一地址取出m条指令,然后将指令逐条送至CPU * 缺点 * 指令和数据在主存内必须是连续存放的,一旦遇到转移指令或操作数不能连续存放,这种方法不明显 * 多体并行存储器 * 由多体模块组成,每块都有相同容量和读取速度,各模块都有独立的读写控制电路、MAR和MDR,既能并行工作也能交叉工作 * 高位交叉编址(顺序方式) * 特点 * 先在一个模块内访问,等到该模块访问完后才转到下一个模块访问 * 编号 * 高位地址表示体号【模块号】,低位地址表示体内地址 * 优点 * 某个模块进行存取时,其它模块不工作 * 某一模块出现故障时,其它模块可以照常工作 * 通过增添模块来扩充存储器容量比较方便 * 缺点 * 各模块串行工作,存储器的带宽受到了限制,并不能提高吞吐量 * 示意图 * ![](../../images/408/《计组》存储系统/高位交叉编址(顺序方式).jpg) * 低位交叉编址(交叉方式) * 特点 * 连续地址分布在相邻的不同模块内,同一模块内的地址是不连续的 * 地位交叉编制时交叉存放的,满足程序的局部性原理 * 编号 * 高位地址表示体内地址,低位地址表示体号【模块号】 * 优点 * 对连续字的成块传送可以实现多模块并行存取,提高存储器的带宽 * 计算 * 每个模块按模m交叉编址,模块号 = 单元地址%m * 设模块字长等于数据总线宽度,模块存取一个字的存取周期为T,总线传输周期为r,则存储器交叉模块的数目最小为m=T/r * 每个r时间延迟后启动下一模块,当数目不小于m时,就可以保证T时间后再启动该模块,流水线就不会中断 * 取m个字的时间为T+(m-1)r,顺序方式时间为mT * 判断发送访问冲突的规则 * 给定的访存地址在相邻的四次访问中出现在同一个存储模块中 * 示意图 * ![](../../images/408/《计组》存储系统/低位交叉编址(交叉方式).jpg) * ![](../../images/408/《计组》存储系统/低位交叉编址流水线方式存取示意图.jpg) * 计算带宽 * ![](../../images/408/《计组》存储系统/多体并行存储器-计算带宽.jpg) * 常考 * 模块数=4,存储周期T,字长W,数据总线宽度即为W,总线传输周期r,连续存取n个字,分别求带宽 * 有m个存储体,存储周期为T,字长为W,每隔r时间启动下一个存储体,连续存取n个字,分别求带宽 * 带宽 = 存储速率 = $\frac{总量}{时间} = \frac{n\times W}{t}$【顺序t = mT】【交叉t = T+(m - 1)r】 ## 主存储器与CPU的连接 ### CPU与存储器的连接原理 * CPU读指令,通过地址线去访问存储器的MAR(地址寄存器) * MAR(地址寄存器)通过选通线去访问矩阵中的数据 * 矩阵需要通过数据线与MDR(数据寄存器)进行接发 ### 主存容量的扩展 * 位扩展法 * 8K * 8位的存储器 = 共8片 8K*1位的RAM组成 * 地址线并行,数据线一一接上 * 结构图 * ![](../../images/408/《计组》存储系统/位扩展法.jpg) * 字扩展法-线选法实现 * 18k * 8位的存储器 = 2片8K*8位的存储器 * 由片选信号来区分芯片的地址范围 * 当A12为1时,第一块工作,A13的CS必须为0 * 谁工作,数据线就接送谁的数据吗,即将CS设置为1 * 2位二进制时,只能利用01,,0 * 结构图 * ![](../../images/408/《计组》存储系统/字扩展法.jpg) * 字扩展法-译码片实现 * 有4块芯片,不需要4条线而只需要两条 * 2位二进制时,可以利用00,01,10,11 * 译码器 * 一个二进制转十进制的物理元件,将三根地址线表示的二进制意义映射到右边十进制的选通线 * 结构图 * 地址线应为A0~A11共12位,译码线位A12和A13共2位 * ![](../../images/408/《计组》存储系统/字扩展法【译码片实现】.jpg) * 字位同时扩展法 * 一块芯片只有4位,因此通过两片叠加实现位扩展 * 等价于实现了一个8位的存储芯片 * 在通过译码片选的方式实现字拓展 * 在不同的地址线中选择不同的芯片组合进行工作 * 结构图 * ![](../../images/408/《计组》存储系统/字位同时扩展法.jpg) 线选法和译码片选法的比较 |线选法|译码片选法| |---|---| |n条线$\rightarrow$n个选片信号|n条线$\rightarrow 2^n$个选片信号| |电路简单|电路复杂| |地址空间不连续|地址空间可连续,可以增加逻辑设计| 例题:求字扩展法的地址 ![](../../images/408/《计组》存储系统/求字扩展法的地址例题.jpg) ## 外部存储器 ### 固态硬盘SSD * 定义 * 一种基于闪存技术的存储器 * 组成 * 一个SSD由一个或多个闪存芯片和闪存翻译层组成 * 优点 * 有半导体部分组成,没有移动的部件 * 随机访问的时间比机械硬盘快很多 * 没有机械噪声和震动 * 能耗低 * 抗震性好 * 缺点 * 易磨损 * ![](../../images/408/《计组》存储系统/SSD.jpg) ## 高速缓存存储器 ### Cache * 高速缓存存储器就是存在于主存与CPU之间的一级存储器,有了它CPU可以直接对其存取数据,从而减少了时间,提高了系统的运行速度 * CPU与Cache/主存的信息交互单位为字,Cache与主存的信息交互单位为块 * 一个块通常由若干字组成 ### Cache提高存储速度原因 * 局部性原理 * 时间局部性 * 程序中的某条指令一旦执行,则不久之后该指令可能再次被执行,如果某数据被访问,则不久之后该数据可能再次被饭翁 * 空间局部性 * 一旦程序访问了某个存储单元,则不久之后,其附近的存储单元也将被访问 * Cache利用了局部性原理 * 将程序中正在使用的部分存在容量较小但速度更快的Cache中,使CPU更多针对它进行提高速度 * 指令与数据Cache分离的目的 * 减少指令流水线资源冲突 ### Cache的读写过程 * CPU、Cache和主存三者的读写关系 * Cache会从主存中一并读取目标数据以及附近空间的数据【通常以块为单位读出】 * CPU要取数据会优先从Cache中读取,因为速度快 * CPU计算完后,会把数据再次返回给Cache * 无法从Cache中直接存取时,CPU会进行补救 * 让Cache读取主存,CPU再从Cache中读取 * CPU一边直接访问主存读取,一边让Cache读取主存,CPU再从Cache中读取 ![](../../images/408/《计组》存储系统/Cache的读写过程.jpg) ### Cache的性能分析 * Cache命中率 = $\frac{Cache的总命中次数}{Cache的总命中次数 + 访问主存的总次数}$ * 系统平均访问时间 = 命中的概率$\times$命中所需要的时间+缺失的概率$\times$平均访存次数$\times$一次总线读突发总线事务所需时间 * 性能效率 = $\frac{访问Cache的时间}{系统平均访问时间}$ ### 实现Cache的关键问题 * 地址映射 * 主存块如何存放在Cache中,如何将主存地址转换为Cache地址 * 替换策略 * Cache满后,使用何种策略对Cache块进行替换或淘汰 * 写入/更新策略 * 如何既保证主存块和Cache块的数据一致性,又尽量提升效率 ### 地址映射 * 全相联映射-空位随意放 * 定义 * 只规定了主存需要映射到Cache中 * 没有规定它映射到cache中的哪一个位置 * 通常使用按内容寻址的相联存储器进行地址映射 * 计算方法 * 全相联中的t,c,b,m和直接映射中的都一样 * 例图 * ![](../../images/408/《计组》存储系统/全相联映射.png) * 优点 * 映射灵活 * 块冲突概率比较低 * 空间利用率也高 * 缺点 * 成本高 * 速度慢 * 耗时多 * 直接映射-对号入座 * 定义 * 规定好了主存中每一块都放置在cache中的哪个地方 * 而且相邻块之间映射的位置也是相邻的 * 因为主存的容量肯定比cache大得多,其实相当于一轮轮映射过去 * 例图 * ![](../../images/408/《计组》存储系统/直接映射.png) * 计算方法 * 主存地址长度 * 主存中存储单元个数为$2^{10}$,则主存地址长度就是10 * Cache地址长度 * Cache中存储单元个数为$2^{10}$,则Cache地址长度就是10 * Cache行的总位数 = 标记位数t + 数据位 + 1位有效位 + 1位脏位(回写策略) * t * 别名 * 主存区号 * Tag位 * 主存字块标记 * 通过主存区的标记位数就能知道这个cache属于主存的第几区 * t = 主存地址长度 - Cache地址长度 * t = 主存大小/Cache大小 * c * Cache块的地址位数 * 如有1k个Cache行,则Cache块的地址位数 = c=10 * m * 主存块的地址位数 * 如有1k个主存块,则主存块的地址位数=m=10 * b * 块内地址位数 * 如块的大小为32B,按字节编制,块内地址位数=b=5 * 有效位 * 每个Cache行一般都有一个有效位,判断Cache是否命中【加上计算位数】 * 有效位的作用是指出所在Cache行中的信息是否有效 * 脏位 * 如果是回写策略,则需要1个脏位 * LRU位 * 如果有用LRU替换算法,则增加一位LRU位 * 其他 * m = t + c * m = 主存地址长度 - b * 主存地址长度 = t + c + b * 优点 * 简单、成本低、易实现 * 由于物理位置也是相邻的,所以地址变换速度快 * 不需要替换算法 * 缺点 * 映射方式不够灵活 * 空间利用率最低 * 块冲突概率最高 * 组相联映射-按号分组,组内任意放 * 定义 * 先按号分组【如8块Cache分为四组】 * 组内再任意放【组内为全相联映射】 * 例图 * ![](../../images/408/《计组》存储系统/组相联映射.png) * 计算过程 * $2^c$ * Cache总块数 * $2^q$ * Cache分组个数 * 分组个数 = 分块个数/组内块数 * $2^r$ * 组内包含的块数 * r=1,每组包含两块,叫二路组相联 * s = t +r * q=c-r #### 例题1 假设主存容量为512KB,Cache容量为4KB,每个字块为16个字,每个字为32位 (1)Cache地址为多少位,可容纳多少块 (2)主存地址为多少位,可容纳多少块 (3)在直接映射方式下,主存的第几块映射到Cache中的第五块(设起始字块号为1) (4)画出直接映射方式下主存地址字段中各段的位数 $(1) $ $默认按字节访问(8bit)$ $存储容量 = 存储单元个数\times存储字长 = 4KB = 2^{12}\cdot 8位$ $Cache有2^{12}个数据单元,即地址长度为12位,每个字块有16\times32位$ $Cache可容纳块数 = \frac{4KB}{16\times 32位} = \frac{2^{12} \cdot 8位}{2^6 \cdot 8位} = 64块$ $(2)$ $主存地址长度 = \log_2(\frac{512KB}{8位}) = 19位$ $可容纳块数 = \frac{512KB}{16\times32位} = \frac{2^{19}\cdot 8位}{2^6\cdot8位} = 2^(13) = 8192块$ $(3)$ $cache共64块$ 则主存块号%64 = 5 $\rightarrow 主存块号 = 5,64+5,64^2 \cdots 2^{13} - 64 +5$ $(4)$ 主存地址 |主存字块标记t|Cache字块地址c|字块内地址b| |---|---|---| |t=7|c=6|b=6| t = 主存地址长度 - Cache地址长度 = 19-12 = 7 Cache共有64块 = $2^6 \rightarrow$ c = 6 默认按字节访问 每个字 = $\frac{32}{8} = 4B$,每个字块有16$\times4$ = 64B = $2^6$B b = 6 #### 例题2 假设主存容量为512K*16位,Cache容量为4096 * 16位,块长为4个16位的字,访存地址为字 (1) 在直接映射下,设计主存的地址格式 (2)在全相联映射下,设计主存的地址格式 (3)在二路组相联映射方式下,设计主存的地址格式 (4)若主存容量为512KB*32位,块长不变,在四路组相联映射下,设计主存的地址格式 (1) 访存地址为字,每个字16位,块长为4个16位的字$\rightarrow$块长=4$\rightarrow$b=$\log_2$块长 = 2 主存地址长度 = $\log_2\frac{512K\times16位}{16位}$ = 19 Cache地址长度 = $\log_2\frac{4096\times16位}{16位}$ = 12 t = 19-12 = 7 Cache能分$\frac{4096\times 16位}{4\times 16位}$ = 1024块 c = $\log_2 1024$ = 10 主存地址 |主存字块标记t|Cache字块地址c|字块内地址b| |---|---|---| |t=7|c=10|b=2| (2) 由第一问知 b=2,m = 19-2 = 17 |主存字块标记|字块内地址b| |---|---| |m = 17|b=2| (3) 二路组映射方式可知 r = 1 b = 2,t=7,s=t+r=8.q=c-r=10-1=9 |主存字块标记|组地址|字块内地址| |---|---|---| |s=t+r=8|q = c-r =9|b=2| (4) 主存容量改写为1024K$\times$16位 主存地址长度 = $\log_2 1024 = 20位$ Cache长度没变,cache长度 = 12位 t = 20-12 = 8位,c没变 = 10 四路相联可知r=2 s = t+r = 8+2=10,q=c-r=10-2=8 主存地址 |主存字块标记|组地址|字块内地址| |---|---|---| |s=t+r=10|q = c-r =8|b=2| q可以认为是Cache分为1024块,每组是$2^r$ = 4块,就能分$\frac{1024}{4}$ = 256组 = $2^8$ 因此q = 8 ### 替换算法-解决满Cache情况下替换问题 * 随机算法 * 任何情况下直接覆盖想映射的Cache块 * 现实中不会以这种方式设计 * 先进先出FIFO * 按调入Cache的先后顺序来,先进的先替换 * 需要记录进入Cache的先后次序 * 实现起来比较简单 * 只考虑时间层面的问题,会吧一些经常使用的页当作最早进入cache的块给替换掉 * 近期最少使用LRU * 把最近比较少用的替换掉 * 需要记录进入cache的先后次序 * 也需要软件计数器来记录使用的频率 * 实现起来比较复杂且开销大 * 根据程序访问局部性原理选择近期使用最少的存储块作为替换的块 * 最不经常使用LFU * 只统计使用次数,优先替换使用最少的 * 通常也需要硬件设计计数器支持 例题 设Cache由8个块构成,CPU依次访问的主存地址块号为:4,6,12,4,8,14,22,6,4,11,5,2(二进制),求 (1)假设地址映射方式为全相联映射,在采用FIFO、LRU、LFU替换算法时,分别求Cache命中次数 * 有效位表示当前Cache块是否存在数据 * 标记位记录存入的数据是几 * 先入先出算法(FIFO) * 由于最先进入的是0号cache * 因此0号cache替换掉,标记位标记为2 * ![](../../images/408/《计组》存储系统/替换算法-FIFO.jpg) * 近期最少使用(LRU)算法 * 从后往前,先把前面使用过的划去 * 没有被划去的意味着用的比较少 * 然后从前往后看 * 看第一块没有被划去的就决定替换它 * ![](../../images/408/《计组》存储系统/替换算法-LRU.jpg) * 最不经常使用(LFU)算法 * 统计使用次数 * 4号块用了3次,6号块用了2次 * 其他几块均用了1次,需要更多判断依据 * 最终替换掉cache第2块(12号) ### 写入/更新策略 * 引入目的 * 保证CPU向内存中写入数据时Cache中和内存中的内容保持一致 #### Cache写命中 * 全写法/写直达法 * 在写的时候CPU将数据通过数据总线橙色箭头方向运输 * 由于CPU写给cache的速度和写入主存的速度会差很多 * 所以需要设计一个缓冲,先写入缓冲块中,再慢慢写入 * ![](../../images/408/《计组》存储系统/全写法写直达法.jpg) * 回写法 * 在CPU执行写操作时,先按橙色线写入cache存储体中 * 此时并没有修改主存的内容,会在cache中设计一个脏位 * 当一块中的任何一个单元被修改时,脏位(修改位)被置1 * 需要替换掉该块时,如果修改位为1,则必须先把这一块写回到主存中,然后才能再调入新的块 * 如果修改位为0,则这一块不必写回主存,只要用新调入的块覆盖这一块即可 * ![](../../images/408/《计组》存储系统/回写法.jpg) #### cache写没命中 * 写分配法 * 先将数据从内存中调入到cache中 * 再按回写法修改cache * ![](../../images/408/《计组》存储系统/写分配法.jpg) * 非写分配法 * 直接去内存修改 * ![](../../images/408/《计组》存储系统/非写分配法.jpg) ![](../../images/408/《计组》存储系统/四种方法的搭配.jpg)