CPU多级缓存

CPU多级缓存

  1. L1 Cache 是CPU第一级缓存,分为数据缓存和指令缓存.以帮服务器CPU的L1缓存的容量通常在21-4906KB.
  2. L2 Cache 由于L1级高速缓存容量限制,为了再次提高CPU的运算速度在CPU外部放置已高速存储器,即二级缓存。
  3. L3 Cache 现在都是内置的,而他可以进一步降低内存延迟,同时提高大数据量计算的处理器性能(其作用是进一步降低内存的延迟,同时提升海量数据量计算时的性能)。具有加大L3缓存的处理器提供更有效的文件系统缓存行为,即较短消息队列长度。一般是多核共享一个L3级缓存。

CPU读取数据顺序: L1–>L2–>L3–>内存–>外部存储器

缓存同步协议(MESI协议)

MESI协议它规定每条缓存都有个状态为,同时定义了下面的四个状态

  1. **修改态(modified)**该条数据是在CPU的缓存中,并且是被修改过的,与主内存里面的数据不一致,这条数据是要在某个的时间点回写到主内存当中,这个时间点是允许其他CPU读取主内相应的内存之前,当值被回写到主内存后缓存状态被修改为E.

  2. **专有态(Exclusive)**该条数据是没有被修改过的,内容同于主内存,但不出现在其他Cache中,这条数据可以在任何时刻,其他CPU读取后状态修改为S,当CPU修改内容后状态就会变为M.

  3. **共享态(shared)**这条数据内容同于主内存当也出现在其他CPU中(也就是可以被多个CPU进行缓存),当有一个CPU修改缓存时,其他CPU从该缓存行是可以被作废的,状态就会变为I.

  4. **无效态(invalid)**这个缓存是无效的,可能是其他CPU修改了该缓存。

  5. 多处理器时,单个CPU对缓存中的数据进行了改动,需要通知给其他CPU,也就意味着CPU处理要控制自己的读写操作,还要监听其他CPU发出的通知,从而保证最终一致。

指令重排

场景
指令重排
当CPU写缓存时发现缓存区块正被其他CPU占用,为了提高CPU的处理性能,可能讲后面的读缓存命令优先执行。
as-if-serial
不管CPU怎么重排序,程序(单线程)的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial,也就是说编译器和处理器不会在数据依赖关系操作重排序。

同样CPU在执行过程中会面临两个问题:
1. 高速缓存下,缓存中的数据于主数据并不是实时同步的,各CPU(或CPU核心)间缓存的数据也不是实时同步。在同一个时间点各个CPU看到的同一内存地址的数据可能不一致。
2. CPU执行指令重排序优化时,虽然遵守as-if-serial语义,但只能保证在单CPU自己执行的情况下保证结果正确。多核线程中,指令逻辑无法分辨因果关联。可能出现乱序,导致运行结果错误。
内存屏障
处理器提供了两个指令(Memory Barrier)用于解决上述问题

  1. 读内存屏障(Load Memory Barrier) 在指令执行前插入Load Memory Barrier 可以让高速缓存中的数据失效强制从主内存加载数据,强制读取主内存内容让CPU缓存与主内存保持一致,避免了缓存导致一致性的问题。
  2. 写内存屏障(Store Memory Barrier)在指令后插入store barrier,能让缓存中最新的数据写入到主内存中,让其他线程可见。强制写入主内存,这种显示调用,CPU就不会因为性能考虑,而去对指令重拍。