存储器层次结构及高速缓存cache的思考

首先给出一个存储器的金字塔形结构图:

                                                  L0 寄存器 Regs.   (CPU在一个时钟周期内可以访问到)

                                               L1 高速缓存  SRAM   几个时钟cycles

                                               L2 高速缓存  SRAM   几十个到几百个cycles

                                             L3 高速缓存  SRAM     L1, L2,L3 三级 cache

                                       L4 主存 main memory.  主要是由 DRAM构成

                                     L5 本地的二级存储 主要是本地的磁盘, 可以看成成远程存储例如网络数据的一个本地缓存

                                  L6 远程二级存储 (分布式文件系统,Web服务器)

从上到下,CPU的访问速度依次降低,存储容量依次变大。

拿Intel  Core i7 的高速缓存层次结构做一个例子,假设有四个核, core0 ....core3,每个核有单独的Regs,L1 d-cache, L1 i-cache,一个L2统一的高速缓存,然后在处理器包中,四个核共享一个L3统一的高速缓存,这是所有核共享的。

如何编写cache友好的程序?考虑空间局部性和时间局部性两个准则,在对多维数组进行操作的时候,空间局部性要求循环以行首先,步长为1的引用模式会是cache友好的,因为多维数组的内存模型就是线性分布的,这样的话cache hit 会高。


介绍下 cache cold的概念:

在初始访问数据的时候,第K层对K+1层的缓存是空的,这时候任何K+1层数据的访问都不会命中,在反复放存储器使得 cache warmed up 之后,就恢复正常。

典型的cache结构 :

(S,E,B,m)表示有 S 个 cache set,就是组数, 而每组由E个高速缓存行 (cache line),每行的数据block 有 B字节大小。m表示的地址的位数。

关于cache抖动的概念:

针对每个组只有一行的cache,高速缓存反复加载和替换掉相同的cache line的现象,因为某些数据被隐射到了相同的cache line上,即缓存组的索引是相同,导致每次饮用数据块的时候,冲突不命中。还有一种情况, 一般一个cache line 会有32B或者是64B,如果有一个四个double类型的元素的数组,有四个线程分别修改对应的数组元素的值,那么每次引用这四个元素中的一个的时候,都可能会引起cache抖动, 因为4个元素一起被缓存到一个cache line中,每次一个线程修改其中一个元素,但其他线程引用其他元素的时候,其实引用的是相同的一个cache line,这时候这个cache line是被修改过的,换句话说这个数据块对应的页是脏的,那么就会引起页的回写(write-back),脏页回写之后,重新覆盖掉这个cache line,如此重复操作,不断引起页回写,高速缓存反复加载和替换掉相同的cache line, 那么性能随之下降,这个现象就叫做cache 抖动。


关于cache 读和写的操作:

读:首先在cache中查找所需字w的拷贝,如果cache hit,则立即返回字给CPU,若cache miss,则从低一层的存储器中读出包含字w的块,将这个块存储在某一个cache line中,可能会覆盖掉一个可能的行。

写:当在当前层的cache更新了w的copy之后,如何更新低一层的存储器的copy,1)write-through 2) write-back----->标记dirty 位




你可能感兴趣的:(cache,缓存,内存管理,linux内核)