局部性原理
空间局部性
在最近的未来要用到的信息(指令和数据),很可能与现在正在使用的信息在存储空间上是邻近的
时间局部性
在最近的未来要用到的信息,很可能是现在正在使用的信息
cache工作原理
即使设计了双端、多模块存储器,M和CPU的速度差距还是过大,故而引入cache
cache被集成在CPU内部中,cache用SRAM实现,速度快,成本高
基于局部性原理,不难想到,可以把CPU目前访问的地址“周围”的部分数据放到Cache中
性能:
命中率H:CPU欲访问的信息已在Cache中的比率
缺失(未命中)率M=1-H
Cache-主存系统的平均访问时间为
t=H*Tc+(1-H)*(Tc +Tm),cache未中访问主存
或者
H*Tc+(1-H)*Tm,cache和主存同时命中
将主存的 存储空间“分块”,如:每 1KB为一块。主存与Cache之间以“块”为单位进行数据交换
cache和主存的映射关系
全相联映射
主存块可以放在Cache的任意位置
根据cache块划分成块内地址和主存块号(标记)
访问的时候标记对比找到目标块
直接映射
每个主存块可放每个主存块只能放到一个特定的位置
Cache块号=主存块号%Cache总块数
缺点:其他地方有空闲Cache块,但是8号主存块不能使用
若Cache总块数=2^n
则主存块号末尾n位直接反映它在Cache中的位置
将主存块号的其余位作为标记即可
组相联映射
Cache块分为若干组,每个主存块可以存放在到特定分组中的任意一个位置
组号=主存块号%分组数
n路组相联映射:n块为一组,分为N/n组
cache替换算法(csapp无)
全相联映射:Cache完全满了才需要替换需要在全局选择替换哪一块
直接映射:如果对应位置非空,则毫无选择地替换
组相联映射:分组内满了才需要替换,需要在分组内选择替换哪一块
随机算法(RAND)
cache满了随机替换一块即可
先进先出算法(FIFO)
cache已满,则替换最先被调入的cache块
(先进先出算法)一实现简单,最开始按#0#1#2#3放入Cache,之后轮流替换#0#1#2#3
FIFO依然没考虑局部性原理,最先被调入Cache的块也有可能是被频繁访问的
近期最少使用(LRU)
为每一块cache块设置一个计数器,用于记录每个cache块,记录cache块多久没有被访问过了,每次替换计数最大的。
①命中时,所命中的行的计数器清零,比其低的计数器加1,其余不变;
②未命中且还有空闲行时,新装入的行的计数器置0,其余非空闲行全加1;
③未命中且无空闲行时,计数值最大的行的信息块被淘汰,新装行的块的计数器置0,其余全加1。tips:看这种题目有种比较快的方法,cache有n块,往前看n-1块,谁没出现替换谁
若被频繁访问的主存块数量>Cache行的数量,则有可能发生“抖动”
最近不经常使用(LFU)
为每一个cache块设置一个计数器,计数器最小的被替换
LFU算法--曾经被经常访问的主存块在未来不一定会用到(如:微信视频聊天相关的块)
并没有很好地遵循局部性原理,因此实际运行效果不如LRU
cache写策略
写命中
全写法
当CPU对cache命中时,必须把数据同时写入cache和主存,一般使用写缓冲(用队列一个个写到主存中)
使用写缓冲,CPU写的速度很快,若写操作不频繁,则效果很好。写操作很频繁,可能会因为写缓冲饱和而发生阻塞
写回法
当CPU对cache写命中时,只修改cache内容,而不立即写入主存,只有当此块被换出时,才写回
写不命中
写分配法
当CPU对cache写不命中时,把主存中的块调入cache,在cache中修改。通常搭配写回法
非写分配法
当CPU对cache写不命中的时候只写入主存,不调入cache,搭配全写法
多级cache
虚拟存储系统
页式存储器
思想
页式存储系统:一个程序(进程)在逻辑上被分为若干个大小相等的“页面”,“页面”大小与“块””的大小相同。每个页面可以离散地放入不同的主存块中。
逻辑地址(虚地址):程序员视角看到的地址
物理地址(实地址):实际在主存中的地址
页表
CPU执行的机器指令中,使用的是“逻辑地址”,因此需要通“页表”将逻辑地址转为物理地址
页表的作用:记录了每个逻辑页面存放在哪个主存块中
地址变换过程
切换页表基地址寄存器的内容相当于切换进程
因为页表也是在主存,所以快表(页表项的副本)存储近期使用过的页表
虚拟存储系统
页式虚拟存储器
段式虚拟存储器
段页式虚拟存储器
把程序按逻辑结构分段,每段再划分为固定大小的页
主存空间也划分为大小相等的页,
程序对主存的调入、调出仍以页为基本传送单位。
每个程序对应一个段表,每段对应一个页表。
虚拟地址:段号+段内页号+页内地址