背景知识
现在的CPU基本是多核的,而且CPU 运算速度远比主存(内存)读写速度快,并且速度相差了几个数量级。所以CPU 大部分时间都在等数据从主存读取,运算完数据写回内存。
所以现代计算机在CPU和主存之间加了一层读写速度尽可能接近CPU运算速率的高速缓存来做缓冲。而且CPU还有内置的寄存器存放一些计算结果。
如果cpu每次需要的数据都不在缓存中,那么还不是要去主存中读取,放入缓存,岂不是多此一举?
由于长期的实验显示:程序 80% 的时间在执行 20% 的代码,所以只要把这 20% 的数据和代码放入缓存中,系统性能将会大大提升。
而且CPU访问主存时存在两个局部性现象:
-
时间局部性现象
如果一个主存数据正在被访问,那么近期它再被访问的可能性也很大。
-
空间局部性现象
如果某块主存数据被访问了,这块内存区域邻近的数据也很有可能会被访问到。例如数组。
局部性原理对编程的影响
- 反复引用同一个变量具有良好的时间局部性
- 对于步长为 k 的引用模式的程序,步长越短,空间局部性越好,例如操作数组。
- 对于取指令来说。循环有好的时间和空间局部性。循环体越小。循环次数越多,局部性越好。
缓存一致性问题
多核cpu且有各自的高速缓存,这就会出现缓存数据不一致的问题,两个核心的线程都读取了主存中的同一个共享变量,并且都对其进行了操作,比如都读取了一个整型数据i = 0,两个线程都对其 i++,写回主存中,主存中 i 的值变为了 1,但是这是错误的,因为执行了两次++操作,i 应该为2。
如何解决缓存一致性问题?
早期的做法是锁住总线,因为所有cpu都是通过总线向内存中读取数据,当一个cpu访问主存中的共享变量时,其他cpu都无法访问,这样就不会有数据不一致的现象了,但是这样对cpu性能损耗非常大。
**缓存一致性协议:**缓存一致性协议有很多种,用的最多的是 MESI协议
( Modified 修改状态、Exclusive 独占状态、Sh