多线程对共享变量的访问,是对cache 的访问
Cpu的执行指令的步骤
-
取指令
根据Pc 要执行的指令
-
译码 (decode )
将机器码翻译为机器操作
读取存储( read memory)
将结果写入寄存器(register)
Cpu 和 存储( Memory)概述
Cpu 要执行的指令 来自于存储
Cpu 指令要操作的数据 同样来自于存储
-
不同类型的存储
- Sram ( 静态ram,一般用作cache)
L1 cache :一级cache,一般和cpu 处于同一个芯片上
L2 cache :二级cache, 片外cache
Dram ( main memory, 主存)
Magnetic Disk ( 磁盘,外部存储)
CdRom ( 代指其他外部存储)
不同类型的存储速度递减
L1 cache > L2Cache > Dram > cdrom
-
Cpu 和存储的通信( 这里是说 总线架构的存储)
CPU需要读取数据的时候,直接和cache 通信,并不直接从主存中获取数据。 如果要从主存中直接获取数据,那么cpu 可能大部分时间要等待(主存速度相对cpu太慢了)。
当cpu 要读取内存中的数据的时候, 首先会从cache 中获取, 如果cache 没有命中(hit), 那么才会从内存中加载(内存中的数据也是先到cache ,然后cpu 从cache 中获取)。
Cache 要比主存快的多,如果可以将主存中数据都放在cache 中,cpu 等待的时间就更少了。然而cache 的高成本限制cache的大小。我们只能把少量的数据放在cache。要让cache 发挥最好的效果,必须 有靠谱的算法来提高cache 的命中率, 同时保证这些策略不会有太高的额外的负担( overhead ).
多处理器和总线(busbased)架构存储
这里我们把cache 理解为cpu 的一部分。 cpu 通过总线和存储进行通信。
多cpu 总线结构示意
我们假设在多个线程(相当于多个cpu 执行流程)中使用了共享变量V。由于CPU 之和Cache 数据的读写是基于cache, 也就是说CPU1, CPU2 都是使用本地cache 中V 变量的copy。
CPU1 变更了变量V,怎么才能让CPU2立刻知道V发生了变化, 以及什么时候更新CPU2 的cache, 还有CPU1,CPU2同时更新V,要怎么不相互影响。
Cache coherence
许多情况下翻译为缓存一致性。 描述了多处理器更新共享存储时的读写问题。 这里会介绍 cache coherence 问题的一种方案 : MESI protocol。
MESI
分别cache 块(cache line/ cache block) 的四种状态。M:Modifed, E:exclusive, S:shared,I:invalidate。
- M: cache 中的数据发生变量,但没有写入到主存
- E: 主存的数据在cache中只有一个备份( e.g. CPU1 中有,但是其他CPU 没有)
- S: 主存中的数据在多个CPU的cache 中有备份
- I: 当前Cache 中的备份无效( 不能用于cpu 计算)
总线广播(broadcast)
cpu 会将对数据的操作放在总线上, 广播给每个cpu。
总线侦听(sniff)
每个cpu 可以侦听到发送到总线上的消息。
MESI 中读写的原理
按照在读写中命中(hit) 和 不命中(miss) 的情况来展开。 为了便于说明,将cache 分为 myCache(当前cpu 的cache), ocache ( 其他cpu cache)
Read
-
Miss
- 没有在任何cache 中,
从主存中加载到cache, 同时将cache 标记为E - 在其他cache 中
cpu 将load 信息发送到总线,ocache 侦听到该消息- ocache (S ), ocache将自己的cache 信息发送到总线;mycache 侦听到总线上的消息,将cache 信息加载到自己的cache(不去加载主存), 同时mycache ->S
- ocache (E), ocache将自己的cache 信息发送到总线, 同时ocache 状态变为S; mycache 侦听到总线上的消息,将cache 信息加载到自己的cache(不去加载主存), 同时mycache ->S
- ocache (M) , ocache 将自己的cache 信息放到总线, 同时将自己的cache 写入主存, ocache -> S; mycache 获取到总线上的消息,同时mycache-> S
- 没有在任何cache 中,
-
Hit
- mycache(S), 不做操作
- mycache(E), 不做操作
- mycache(M),不做操作
Write
-
Miss
cache miss 的时候,cpu 会发送RWITM( read with intent for modify) 到总线, 从主存加载信息。- ocache 不存在 , mycache 从主存加载, 同时mycache ->M
- ocache(S) , ocache -> I, mycache 从内存加载, 同时mycache ->M
- ocache(E) , ocache -> I, mycache 从内存加载, 同时mycache ->M
- ocache(M) , mycache 操作被阻塞(block); ocache 写入主存,同时ocache -> I; mycache 从主存中加载,mycache ->M
-
Hit
- mycache(S), mycache -> M
- ocache (S) : ocache -> I
- mycache(E), mycache ->M
- mycache(M),不做操作
- mycache(S), mycache -> M