美文网首页
写缓冲器 ,无效化队列 存储屏障 加载屏障 (gold_ax

写缓冲器 ,无效化队列 存储屏障 加载屏障 (gold_ax

作者: 胖达_4b7e | 来源:发表于2020-02-22 20:08 被阅读0次

为了结果MESI的性能弱点(要等其他cpu发来的回复), 有 写缓冲器 ,无效化队列

就是除了给cpu配高速缓存外, 还给它们每个 配一个 写缓冲器 和 无效队列

这么用

写缓冲器

写的时候,发现相应 缓存行的状态是S, 就是共享,说明其他cpu也有副本, 这时候要发 无效 的通知出去广播给其他cpu, 本来是要等回复才能继续的, 有写缓冲器 就可以先在写缓冲器放下就走了, cpu可以用本来等待的时间干点活, 省了
等回复都到了以后, cpu再来从写缓冲器搬运到缓存行
存储转发: 读的时候先从 写缓存器读, 因为它一般来说更新嘛, 没有 再去 高速缓存, 这样就可以还是读到真的数据了

无效化队列

收到无效通知以后, 并不把数据无效化, 而是存入无效化队列 就回复 收到无效Ack,
这样可以让对方早点收到回复

存储转发 导致可见性问题

cpu0 更新了a的值, 写到写缓冲器就往下走了,
过一阵,要读a, 这时先去写缓存器读, 读到的自以为是最新的,
但是没准这一阵时间里面, cpu1已经改过a的值了,
但是, cpu1过来的无效通知, 是管不到 cpu0的写缓冲器

写缓冲器 导致 StoreLoad重排序, 导致可见性问题

写缓冲造成的
比如 cpu0 执行

data=1
ready=true

cpu0的高速缓存里面ready是E/M的状态(本来就是以我为准),data是无效的状态
这样对写data的时候会写入写缓冲器,_先当写成了,再慢慢通知等其他cpu等他们回复知道了
写ready的时候 直接写高速缓存就行了, 因为其他cpu本来就知道自己不知道,不用通知

这样 其他cpu可能先看到对ready的写(因为会主动去问来), 再看到对data的写(要等失效的通知), 相当于重排序了

无效化队列 导致LoadLoad重排序 导致可见性问题

也是上面这个例子, 但是改成 cpu0 和cpu1 的高速缓存里面 data都是有效值, 就是状态为S,
cpu1里面ready是I的状态,本来就没有有效的ready
cpu0的都执行过了,cpu1收到data无效的信息, 但是它存了无效化队列没真的更新状态,就回复知道了,
然后,cpu1执行

if(ready){//我么有,需要去总线请求. 拿到真实值
  b=data+1
}

先读ready, 本来状态就是I 需要去总线问来, 这样肯定就能拿到最新值了, true
到这是对的,
然后读data, !!! data状态还是S没改, 无效化队列里面排队的还没生效!!!还以为已经失效的值是对的!

2个重排导致的后果是一样的, 但是原因不同, 一个是发送方没通知到, 一个是接受方收到了 没来得及改变状态

存储屏障 加载屏障 来解决

总之, 写缓冲器 ,无效化队列 就是导致了可见性问题, 明明写了 其他线程看不到
这就需要编译器等底层系统 借助 内存屏障

存储屏障 : 让cpu 将 写缓冲器排空,写入高速缓存 这叫冲刷, 这样其他cpu 就会收到通知, 其他cpu可以来拿新数据
加载屏障:cpu 根据无效化队列里面的信息,删除其高速缓存的无效数据(就是状态变为I)

这2个屏障的成对使用, 才能保证更新可见

相关文章

网友评论

      本文标题:写缓冲器 ,无效化队列 存储屏障 加载屏障 (gold_ax

      本文链接:https://www.haomeiwen.com/subject/tqfrqhtx.html