目录结构
一、CPU缓存基础知识
二、缓存命中
三、缓存的一致性
四、典型用例
五、队列伪共享
前言导读
基本上cpu缓存知识是进入大厂的一个基本知识点了,而且也相当看重,这部分的知识掌握的比较好的话,会很加分的!
说下历史:
在计算的前几十年中,主内存非常慢且昂贵得令人难以置信,但是CPU也不是特别快。从1980年代开始,差距开始迅速扩大。微处理器的时钟速度飞速发展,但是内存访问时间的改善远没有那么明显。随着这种差距的扩大,越来越明显的是需要一种新型的快速存储器来弥合这种差距。
今天分享的是缓存一致性和缓存命中
缓存一致性
部分来自维基百科:
为了和下级存储(如内存)保持数据一致性,就必须把数据更新适时传播下去。这种传播通过回写来完成。一般有两种回写策略:写回(Write back)和写通(Write through)。
根据回写策略和上面提到的未命中的分配策略,请看下表
通过上图,我们知道:
写回时:如果缓存命中,不用更新内存,为的就是减少内存写操作,通常分配策略是分配
-
怎么标记缓存在被其他cpu加载时被更新过?每个Cache line提供了一个脏位(dirty bit)来标识被加载后是否发生过更新。(cpu在加载时是一块一块加载的不是一个字节一个字节加载的,前面说过)
-
写通:
-
写通是指,每当缓存接收到写数据指令,都直接将数据写回到内存。如果此数据地址也在缓存中,则必须同时更新缓存。由于这种设计会引发造成大量写内存操作,有必要设置一个缓冲来减少硬件冲突。这个缓冲称作写缓冲器(Write buffer),通常不超过4个缓存块大小。不过,出于同样的目的,写缓冲器也可以用于写回型缓存。
-
写通较写回易于实现,并且能更简单地维持数据一致性。
-
通常分配策略是非分配
对于一个两级缓存系统,一级缓存可能会使用写通来简化实现,而二级缓存使用写回确保数据一致性
MESI协议:
这里有一个网页这个地址太6x了,参考了很多资料,还是不如动画嗄。。。。www.scss.tcd.ie/Jeremy.Jone…
建议先玩一玩上面网址的动图,可以了解下,各个cpu的缓存和主存的读、写数据。
这里简单阐述一下:我们主存有个x=0的值,处理器有两个cpu0,cpu1
-
cpu0读x的值,cpu0先在cpu0缓存找,找不到,有一个地址总线,就是路由cpu的和主存,同时去cpu和主存找,比较版本,去主存拿x,拿到x的值通过数据总线将值赋值cpu0的缓存
-
-
cpu0对x+1写,直接获取cpu0的x=0,进行加1(这里不会更新主存,也不会更新cpu1的缓存,cpu1缓存还没有x的值)
-
-
cpu1读x的值,首先在cpu1的缓存中找,找不到,根据地址总线,同时去cpu和主存找,比较版本(如果版本一样,会优先去主存的值),找到cpu0的x值,cpu0通过数据总线将数据优先更新cpu1的缓存x的值,在更新主存x的值
-
-
cpu1对x+1,直接获取cpu1的x=1,进行加1(这里会更新主存,也不会更新cpu0的缓存,但是会通过RFO通知其他cpu
-
其他情况可以自己去试一下。
通知协议:
Snoopy 协议。这种协议更像是一种数据通知的总线型的技术。CPU Cache通过这个协议可以识别其它Cache上的数据状态。如果有数据共享的话,可以通过广播机制将共享数据的状态通知给其它CPU Cache。这个协议要求每个CPU Cache 都可以“窥探”数据事件的通知并做出相应的反应。
MESI协议的状态:
Modified(已修改), Exclusive(独占的),Shared(共享的),Invalid(无效的)。
跟着动画走一遍,其实也不是很复杂。
了解这个对理解java中的volatile关键字其实是有帮助的!!
接下来的一篇文件就是典型用例啦!
真心感谢帅逼靓女们能看到这里,如果这个文章写得还不错,觉得有点东西的话
求点赞👍 求关注❤️ 求分享👥 对8块腹肌的我来说真的 非常有用!!!
如果本篇博客有任何错误,请批评指教,不胜感激 !❤️❤️❤️❤️