1.多级cache
2.Cache line
Cache是由cache Line组成 它是 CPU 从内存读取数据的基本单位,而cache Line 是由各种标志(Tag)+ 数据块(Data Block)组成;但是怎么写呢?
写直达:如果命中,直接将数据写到cache和主存;如果没命中,直接写到主存
还有写回:写到Cache line,标记为脏;当修改过的 Cache line被替换(替换算法决定时机)时,才需要写到内存中
3.一致性问题
如果按照写回方法:
当a=0;被核心1写a+1;此时a=1还放在cache line中,在这个cache line还没被替换时,主存中a还是=0;此时,核心2正好从主存中读取了a,把a放到了核心2的cache line;结果两个核心的cache里的a不一致,产生了一致性问题;为解决这个问题,引出了“写传播”和“事务串行化”
3.1 总线嗅探
当核心1里面修改了cache某个数据时,通过总线广播给其他核心,每个核心也会监听广播的事件,如果自己的cache也有相同的数据,则会更新到自己的L1 cache;这种方式只保证了写传播,没保证事务串行化,于是有了mesi:基于总线嗅探实现事务串行化
3.2 mesi协议
用四种状态来标记cache line的状态M:已修改;E:独占;S:共享;I:失效;用状态机来减少广播和实现串行化
4. Dma跟cache一致性
dma外设到内存:需要将数据对应的cache line设为i,cpu再使用数据就重新从内存拿
dma内存到外设:如果cache line为m,需要将cache的数据同步到内存
5. 屏障指令
Mesi虽然保证了cache一致性,但是没有解决执行乱序的问题,因为执行乱序是一定存在的,在不能的乱序的地方需要使用屏障指令(保证指令跟数据按照程序逻辑执行)避免它,比如互斥锁里面就用到了屏障指令
a=0;a=1,flag=1;//核心1执行,flag先于a=1执行
if(flag==1) b=a+1;//核心2执行,b的结果跟程序的逻辑就不一致了
单核:有依赖点,结果不会出错
多核:flag先命中cache,先执行,结果就会出错