CPU多级缓存(总线锁/缓存行/MESI)
2021-02-25 23:26:48 4 举报
AI智能生成
CPU多级缓存(总线锁/缓存行/MESI)
作者其他创作
大纲/内容
喜欢收藏+点赞👍 谢谢
CPU架构
存储层次结构(金字塔)
寄存器 → L1缓存 → L2缓存 → L3缓存 → 主内存 → 本地磁盘 → 远程数据库
越往上访问速度越快、成本越高,空间更小。越往下访问速度越慢、成本越低,空间越大
多级缓存
为什么要设置多级缓存?
为了解决CPU运算速度与内存读写速度不匹配的矛盾
多级缓存的工作原理
在CPU和内存之间,引入了L1高速缓存、L2高速缓存、L3高速缓存每一级缓存中所存储的数据全部都是下一级缓存中的一部分
当CPU需要数据时,先从缓存中取,加快读写速度,提高CPU利用率
总线锁和缓存锁
总线锁
锁住总线,通过处理器发出lock指令,总线接受到指令后,阻塞其他处理器的请求,直到此处理器执行完成。这样该处理器就可以独占共享内存的使用
缺点:一旦某个处理器获取总线锁,其他处理器都只能阻塞等待,影响多核处理器的性能
缓存锁
不锁总线,只锁住被缓存共享的对象(缓存行)
缓存锁也不是万能,有些场景和情况依然必须通过总线锁才能完成
缓存行(cache line)
为了压榨CPU的性能,一次获取一整块的内存数据(64个字节)放入缓存
为什么是64字节?
与CPU架构有关,通常有32字节、64字节、128字节不等。目前64位架构下,64字节最为常用
设置的太小了,读取速度快,但命中率太低
设置的太大了,命中率很高,但读取速度慢
伪共享问题
多核多线程并发场景下,如果多核要操作的共享变量处于同一缓存行,某CPU更新该缓存行中的数据,会导致其他处理器缓存中的缓存行失效,每次用还要去主存重新加载
解决方案:字节填充
字节填充
long在java中占用8字节,在其前后额外填充7个long类型的变量将目标变量放入缓存行时,可以实现一个缓存行中只有目标变量
缓存一致性协议
当多个处理器都涉及同一块主内存区域的更改时,将导致各自的的缓存数据不一致,为了解决这个问题所以提出了缓存一致性协议,这类协议有 MSI、MESI、MOSI等,其中最常见的就是 Intel 的MESI 协议
MESI协议
MESI 协议是四种状态的缩写,用来修饰缓存行的状态(在每个缓存行前额外使用2bit,来表示这四种状态)
监听(嗅探)机制
M 已修改Modified
该缓存行的数据被修改了,和主存数据不一致
监听所有想要修改此缓存行对应的内存数据的操作,该操作必须等缓存行数据更新到主内存中,状态变成 S (Shared)共享状态之后执行
E 独占Exclusive
该缓存行和内存数据一致,数据只在本缓存中
监听所有读取此缓存行对应的内存数据的操作,如果发生这种操作,Cache Line 缓存状态从独占转为共享状态
S 共享Shared
该缓存行和内存数据一致,数据位于多个缓存中
监听其他缓存使该缓存行失效或者独享该缓存行的操作,如果检测到这种操作,将该缓存行变成无效
I 失效Invaild
该缓存行的数据无效
没有监听,处于失效状态的缓存行需要去主存读取数据
JMM
Java内存模型即Java Memory Model,用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各平台下都能够达到一致的内存访问效果
通俗来讲,每个线程都有自己的工作内存(本地内存),线程之间的共享变量存储在主内存,工作内存中存储了共享变量的副本,不同线程之间无法直接访问对方工作内存中的变量,线程间的通信均需要在主内存完成
再通俗点
工作内存 = 虚拟机栈
主内存 = 堆区 + 方法区
0 条评论
下一页