前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CPU高速缓存与内存屏障

CPU高速缓存与内存屏障

作者头像
keithl
发布2020-03-10 15:19:36
1.7K0
发布2020-03-10 15:19:36
举报
文章被收录于专栏:疾风先生疾风先生
1. CPU高速缓存

cpu高速缓存的由来

  • 在CPU的全部取指令周期中(程序计算),至少需要访问一次存储器(也就是我们所说物理内存上的数据)
  • 通常需要多次访问存储器的取操作数或者保存结果,CPU处理计算的速度明显受限于访问存储器的限制
  • 因此解决方案就是利用局部性原理,在CPU与物理内存之间提供一个容量小并且速度快的存储器,称为高速缓存

高速缓存概述

  • 缓存是分“段”(line)的,一个段对应一块存储空间,大小是 32(较早的 ARM、90 年代 /2000 年代早期的 x86 和 PowerPC)、64(较新的 ARM 和 x86)或 128(较新的 Power ISA 机器)字节
  • 高速缓存包含物理内存部分数据副本
  • cpu读取数据时将会先检查高速缓存中的数据是否存在,存在就返回,不存在就读取物理内存数据

高速缓存和内存

高速缓存分为L1-L3 Cache

  • L1 Cache: 一级缓存是CPU第一层高速缓存,分为指令缓存和数据缓存,一般服务器的CPU的L1缓存容量在32-4096kb,现在的L1 Cache都不能直接与内存直连传输数据
  • L2 Cache: 由于L1级别高速缓存容量的限制,为了再次提高CPU的运算速度,在CPU外部放置一个高速存储器,即二级缓存
  • L3 Cache: 现在的L3缓存都是内置的,主要是进一步降低内存延迟,提升处理器运算能力,一般是多核共享一个L3缓存

CPU系统架构

2. 缓存一致性与MESI协议

单CPU缓存的读与写操作

  • 缓存读操作
    • CPU读取数据时,先在L1中寻找,再从L2中寻找,再从L3中寻找,然后是内存,最后是外存储器(持久化介质)
    • 如果只处理读取操作,那么不论是L1-L3的缓存,都将会和主内存的数据保持一致
  • 缓存写操作
    • 缓存直写:直接透过本级缓存,直接将数据写入到下一级缓存或主内存中,写入成功/失败后将对应的缓存内容也执行更新/丢弃操作,这样缓存中的数据与将与主内存数据一致
    • 缓存回写:将修改本级缓存并记录标志段,通过标志段将数据回写到下一级缓存或主内存中,如果标志段被丢弃也将会先进行一次回收,也保证所有级别的缓存数据保持一致

缓存的一致性协议

  • 多核缓存的写操作问题
    • 场景: 在一个多核且每核都有对应的缓存的处理器进行读写操作
    • 假设有一个CPU缓存了主内存上的某一段数据,在另一个CPU上需要对该内存段的数据进行写操作,此时在写数据的CPU更新了缓存而其他CPU并没有更新到缓存,这时候便会产生缓存数据的不一致性

缓存一致性约定

代码语言:javascript
复制
如何解决上述的问题,出现缓存数据不一致的原因如下:
  • 多核CPU都有对应的高速缓存,每核缓存的数据都无法共享
  • 这时候我们会想到就是让缓存能够为多核CPU共享,但出现的问题就是处理器运算能力性能会下降,每次都需要等待其中一个CPU进行写操作之后才能够进行下一步的处理
  • 那么我们的期望就是使用多核缓存,同时也能够让它们运作变得像操作一组缓存一样,那么缓存的一致性协议就是为了这一点而设计解决问题的

缓存的MESI协议

代码语言:javascript
复制
缓存的一致性协议有很多种,比较典型的就是MESI协议,关于MESI协议简述如下:
  • 失效(Invalid)缓存段: 缓存不存在或者已经失效过时
  • 共享(Shared)缓存段: 数据有效,并与主内存以及其他Cache的数据保持一致,用于读缓存操作
  • 独占(Exclusive)缓存段: 数据有效,与主内存的数据保持一致,与S的区别就是在于该处理器处于独占的状态时,其他的cpu缓存将会失效
  • 已修改(Modified)缓存段,属于脏段,表示当前的cpu缓存已经修改过,但是还没有同步到主内存中,为当前的cpu所专有
  • 小结:也就是cpu控制缓存的读写操作,还需要监听其他cpu发生的通知,保证缓存最终数据的一致性,其中E状态解决了修改缓存数据之前告诉其他处理器的问题

cpu数据读写流程

3. 内存屏障

CPU优化手段:运行时指令重排序

  • 为什么会出现指令重排序
代码语言:javascript
复制
当CPU写缓存时发现区块正被其他CPU占用,为了提高CPU处理性能,可能将后面的读缓存命令优先执行
  • 指令重排原则
代码语言:javascript
复制
重排需要遵循as-if-serial语义规则,即不管怎么进行重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变.编译器/runtime/处理器都必须遵循as-if-serial语义,也就是说编译器和处理器不会对存在数据依赖关系的操作做重排序

CPU高速缓存存在的问题

  • 缓存中的数据与主内存的数据并不是实时同步的,各CPU(或CPU核心)间缓存的数据也不是实时同步的,也就是在同一个时间点,各CPU所看到同一个内存地址的数据的值可能是不一致的
  • 指令重排序存在问题,虽然遵循as-if-serial语义,但是仅仅能保证是在单核CPU下单线程自己执行的情况下保证结果是正确的,如果是多核多线程,指令逻辑无法分辨因果关联,可能会出现乱序,导致程序运行结果出现错误

内存屏障

  • 定义
代码语言:javascript
复制
是一类同步屏障指令,它使得CPU或编译器在对内存进行操作的时候,严格按照一定的顺序来执行, 也就是说在memory barrier之前的指令和memory barrier之后的指令不会由于系统优化等原因而导致乱序
  • 内存屏障指令
    • 写内存屏障,在指令后插入Store Barrier,能让写入缓存中最新的数据更新写入主内存,让其他线程可见.强制写入主内存,这种显示调用,CPU就不会因为性能考虑而去对指令重排
    • 读内存屏障,在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新主内存中加载数据读取主内存内容,让CPU缓存与主内存保持一致,避免缓存导致的一致性问题
    • 完全内存屏障,保障了早于屏障的内存读写操作的结果提交到内存之后,再执行晚于屏障的读写操作
  • 作用
    • 就是解决上述CPU高速缓存存在的问题

最后,关于写作内存相关的原因是为了更好地理解同步关键字synchronized的内存语义(下一篇哈)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 疾风先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. CPU高速缓存
  • 2. 缓存一致性与MESI协议
  • 3. 内存屏障
相关产品与服务
云硬盘
云硬盘(Cloud Block Storage,CBS)为您提供用于 CVM 的持久性数据块级存储服务。云硬盘中的数据自动地在可用区内以多副本冗余方式存储,避免数据的单点故障风险,提供高达99.9999999%的数据可靠性。同时提供多种类型及规格,满足稳定低延迟的存储性能要求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档