- 对于直接映射的块交换还无法形成完整的逻辑自洽
- 如何求的块内地址、标记、cache行号
- 如何根据主存地址去寻找
寄存器和Cache
就集成在CPU中了
内存墙:CPU的速度比内存(受限于电容)的速度快得多
解决:CPU和内存之间增加Cache
工作
工作原理
工作流程
- 如何判断是命中还是未命中?
- 如果未命中,为什么不直接把所需要的字从内存传送到CPU?
- 时间局部性
- 如果未命中,为什么从内存中读入一个块而不只读入一个字?
- 空间局部性
- 使用
Cache
后需要更多的操作,为什么还可以节省时间? -
命中VS未命中
通过这种映射关系判断有无命中
程序访问的局部性原理
- 把块给
Cache
,把字给处理器 - 两种方式时间开销上无较大差异
- 系统总线代表主存,主存速度很慢,而
CPU
会一直申请数据,所以需要缓冲器
因为会重复访问特定的数据
- 字在某一个块中,传递块而不是字
- 通过标记,判断字所在的块命中了,则字命中了=>所以块是预先划分好的
- 方便访问相邻数据
平均访问时间
Tc
:做的是检查Ta = 检查时间+访问主存的时间(1-p 需要访问)
- 降低
Tm
很难,受到电容的限制 - 命中率高要求cache大,而这会使访问cache时间变大
Cache未命中原因
- 容量失效:原8kb的数据块访问后被后面的8kb的数据覆盖。如果再要访问到该8kb的数据,因为已经被替换了,则会失败,导致失效
- 冲突失效:
Cache的设计要素
- 容量:太大-命中率低;太低:容量失效
- 映射功能:冲突失效
- 替换算法:用一个更小的区域放一个更大的区域,有更高概率被访问的数据留下来
- 写策略
- Cache行大小(主存的块大小)
- Cache数目
容量
涉及到的空间局部性和所需的数据更大,则容量设置的更大
映射功能
直接映射
使用地址的高2位就可以指向具体的行
**M是128/8=16,C=4 所以n=2:**
16个块,有4行,所以一行中有4个块,所以需要2位标记CPU
寻找主存,通过主存地址进行寻找
一个块包含很多字,一个块对应的是cache
中的一行。
所以要通过块内地址找到块中具体的字在哪里。
- 什么是每行包含8个字:一个块包含了八个字,需要用3位二进制进行。这里的字可以理解为一个数据单元。
- 主存中包含128个字:所以主存地址为7位
- 主存和缓存是按块进行存储的
- 块的大小是相同的
命中了的话再根据子块内地址找到对应的字
- 因为只有16行,所以只需要1位表示就行(前提是16进制)
Cache
中本身不记录行号和块号,是逻辑上产生
总结
- 行数变多:数据之间的关联性降低,因此冲突失效概率降低
- 电路简单:增大容量,但是映射关系仍然保持一致,所以检查时间变化不大
- 降低检查时间
Tc
,增加命中率,这两者直接存在矛盾。
全相联映射
一个主存块可以装入Cache
任意一行,所以不需要记录行号了
总结
代价:
- 需要知道哪一行是空的
- 要访问每一行,所以容量增大的话,则
Tc
显著增加
对于小容量,不适合直接映射
组关联映射
将书柜分区:中文区、日文区、英文区
总结
比较
K和容量、命中率、检查时间的变化
替换算法
可以通过软件进行模拟,例如解决缓存问题。但本身是通过硬件实现
再次访问的概率相较于其他行更低?
最近最少使用算法 LRU?
非此即彼:0/1代表的是访问时间的近远
先进先出算法
仍然存储抖动现象
最不经常使用算法 LFU
随机替换算法
假设的情况和真正情况的符合度较高。所有能够进入Cache
的数据,本身都是“万里挑一的”
写策略
缓存命中时的写策略
写直达
写回法
缓存未命中时的写策略
写不分配:对安全要求较高的
写分配:程序中隐含较多时间和空间的局部性
行大小
不是违反了时间关系,而是违反了时间局部性:重复访问存储在相同位置的信息,那么每一次找都要找很久
反空间局部性:**重复
Cache数目
冯诺依曼:指令和数据不区分。根据阶段进行区分
对与Cache
,数据很快会把Cache填满,而指令也会频繁使用-都受到局部性的支配,所以需要消除竞争关系,避免冲突失效