主存块和cache块关系_高速缓存Cache

程序局部性原理

程序访问的局部性原理包括时间局部性和空间局部性。

  • 时间局部性:在最近的未来要用到的信息,很可能是现在正在使用的信息。

    ——程序中存在大量循环。

  • 空间局部性:在最近的未来要用到的信息,很可能与现在正在使用的信息存储在邻近空间。

    ——指令通常是顺序存放、顺序执行的,数据一般也是以向量、数组等形式簇聚在一起存储。

高速缓存技术就是利用程序的局部性访问原理,大大提高了程序的运行速度。

程序局部性原理的应用

2345ca5092ed8f3ff159febef259a2cf.png

假定数组元素按行优先方式存储,对于上面A,B两个程序:

(1)对于数组a的访问,哪个空间局部性更好?哪个时间局部性更好?

(2)对于指令的访问来说,for循环的空间局部性和时间局部性?

假定M、N都为2048,按字节编址,每个数组元素占4B,则指令和数据在主存的存放情况如上图右部分。

(1)对于数组a,程序A和程序B的空间局部性相差较大。

程序A对数组a的访问顺序为a[0][0],a[0][1],.......,a[0][2047];a[1][0],a[1][1],...,a[1][2047];....。由此可见,访问顺序与存放顺序是一致的,因此空间局部性好。

程序B对数组a的访问顺序为a[0][0],a[1][0],...,a[2047][0];a[0][1],a[1][1],....,a[2047][1];...。由此可见,访问顺序与存放顺序不一致,每次访问都要跳过2048个数组元素,即2048*4B=8192B,若主存与Cache的交换单位小于8KB,则每访问一个数组元素都需要装入一个主存块到Cache中,因而没有空间局部性。

两个程序的时间局部性都差,因为每个数组都只被访问一次!!!

(2)对于for循环体,程序A和程序B中的访问局部性是一样的。因为循环体内指令按序连续存放,所以空间局部性好;内循环体被连续重复执行2048*2048次,因此时间局部性也好。

由上述分析可知,虽然程序A和程序B的功能相同,但因内、外两重循环的顺序不同而导致两者对数组a访问的空间局部性相差较大,从而带来执行时间的不同。

for(i=0;i<=9;i++){  temp=1;  for(j=0;j<=i;j++)temp*=a[j];  sum+=temp;}//访问顺序a[0],a[0],a[1],a[0],a[1],a[2]...所以既有空间局部性又有时间局部性。

注:指令Cache和数据Cache是分离的!这种结构也称哈佛Cache,特点是允许CPU在同一个Cache存储周期内同时提取指令和数据,由于指令执行过程取指令和取数据都有可能访问Cache,因此这一特性可以保证不同的指令同时访存。

主要是为了避免资源冲突,在五级指令流水线中,分为IF(取址),ID(译码),EXE(执行),MEM(访存),WB(写回)。当然也不一定是五级,现在处理器流水线的长度都在15级左右。但是IF和MEM这两步总是有的。其中IF和MEM都会访问cache。但是IF访问cache是取指令,MEM访问内存是取数据。当前指令的MEM和后面指令IF同时在流水线上执行,会产生同时访问cache的冲突(资源冲突),但是将指令cache和数据cache分开就能满足两者的同时访问了。就不会因为冲突,造成流水线暂停了,提高了流水线运行效率。

Cache命中率

750c3b08205be438ea99bdcdf7437694.png

Cache命中率和Cache行大小的关系

行的长度较大,可以充分利用程序访问的空间局部性,使一个较大的局部空间被一起调到Cache中,因而可以增加命中机会。但是,行长也不能太大,主要原因有:

1)行长大使得失效损失变大。也就是说,若未命中,则需要花更多时间从主存读块。

2)行长太大,Cache项数变少,因而命中的可能性变小。

如何提高Cache命中率

1.尽量绑定线程到一个CPU上

 这样就避免了数据缓存在多个cpu cache中。

2.频繁更新和不频繁更新的数据分开存放,读数据和写数据分开

实际操作具有一定的难度。

3.数据的分布尽可能的按照访问顺序定义

实际操作具有一定的难度。

4.减少使用全局变量,增强数据访问的局部性

Cache和主存的映射方式

Cache行结构

每个Cache行由标记项和数据项构成。其中数据项就是内存块的副本。大小和内存块相等。

Cache标记项包括:有效位、标记位Tag、一致性维护位、替换算法控制位。

注意:在组相联中,将每组的标记项排成一行,将各组从上到下排成一个二维的标记项阵列(直接映射一行就是一组)。查找Cache时就是查找标记阵列的标记项是否符合要求。例如,下图为二路组相联的标记阵列。

注:标记项阵列(组相联)或标记项组(直接映射)也叫地址映射表。

badc0138a8917d4147bac1f6a93f8fa6.png

在考题中一般标记项只计算1位有效位和标记位(即一般不考虑一致维护和替换算法位),其中标记位是可变的,需要通过计算得到,所以是考查重点。

注:

①全相联映射方式:标记位 = 主存块号

②直接映射方式的:“标记位 + Cache行号 = 主存块号”

③组相联映射方式:“标记位 + 组号 = 主存块号”

三种映射方式特点比较

映射方式优点缺点
全相联映射Cache存储空间利用充分,命中率高查找标记速度最慢,有可能对比所有行的标记,且标记占的额外空间最多
直接映射对于任意一个地址,只需要对比一次标记位,速度最快,且标记所占的额外空间开销最少Cache存储空间利用不充分,命中率低
组相联映射两种方式的折中,综合效果好——

一、全相联映射方式——没有限制(全部联合)

1.原理

主存中的每一块可以装入到Cache中的任意位置。

2.访存地址结构

主存块大小 = 行大小 = 64B

e8b6aff3b9ca1c68953d26c4c9971725.png

3.CPU访问过程

①用主存地址的前22位主存块号与Cache中所有块的标记位对比。

②若匹配,且有效位=1,则Cache命中,再根据块内地址访问对应块中的相应存储单元。

③若未命中或有效位=0,则正常访问主存。

二、直接映射方式——都有限制(全部斗争)

1.原理

主存中的每一块只能装入Cache中的特定位置。若这个位置已有内容,则产生块冲突,原来的块将无条件被替换出去(无须使用替换算法)。

直接映射实现简单,但不够灵活,即使Cache的其他许多地址空着也不能占用,块冲突概率最高,空间利用率最低。

映射关系:Cache行号 = 主存块号%Cache总块数

注:当Cache总块数是2^k时,主存块号的末尾k位即为Cache行号!!

主存块号可以被分为标记部分和行号部分

2.访存地址结构

主存块大小 = 行大小 = 64B

3427dcd16ea3359d4ea3ad0cd2c524da.png

3.CPU访存过程

①根据主存块号的后3位确定Cache行。

②对比主存块号的前19位和Cache的标记位,若匹配,且有效位=1,则Cache命中,再根据块内地址访问对应块中的相应存储单元。

③若未命中或有效位=0,则正常访问主存。

三、组相联映射方式——外部限制,内部无限制(既联合又斗争)

组相联路数的选择:

路数越大,每组Cache行的数量越多,发生冲突的概率越低,但相联比较电路也越复杂(比较标记次数越多)。选择适当的数量,达到折中效果。

1.原理

将Cache空间分成大小相同的组,主存的一个数据块可以装入一组内的任何一个位置,即组间采取直接映射,组内采取全相联映射。

映射关系:所属分组号 = 主存块号%分组数

同理,如果分组数=2^k,则主存块号的末尾k位为所属分组号!

2.访存地址结构

主存块大小 = 行大小 = 64B

4a6f0d29a56ebb019821d6c19a420fba.png

3.CPU访问过程

①根据主存块号的后2位确定所属分组号。

②对比主存块号的前20位和分组内的每个Cache行的标记位,若匹配,且有效位=1,则Cache命中,再根据块内地址访问对应块中的相应存储单元。

(注意每行的标记位都是不一样的,不存在每组共有标记位的说法,标记位是指出存的是哪个块的副本)

③若未命中或有效位=0,则正常访问主存。

Cache替换算法

注:对于直接映射方式,由于每个内存块只能对应调入到Cache中的固定位置,所以就不存在选则Cache块,也不会有替换算法。

对于全相联映射:Cache全满了才替换

对于组相联映射:一组满了就要替换!!

1、随机算法(RAND)

随机确定替换的Cache块。实现简单,但未依据程序访问的局部性原理,命中率较低。

2、先进先出算法(FIFO)

选择最早调入的行进行替换。实现简单,但也未依据程序访问的局部性原理。最早进入的主存块也可能是目前经常使用的。

3、最近最久未用算法(LRU)——考查重点

LRU算法对每个Cache行设置一个计数器(LRU位),用计数值来记录主存块的使用情况,根据计数值选择淘汰某个块。

30d7ebdf550aa9325a9e96f5a9623042.png

注:LRU位的位数与Cache组大小有关!!n路组相联有log2n位LRU位!!

计数器的变化规则:

①命中时,所命中的行的计数器清零,比其低的计数器加1,其余不变。

②未命中且还有空闲行时,新装入的行的计数器置为0,其余全加1。

③未命中且无空闲行时,计数值最大的行的信息块被淘汰,新装行的计数器置为0,其余全加1。

注意:为什么不是所有计数器都加1,首先,计数器值只是为了比较大小,其余全加1就不能保证计数器值与Cache组大小相匹配,也不会有LRU位的位数=log2n。

4、最不经常使用算法(LFU)

同样为每个Cache块设置一个“计数器”,不过是记录每个Cache块被访问过几次。

LFU的计数器值会很大,曾经被经常访问的主存块在未来不一定会用到,并没有遵循局部性原理,Cache命中率也不高。

6a8b1b2b05707af8317478baf35cc655.png

Cache写回策略

由于Cache中的内容是主存块副本,当对Cache中的内容进行更新时,就要选择写操作策略使Cache内容和主存内容保持一致。由于只有写操作才会导致Cache和主存中的内容不一致的问题,因此只讨论写操作,此时分两种情况。

Cache写命中——CPU要写的存储单元(所在的块)正好在Cache中有副本

1、写回法(回写法,回写方式,write-back)

当CPU对Cache写命中时,只修改Cache中的内容,而不立即写入主存,只有当这个Cache块被换出时才写回主存。

这种方法减少了访存次数,但存在不一致的隐患(主存中的数据和Cache中的数据不一致)。采用这种策略时,每个Cache行必须设置一个标志位(脏位),以反映此块是否被CPU修改过。——1表示修改过

2、全写法(写直通法,直写方式,write-through)

当CPU对Cache写命中时,必须把数据同时写入Cache和主存。当某一块需要替换时,不必把这一块写回主存,用新调入的块直接覆盖即可。

这种方法实现简单,能随时保持主存数据的正确性。缺点是增加了CPU访存次数,降低了Cache的效率。

为减少全写法直接写入主存的时间损耗,在Cache和主存之间加一个写缓冲(Write Buffer),CPU将数据同时写入Cache和写缓冲而不是Cache和主存,再由写缓冲将内容写回主存,CPU可以做其他事情。

写缓冲是一个FIFP队列,写缓冲可以解决速度不匹配问题。但若出现频繁写时,会使写缓冲饱和溢出。

Cache写不命中——CPU要写的存储单元在只在主存中,不在Cache中

1、写分配法(write-allocate)

把主存中的块加载到Cache中,然后更新这个Cache块。

注:主存中的内容不动,修改的是调入到Cache中的副本,因此该方法通常搭配写回法使用。

此法试图利用程序的空间局部性,但缺点是每次不命中都需要从主存中读取一块。

2、非写分配法(not-write-allocate)

只写入主存,不进行调块。一般搭配全写法

注:也就是说,采用这种方法,只有在读操作未命中时才调入Cache!!

a27f1e6bf79db31fa9a29c79b58f3dbc.png

现代计算机的Cache通常设立多级Cache(一般为3级)

各级Cache之间常采用“全写法+非写分配法”

Cache与主存之间常采用“写回法+写分配法”

  • 13
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值