Cache的一般设计
Cache的设计来由
时间相关性:被访问的数据之后可能再次被访问
空间相关性:被访问的数据周围的数据可能被访问
不同层级Cache的设计考量
L1:(快)最靠近处理器,需要保持高速,因此容量不可能很大
L2:(全)指令和数据共享,允许稍慢,尽量降低Miss率
超标量处理器对Cache的特殊需求
I-Cache:支持每Cycle读多条指令
D-Cache:支持每Cycle多条Load/Store读写,需要多端口
Cache的术语
Data:一片连续的数据
Tag:这片连续数据的公共地址
Cache Line:一个Tag和对应的Data部分
Cache Set:同一个地址对应的多个Cache Line
Cache Miss的3C定理
Compulsory:首次访问造成的Miss,可以用prefetching来缓解
Capacity:容量限制造成的Miss,例如频繁使用的5个数据放在4个Cache Set
Conflict:多个数据映射到同一个Cache Set,可以用Victim Cache来缓解
Cache的组织方式(地址= {Tag, Index, Offset})
直接映射(1路组相连):Index直接寻址Cache Line,Tag比较的延迟低,但是Miss率高
n路组相连:Index寻址到n个Cache Line,同时比较n个Tag
全相连(MAX路组相连):不需要Index寻址,直接比较所有Tag,Miss低但延迟高
Cache的访问方式
并行:同时访问Tag RAM和Data RAM,节省1个Cycle
串行:先访问Tag RAM,根据比较结果访问Data RAM,节省功耗
Cache的写入
数据不一致:同一个地址在Cache和下级存储器对应不同的数据
Write Through:写Cache的同时也写下级存储器,保证一致性,很慢
Write Back:增加dirty位,只在Cache Line替换时写下级存储器
Write Non-Allocate:发生Miss时绕过Cache直接写下级存储器
Write Allocate:发生Miss时先从下级存储器读回对应的Data Block,将要写的数据合入再写入Cache,并将dirty位置1
Cache替换策略
LRU:每个Cache Line记录访问次数,优先替换较少被访问的Line
伪随机:由一个每Cycle递增的Counter决定哪个Line优先被替换,实现简单,节省资源
提高Cache的性能
Write Buffer
缓存需要被写回的dirty Line,节省Cache Line替换或Write Through的时间
读Miss时需要额外访问Write Buffer,增加硬件开销
流水线
写Cache需要先读Tag RAM、比较,然后才能决定是否写Data RAM,很难单拍完成
流水起来可以保证平均每Cycle都能执行Store指令
如果Store第二拍遇到了相同地址的Load指令,还可以进行数据转发
多级结构
容量和速度相互制约,为了看起来“又快又全”,引入多级Cache结构
L2 Cache一般使用Write Back;L1 Cache使用Write Through可以简化流水线,而且在多核环境下(L3 Cache共享)便于管理一致性
Inclusive:L2包括L1所有内容,重复存储,替换时允许直接覆盖L1 Cache Line,也方便查找某个地址的占用和修改情况(只需检查最低一级Cache)
Exclusive:L2和L1内容互斥,节省资源,替换时必须先将L1 Cache Line写回,多核情况下查找某个地址必须检查每一级Cache
Victim Cache
保存最近被踢出的Cache Line,缓解同一个Cache Set中的Conflict(Cache颠簸)
本质上增加了一个灵活的Cache Way,又避免了Cache整体扩大(帽子戴在需要的人头上)
Filter Cache:类似的思路,保存刚刚从下级存储器读回的Cache Line,如果被再次访问则写入Cache,否则被丢掉,这避免了偶然被访问的Line进入Cache
Prefetching(缓解Compulsory)
硬件预取:一般用于连续取指,为缓解分支预测失败的影响(Cache污染和带宽浪费),引入了Stream Buffer(保存下一个预取Block,预测失败则丢弃)和Strided Prefetching(硬件动态调整预取地址的递增大小)
软件预取:ISA需要支持预取指令,编译器分析程序进行针对性的预取
多端口Cache
真·多端口:控制和数据通路都翻倍,开销太大,一般不使用
Cache复制:消除对延迟的影响,浪费面积且不利于替换,很少使用
分成多个Bank:多个访问地址落在不同Bank没有任何问题,否则会发生Bank冲突,需要仲裁后多拍输出;为了判断多个端口是否命中,Tag RAM仍需要实现多端口
超标量处理器的取指令
连续取指可能受到非对齐地址的影响,无法保证性能
解决思路:冗余设计+缓存,例如2-way超标量使用能容纳4条指令的Cache Line大小,保证了每Cycle得到的平均指令数超过2,多余的指令缓存起来,如此就能稳定得到充足的指令
也可以将Cache Line折叠成2行,这样即便取指地址落在第1行的后半部分,也能一拍取出2条指令,当然需要做一次顺序调整
如果分支预测为真,分支指令之后的指令应当被放弃