Cache

171 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

Cache基本原理、基本概念

Cache工作原理 image.png image.png 局部性原理 image.png 空间局部性:在最近的未来要用到的信息(指令和数据),很可能与现在正在使用的信息在存储空间上是邻近的 (数组元素、顺序执行的指令代码) 时间局部性:在最近的未来要用到的信息,很可能是现在正在使用的信息 (循环结构的指令代码)

基于局部性原理,不难想到,可以把CPU目前访问的地址“周围”的部分数据放到Cache中 程序B按“列优先”访问二维数组,空间局部性更差 性能分析 image.png image.png image.png image.png 如何区分Cache与主存的数据块对应关系? Cache和主存的映射方式 Cache很小,主存很大。如果Cache满了怎么办? 替换算法 CPU修改了Cache中的数据副本,如何确保主存中数据母本的一致性? Cache写策略

Cache和主存的映射方式

全相联映射 image.png 主存块可以放在Cache的任意位置 (b)直接映射 image.png 每个主存块只能放到一个特定的位置 Cache块号=主存块号% Cache总块数 (c)组相联映射 image.png Cache块分为若干组,每个主存块可放到特定分组中的任意一个位置 组号=主存块号%分组数

全相联映射(随意放)

假设某个计算机的主存地址空间大小为256MB,按字节编 址,其数据Cache有8个Cache行,行长为64B。 Cache行:即Cache块,与主存块的大小相等 image.png image.png 实现映射 image.png image.png

直接映射(只能放固定位置)

假设某个计算机的主存地址空间大小为256MB,按字节编 址,其数据Cache有8个Cache行,行长为64B。 直接映射,主存块在Cache中的位置=主存块号%Cache总块数 image.png image.png image.png image.png image.png image.png

组相联映射(可放到特定分组)

假设某个计算机的主存地址空间大小为256MB,按字节编 址,其数据Cache有8个Cache行,行长为64B。 image.png 组相联映射,所属分组=主存块号%分组数 image.png image.png image.png image.png image.png

Cache替换算法

随机算法(RAND)

随机算法(RAND,Random)――若Cache已满,则随机选择一块替换。 设总共有4个cache块,初始整个Cache为空。采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5} image.png

随机算法――实现简单,但完全没考虑局部性原理,命中率低,实际效果很不稳定

先进先出算法(FIFO)

先进先出算法(FIFO,First In First Out)—-若Cache已满,则替换最先被调入Cache的块 设总共有4个Cache块,初始整个Cache为空。采用全相联映射,依次访问主存块 {1,2,3,4,1,2,5,1,2,3,4, 5} image.png 先进先出算法――实现简单,最开始按#O#1#2#3放入Cache,之后轮流替换#O#1#2#3 FIFO依然没考虑局部性原理,最先被调入Cache的块也有可能是被频繁访问的 抖动现象:频繁的换入换出现象(刚被替换的块很快又被调入)

近期最少使用算法(LRU)

近期最少使用算法(LRU, Least RecentlyUsed )--为每一个Cache块设置一个“计数器”,用于记录每个Cache块已经有多久没被访问了。当Cache满后替换“计数器”最大的 设总共有4个Cache块,初始整个Cache为空。采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5} ①命中时,所命中的行的计数器清零,比其低的计数器加1,其余不变; ②未命中且还有空闲行时,新装入的行的计数器置0,其余非空闲行全加1; ③未命中且无空闲行时,计数值最大的行的信息块被淘汰,新装行的块的计数器置0,其余全加1。

image.png image.png image.png image.png image.png LRU算法――基于“局部性原理”,近期被访问过的主存块,在不久的将来也很有可能被再次访问,因此淘汰最久没被访问过的块是合理的。LRU算法的实际运行效果优秀,Cache命中率高。 若被频繁访问的主存块数量>Cache行的数量,则有可能发生“抖动”,如:1,2,3,4,5,1,2,3,4,5,1,...]

最不经常使用算法(LFU)

最不经常使用算法(LFU, Least Frequently Used )—-为每一个Cache块设置一个“计数器”,用于记录每个cache块被访问过几次。当Cache满后替换“计数器”最小的 设总共有4个Cache块,初始整个Cache为空。采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5} 新调入的块计数器=O,之后每被访问一次计数器+1。需要替换时,选择计数器最小的一行 image.png image.png image.png LFU算法―一曾经被经常访问的主存块在未来不一定会用到(如:微信视频聊天相关的块),并没有很好地遵循局部性原理,因此实际运行效果不如LRU

Cache写策略

写命中

写回法(write-back)——当CPU对Cache写命中时,只修改Cache的内容,而不立即写入主存,只有当此块被换出时才写回主存 减少了访存次数,但存在数据不一致的隐患。 image.png

全写法(写直通法,write-through)——当CPU对Cache写命中时,必须把数据同时写入cache和主存,一般使用写缓冲(write buffer) 访存次数增加,速度变慢,但更能保证数据一致性 image.png 使用写缓冲,CPU写的速度很快,若写操作不频繁,则效果很好。若写操作很频繁,可能会因为写缓冲饱和而发生阻塞 image.png

写不命中

写分配法(write-allocate)——当CPU对Cache写不命中时,把主存中的块调入Cache,在Cache中修改。通常搭配写回法使用。 写回法(write-back)——当CPU对Cache写命中时,只修改Cache的内容,而不立即写入主存,只有当此块被换出时才写回主存 image.png

只有“读”未命中时才调入Cache 非写分配法(not-write-allocate)——当CPU对Cache写不命中时只写入主存,不调入Cache。搭配全写法使用。 全写法(写直通法,write-through)——当CPU对Cache写命中时,必须把数据同时写入Cache和主存,一般使用写缓冲(write buffer) image.png

多级Cache

image.png现代计算机常采用多级Cache 离CPU越近的速度越快,容量越小 离CPU越远的速度越慢,容量越大