CPU Cache 机制以及 Cache miss

CPU体系结构之cache小结html

1.What is cache?程序员

Cache是用来对内存数据的缓存。
CPU要访问的数据在Cache中有缓存,称为“命中” (Hit),反之则称为“缺失” (Miss)。
CPU访问它的速度介于寄存器与内存之间(数量级的差异)。实现Cache的花费介于寄存器与内存之间。
如今 CPU 的 Cache 又被细分了几层,常见的有 L1 Cache, L2 Cache, L3 Cache,其读写延迟依次增长,实现的成本依次下降。
现代系统采用从 Register ―> L1 Cache ―> L2 Cache ―> L3 Cache ―> Memory ―> Mass storage的层次结构,是为解决性能与价格矛盾所采用的折中设计。
下图描述的就是CPU、Cache、内存、以及DMA之间的关系。程序的指令部分和数据部分通常分别存放在两片不一样的cache中,对应指令缓存(I-Cache)和数据缓存(D-Cache)。
 
引入 Cache 的理论基础是程序局部性原理,包括时间局部性和空间局部性。即最近被CPU访问的数据,短时间内CPU 还要访问(时间);被 CPU 访问的数据附近的数据,CPU 短时间内还要访问(空间)。所以若是将刚刚访问过的数据缓存在Cache中,那下次访问时,能够直接从Cache中取,其速度能够获得数量级的提升。



CPU缓存(Cache Memory)位于CPU与内存之间的临时存储器,它的容量比内存小但交换速度快。在缓存中的数据是内存中的一小部分,但这一小部分是短期内CPU即将访问的,当CPU调用大量数据时,就可避开内存直接从缓存中调用,从而加快读取速度。

在CPU中加入缓存是一种高效的解决方案,这样整个内存储器(缓存+内存)就变成了既有缓存的高速度,又有内存的大容量的存储系统了。缓存对CPU的性能影响很大,主要是由于CPU的数据交换顺序和CPU与缓存间的带宽引发的。

下图是一个典型的存储器层次结构,咱们能够看到一共使用了三级缓存
算法

2. Why should I care about cache?


从延迟上看,作一次乘法通常只要三个周期,而作一次CPU的内存访问须要167个cycle,若是须要提高程序性能,减小CPU的memory访问相当重要。所以,须要采用容量小可是更快的存储器(cache)。shell

3.为何要有多级CPU Cache

随着科技发展,热点数据的体积愈来愈大,单纯的增长一级缓存大小的性价比已经很低了
二级缓存就是一级缓存的缓冲器:一级缓存制形成本很高所以它的容量有限,二级缓存的做用就是存储那些CPU处理时须要用到、一级缓存又没法存储的数据。
一样道理,三级缓存和内存能够看做是二级缓存的缓冲器,它们的容量递增,但单位制形成本却递减。
另外须要注意的是,L3 Cache和L1,L2 Cache有着本质的区别。,L1和L2 Cache都是每一个CPU core独立拥有一个,而L3 Cache是几个Cores共享的,能够认为是一个更小可是更快的内存。

使用dmidecode命令查看cache size
后端

4.cpu与cache 内存交互的过程

CPU接收到指令后,它会最早向CPU中的一级缓存(L1 Cache)去寻找相关的数据,然一级缓存是与CPU同频运行的,可是因为容量较小,因此不可能每次都命中。这时CPU会继续向下一级的二级缓存(L2 Cache)寻找,一样的道理,当所须要的数据在二级缓存中也没有的话,会继续转向L3 Cache、内存(主存)和硬盘.

程序运行时可使用perf工具观察cache-miss的rate.数组


5.什么是cache line

Cache Line能够简单的理解为CPU Cache中的最小缓存单位。
内存和高速缓存之间或高速缓存之间的数据移动不是以单个字节或甚至word完成的。
相反,移动的最小数据单位称为缓存行,有时称为缓存块
目前主流的CPU Cache的Cache Line大小都是64Bytes。假设咱们有一个512字节的一级缓存,那么按照64B的缓存单位大小来算,这个一级缓存所能存放的缓存个数就是512/64 = 8个。
查看cache line大小
cat /sys/devices/system/cpu/cpu1/cache/index0/coherency_line_size
cache line的影响:缓存

for (int i = 0; i < N; i+=k)
    arr[i] *= 3;



注意当步长在1到16范围内,循环运行时间几乎不变。但从16开始,每次步长加倍,运行时间减半。
因为16个整型数占用64字节(一个缓存行),for循环步长在1到16之间一定接触到相同数目的缓存行:即数组中全部的缓存行。当步长为32,咱们只有大约每两个缓存行接触一次,当步长为64,只有每四个接触一次。ide

6. cache写机制

Cache写机制分为write through和write back两种。

Write-through- Write is done synchronously both to the cache and to the backing store.
Write-back (or Write-behind) - Writing is done only to the cache. A modified cache block is written back to the store, just before it is replaced.

Write-through(直写模式)在数据更新时,同时写入缓存Cache和后端存储。此模式的优势是操做简单;缺点是由于数据修改须要同时写入存储,数据写入速度较慢。

Write-back(回写模式)在数据更新时只写入缓存Cache。只在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储。此模式的优势是数据写入速度快,由于不须要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的状况,数据将没法找回。函数

7.cache 一致性

多个处理器对某个内存块同时读写,会引发冲突的问题,这也被称为Cache一致性问题。
Cache一致性问题出现的缘由是在一个多处理器系统中,多个处理器核心都可以独立地执行计算机指令,从而有可能同时对某个内存块进行读写操做,而且因为咱们以前提到的回写和直写的Cache策略,致使一个内存块同时可能有多个备份,有的已经写回到内存中,有的在不一样的处理器核心的一级、二级Cache中。因为Cache缓存的缘由,咱们不知道数据写入的时序性,于是也不知道哪一个备份是最新的。还有另一个一种可能,假设有两个线程A和B共享一个变量,当线程A处理完一个数据以后,经过这个变量通知线程B,而后线程B对这个数据接着进行处理,若是两个线程运行在不一样的处理器核心上,那么运行线程B的处理器就会不停地检查这个变量,而这个变量存储在本地的Cache中,所以就会发现这个值总也不会发生变化。

为了正确性,一旦一个核心更新了内存中的内容,硬件就必需要保证其余的核心可以读到更新后的数据。目前大多数硬件采用的策略或协议是MESI或基于MESI的变种:
M表明更改(modified),表示缓存中的数据已经更改,在将来的某个时刻将会写入内存;
E表明排除(exclusive),表示缓存的数据只被当前的核心所缓存;
S表明共享(shared),表示缓存的数据还被其余核心缓存;
I表明无效(invalid),表示缓存中的数据已经失效,即其余核心更改了数据。
8.cache的局部性

程序在一段时间内访问的数据一般具备局部性,好比对一维数组来讲,访问了地址x上的元素,那么之后访问地址x+一、x+2上元素的可能性就比较高;如今访问的数据,在不久以后再次被访问的可能性也比较高。局部性分为“时间局部性”和“空间局部性”,时间局部性是指当前被访问的数据随后有可能访问到;空间局部性是指当前访问地址附近的地址可能随后被访问。处理器经过在内存和核心之间增长缓存以利用局部性加强程序性能,这样能够用远低于缓存的价格换取接近缓存的速度。

时间局部性:
代码1:

工具

for (loop=0; loop<10; loop++) {
    for (i=0; i<N; i++) {
        ... = ... x[i] ...
    }
}


代码2:

for (i=0; i<N; i++) {
    for (loop=0; loop<10; loop++) {
        ... = ... x[i] ...
    }
}


代码二的性能优于代码1,x的元素如今被重复使用,所以更有可能留在缓存中。 这个
从新排列的代码在使用x[i]时显示更好的时间局部性。

空间局部性:
一个矩阵乘法的例子:
代码1:

for i=1..n
    for j=1..n
        for k=1..n
            c[i,j] += a[i,k]*b[k,j]


代码2:

for i=1..n
    for k=1..n
        for j=1..n
            c[i,j] += a[i,k]*b[k,j]



代码2的性能优于代码一的性能。
二者实现上的差别:

代码2的b[k,j]是按行访问的,因此存在良好的空间局部性,cache line被充分利用。
代码1中,b [k,j]由列访问。 因为行的存储矩阵,所以对于每一个缓存行加载,只有一个元素用于遍历。


9.cache替换策略

Cache工做原理要求它尽可能保存最新数据,当从主存向Cache传送一个新块,而Cache中可用位置已被占满时,就会产生Cache替换的问题。
经常使用的替换算法有下面三种。
(1) LFU
LFU(Least Frequently Used,最不常用)算法将一段时间内被访问次数最少的那个块替换出去。每块设置一个计数器,从0开始计数,每访问一次,被访块的计数器就增1。当须要替换时,将计数值最小的块换出,同时将全部块的计数器都清零。
这种算法将计数周期限定在对这些特定块两次替换之间的间隔时间内,不能严格反映近期访问状况,新调入的块很容易被替换出去。
(2)LRU
LRU(Least Recently Used,近期最少使用)算法是把CPU近期最少使用的块替换出去。这种替换方法须要随时记录Cache中各块的使用状况,以便肯定哪一个块是近期最少使用的块。每块也设置一个计数器,Cache每命中一次,命中块计数器清零,其余各块计数器增1。当须要替换时,将计数值最大的块换出。
LRU算法相对合理,但实现起来比较复杂,系统开销较大。这种算法保护了刚调入Cache的新数据块,具备较高的命中率。LRU算法不能确定调出去的块近期不会再被使用,因此这种替换算法不能算做最合理、最优秀的算法。可是研究代表,采用这种算法可以使Cache的命中率达到90%左右。
(3) 随机替换
最简单的替换算法是随机替换。随机替换算法彻底无论Cache的状况,简单地根据一个随机数选择一块替换出去。随机替换算法在硬件上容易实现,且速度也比前两种算法快。缺点则是下降了命中率和Cache工做效率。

10.cache的映射
主存与cache的地址映射方式有全相联方式、直接方式和组相联方式三种。
直接映射
将一个主存块存储到惟一的一个Cache行。

1) 多对一的映射关系,但一个主存块只能拷贝到cache的一个特定行位置上去。
cache的行号i和主存的块号j有以下函数关系:i=j mod m(m为cache中的总行数)

优势:硬件简单,容易实现
缺点:命中率低, Cache的存储空间利用率低

2) 全相联映射
能够将一个主存块存储到任意一个Cache行。
主存的一个块直接拷贝到cache中的任意一行上

优势:命中率较高,Cache的存储空间利用率高
缺点:线路复杂,成本高,速度低

组相联映射
能够将一个主存块存储到惟一的一个Cache组中任意一个行。
将cache分红u组,每组v行,主存块存放到哪一个组是固定的,至于存到该组哪一行是灵活的,即有以下函数关系:cache总行数m=u×v 组号q=j mod u

组间采用直接映射,组内为全相联
硬件较简单,速度较快,命中率较高

Cache Miss

1.不要指望编译器对你作任何优化

2.Cache(广义内存)系统表明性的包括三种级别:
1)第一级cache (L1)位于CPU芯片上而且运算于CPU工做频率;
2)第二级cache(L2)也位于芯片上比L1速度慢而体积大;
3)第三级cache(L3)位于CPU外部,是速度最慢、体积最大的存储器。

3.当运算器须要从存储器中提取数据时,它首先在最高级的cache中寻找而后在次高级的cache中寻找。若是在cache中找到,则称为命中hit;反之,则称为不命中miss

4.cache misses的种类:

(1)cold misses:不可避免。若Kcache空,则必发生cache miss,空的cache称为cold cache,这种cache misses称为compulsory misses或者cold misses。当cache已被warmed up则通常不会再发生cold misses

(2)conflict misses:多个K+1级的blocks被映射到K级中同一个block。这一点关系到对于程序员而言可否写出cache友好代码。

(3)程序常会分阶段执行(例如循环:内层、外层),每一个阶段会取cache blocks的固定几个块,这几个块所构成的集合称为working set。 当working set超过cache大小时所发生的miss称为capacity misses

5.从cache指令上作优化:简化调用关系,减小冗余代码(即不是必须存在的的代码),减少代码量,减小没必要要的调用;

6.从数据cache上作优化:即减小cache miss的次数,方法有很多,http://blog.chinaunix.net/uid-7319742-id-2059720.html 这篇文章有介绍

 

推荐连接:

http://bi.dataguru.cn/thread-163962-1-1.html

http://blog.chinaunix.net/uid-7319742-id-2059720.html

http://blog.csdn.net/wangjiaoyu250/article/details/9212863

http://coolshell.cn/articles/10249.html

https://blog.csdn.net/yhb1047818384/article/details/79604976

相关文章
相关标签/搜索