为什么需要cache?
..这里用一句话概括,CPU的数据处理速度,远远高于从内存中读取数据的速度,也就是说,如果CPU直接从内存中读取数据进行处理,CPU很长一段时间会用在等待数据读取完毕,这显示十分浪费CPU资源的。所以通过cache来缓存一部分数据,CPU读取数据时,先从cache里面找,从而提高数据处理的效率
为什么从cache里面读取就能提高cpu的数据处理效率?
..这是由于这个内存和cache本身的存储性能有关: 我们常说的内存指的是DRAM,SRAM的是目前最快的存储设备,但是它也非常昂贵,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓冲。
cache存在的合理性
从上面的知识,我们可以知道,从cache读取数据要比内存中读取块,但是cache终究只有很小一块存储空间,那凭什么通过这么一小块空间,就能大幅度提高数据读取的能力呢?
程序的局部性原理
#include <stdio.h>
int main(){
int i,j;
for(i=1;i<=9;i++){
for(j=1;j<=i;j++){
printf("%d*%d=%2d ",i,j,i*j);
}
printf("\n");
}
return 0;
}
..从上面程序可以看到,这个代码大数时间在执行一个乘法计算和调用一个 printf 函数,而程序一旦编译装载进内存中,它的地址就确定了。也就是说,CPU 大多数时间在访问相同或者与此相邻的地址,换句话说就是:CPU 大多数时间在执行相同的指令或者与此相邻的指令。这就是大名鼎鼎的程序局部性原理。 CPU 大多数时间在访问相同或者与此相邻的地址。那么,我们立马就可以想到用一块小而快的储存器,放在 CPU 和内存之间,就可以利用程序的局部性原理来缓解 CPU 和内存之间的性能瓶颈。这块小而快的储存器就是 Cache,即高速缓存。
什么是cache?
..Cache 中存放了内存中的一部分数据,CPU 在访问内存时要先访问 Cache,若 Cache 中有需要的数据就直接从 Cache 中取出,若没有则需要从内存中读取数据,并同时把这块数据放入 Cache 中。但是由于程序的局部性原理,在一段时间内,CPU 总是能从 Cache 中读取到自己想要的数据。 Cache 可以集成在 CPU 内部,也可以做成独立的芯片放在总线上,现在 x86 CPU 和 ARM CPU 都是集成在 CPU 内部的。其逻辑结构如下图所示。
Cache 主要由高速的静态储存器、地址转换模块和 Cache 行替换模块组成。
Cache 会把自己的高速静态储存器和内存分成大小相同的行,一行大小通常为 32 字节或者 64 字节。Cache 和内存交换数据的最小单位是一行,为方便管理,在 Cache 内部的高速储存器中,多个行又会形成一组。
除了正常的数据空间外,Cache 行中还有一些标志位,如脏位、回写位,访问位等,这些位会被 Cache 的替换模块所使用。
cache的工作流程
1.CPU 发出的地址由 Cache 的地址转换模块分成 3 段:组号,行号,行内偏移。
2.Cache 会根据组号、行号查找高速静态储存器中对应的行。如果找到即命中,用行内偏移读取并返回数据给 CPU,否则就分配一个新行并访问内存,把内存中对应的数据加载到 Cache 行并返回给 CPU。写入操作则比较直接,分为回写和直通写,回写是写入对应的 Cache 行就结束了,直通写则是在写入 Cache 行的同时写入内存。
3.如果没有新行了,就要进入行替换逻辑,即找出一个 Cache 行写回内存,腾出空间,替换行有相关的算法,替换算法是为了让替换的代价最小化。例如,找出一个没有修改的 Cache 行,这样就不用把它其中的数据回写到内存中了,还有找出存在时间最久远的那个 Cache 行,因为它大概率不会再访问了。
以上这些逻辑都由 Cache 硬件独立实现,软件不用做任何工作,对软件是透明的。
如何写出提高 Cache 命中率的代码?
1、遵从80-20法则,程序80%的时间在运行20%或更少的代码,针对热代码进行优化,才容易产出效果;
2、遵从数据访问的局部性法则,按数据存放顺序访问内存效率远高于乱序访问内存效率,也就是尽量帮助CPU做好数据Cache的预测工作。同样根据Cache大小,做好数据结构的优化工作,进行数据压缩或数据填充,也是提升Cache效率的好方式;
3、遵从指令访问的局部性法则,减少跳转指令,同样是尽量帮助CPU做好数据Cache的预测工作;现代CPU都有一些预测功能【如分支预测】,利用好CPU的这些功能,也会提升Cache命中率;
4、避免计算线程在多个核心之间漂移,避免缓存重复加载,可以绑定核心【物理核即可,不用到逻辑核】,提高效率;
5、去除伪共享缓存:在多核环境下,减少多个核心对同一区域内存的读写并发操作,减少内存失效的情况的发生;
6、合理提高进程优先级,减少进程间切换,可以变相提供Cache提速的效果 7、关闭Swap,可以变相提供内存提速、Cache提速的效果;
8、使用Intel自家的编译器,开启性能优化,很多时候可以提速运算效率;
9、使用C语言,而不是更高级的语言,很多时候可以提速运算效率;
10、直接使用昂贵的寄存器作为变量,可以变相提供加速效果;
结尾
cache会存在数据一致性的问题,由多进程,多CPU引起,具体可查看相关博客
|