Cache一致性协议

在说伪共享问题之前,有必要聊一聊什么是Cache一致性协议

局部性原理

时间局部性:如果一个信息项正在被访问,那么在近期它很可能还会被再次访问

比如循环、方法的反复调用等

空间局部性:如果一个存储器的位置被引用,那么将来他附近的位置也会被引用

比如顺序结构、数组

Cache的作用

CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU。为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存Cache,以解决访存速度和CPU运算速度之间不匹配的问题

带Cache的CPU访存过程

CPU和Cache交换数据以为单位。Cache与主存以为单位,一个缓存行(Cache Line)对应一个主存块

  • Cache命中,则直接从Cache中读取数据
  • Cache不命中,则访问主存,并将一个主存块调入Cache中,存入为一个缓存行。这个过程中可能由于Cache满而发生替换,替换算法包括RAND、FIFO、LRU、LFU

  • Cache命中时

    • 写回法(write back):CPU只将数据写入Cache,只有当数据调出Cache时,才写入主存
    • 写穿法(write through):CPU同时将数据写入Cache和主存
  • Cache不命中时
    • 写分配法:从主存中将数据块调入Cache,并修改Cache,和写回法配合使用
    • 非写分配法:只写入主存,不调入Cache,和写穿法配合使用

Cache和主存的映射方式(三种):直接映射、全相联映射、组相联映射

如果是单CPU结构,这么执行没有其他问题。但是现代系统往往包含多个CPU,每个CPU都有各自的Cache。多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致性,不让系统数据混乱。这里就引出了Cache一致性协议——MESI。注意,这并不是唯一的缓存一致性协议,还有其他协议如MOSEI(相对于MESI多引入了一个Owned状态,并重新定义了S状态),这里不多介绍

MESI协议详解

MESI(Modified Exclusive Shared Or Invalid),也称伊利诺斯协议,是一种广泛使用的、支持写回策略的缓存一致性协议。MESI协议其实就是使用4种状态来标记各个缓存行(Cache Line)的状态,而这些状态英文首字母缩写就构成了“MESI”

MESI协议中的各种状态

每个缓存行都使用一个状态来标记,该状态总共有4种,使用2bit进行存储:

  • M(Modified):相应的数据只被缓存在该CPU的Cache中,但数据是被修改过的(脏数据),即与主存中的数据不一致。该缓存行中的内存需要在未来的某个时间点,但必须是其它CPU读取主存中相应内存之前,将数据写回主存
  • E(Exclusive):相应的数据只被缓存在该CPU的缓存中,数据是未被修改过的,与主存中的数据一致
  • S(Shared):相应的数据被多个CPU缓存,且各个CPU的Cache中的数据和主存都是一致的
  • I(Invalid):该缓存行中的数据是无效的,因为有其他CPU修改了数据

总线嗅探机制(监听)

每个CPU都可以感知其他CPU的行为,比如读、写某个缓存行,这就是嗅探机制,也称监听。所有的缓存行(除了Invalid状态)都需要监听自己和其他CPU对相应的缓存行的读写操作,也称触发事件,从而根据触发事件和自身状态,进行状态的转换

各种触发事件

触发事件 描述
本地读取(Local Read) 本CPU读取本Cache的数据
本地写入(Local Write) 本CPU向本Cache写入数据
远端读取(Remote Read) 其他CPU读取它们各自Cache的数据
远端写入(Remote Write) 其他CPU向它们各自Cache写入数据

MESI中各个状态之间的转换

下图描述了当前缓存行在不同触发事件下的状态切换:

下表是对上图的一个详细解释:

举例

假设CPU0、CPU1、CPU2、CPU3中有一个缓存行(包含变量x)都是S状态

此时CPU1要对变量x进行写操作,这时候通过总线嗅探机制,CPU0、CPU2、CPU3中的缓存行会置为I状态(无效),然后给CPU1发响应,收到全部响应后CPU1会完成对变量x的写操作,并更新CPU1内的缓存行为M状态,但不会将数据x同步到主存中

接着CPU0想要对变量x执行读操作,却发现本地缓存行是I状态,就会触发CPU1去把缓存行写回到主存中,然后CPU0再去主存中同步最新的值

其他一些细节

1、写缓冲

前面的描述隐藏了一些细节,比如实际CPU1在执行写操作,更新缓存行的时候,其实并不会等待其他CPU的状态都置为I状态,才去做些操作,这是一个同步行为,效率很低。当前的CPU都引入了写缓存器技术,也就是在CPU和cache之间又加了一层buffer,在CPU执行写操作时直接向写缓冲写入数据,然后就忙其他事去了,等其他CPU都置为I之后,CPU1才把buffer中的数据写入到缓存行中

2、多级缓存

现代系统都会采用多级缓存架构,L1-L3级缓存,其中L3缓存是所有CPU共享的一个缓存,但MESI的描述中并没有涉及L3缓存。其实上文提到的所有跟“主存”交换数据的地方,在L3缓存存在的情况下,都应该替换为L3缓存。比如我上一节举的例子中,CPU0中某缓存行是I,CPU1 中是M。当CPU0想到执行local read操作时,就会触发CPU1中的缓存写入到主存中,然后CPU0从主存中取最新的缓存行。其实这里的描述是不准确的,因为由于L3缓存的存在,这里其实是直接从L3缓存读取缓存行,而不直接访问主存。个人认为是如果在描述MESI的状态流转时,如果引入L3缓存,会使得描述过于复杂,因此一般的描述都会刻意忽略L3缓存

**



作者:酒冽        出处:https://www.cnblogs.com/frankiedyz/p/15786362.html

版权:本文版权归作者和博客园共有

转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

**

伪共享

由于内存和Cache之间的交换单位是内存块/缓存行,因此如果访问一个变量,会将一整个内存块读入一个缓存行。但是如果多个线程访问的变量不相同,且这些变量在内存中的位置临近,那么很可能在同一个缓存行中。在Cache一致性协议(如MESI协议)的约束下,多个线程(CPU)在并行读写相对应的缓存行会有限制,因此其他线程不得不去访问低级别的Cache甚至是主存,这会导致cache没有起到真正的作用,程序性能下降

伪共享示例

如图,线程1访问变量x,而线程2访问变量y,而这两个变量在内存中的位置临近(在同一个内存块中),虽然线程都将该内存块读入到各自的工作内存(Cache)中,但是在Cache一致性协议的约束下,同一时间两个线程很难自由地读写相同位置的缓存行,那么可能就会让其中一个线程去低级别的内存中读写数据,性能因此降低,这就是伪共享

一般地址连续的多个变量更可能被放在同一个缓存行中,例如创建数组时,数组中的多个元素更可能被放入同一个缓存行中

如何避免伪共享问题

JDK8之前

JDK8之前,使用字节填充的方式,即创建一个变量时,使用填充字段填充该变量所在的缓存行,从而避免多个变量被放入同一个缓存行中,如下:

public final static class FilledLong {
public volatile long value = 0L;
public long p1, p2, p3, p4, p5, p6;
}

一般来说,缓存行为64 Byte,而经过填充的FilledLong对象有7*8 Byte=56 Byte,而FilledLong对象的对象头也有8 Byte,正好填满一个缓存行

JDK8及之后

JDK8提供了一个注解——sun.misc.Contended,用于解决伪共享问题,上述代码可以修改为如下:

@sun.misc.Contended
public final static class FilledLong {
public volatile long value = 0L;
}

Thread类中,也有这样的字段,如下:

@sun.misc.Contended("tlr")
long threadLocalRandomSeed; /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
@sun.misc.Contended("tlr")
int threadLocalRandomProbe; /** Secondary seed isolated from public ThreadLocalRandom sequence */
@sun.misc.Contended("tlr")
int threadLocalRandomSecondarySeed;

但是,@Contended注解只用于Java核心类,而用户类路径下的类使用该注解,需要添加JVM参数-XX:-RestrictContended。填充宽度默认为128 Byte,也可以自定义宽度,通过JVM参数-XX:ContendedPaddingWidth来设定

Cache一致性协议与伪共享问题的更多相关文章

  1. 《大话处理器》Cache一致性协议之MESI (转)

    原文链接:http://blog.csdn.net/muxiqingyang/article/details/6615199 Cache一致性协议之MESI 处理器上有一套完整的协议,来保证Cache ...

  2. Cache一致性协议之MESI

    http://blog.csdn.net/muxiqingyang/article/details/6615199 Cache一致性协议之MESI 处理器上有一套完整的协议,来保证Cache一致性.比 ...

  3. 《大话处理器》Cache一致性协议之MESI【转】

    转自:https://blog.csdn.net/muxiqingyang/article/details/6615199 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载 ...

  4. 简述伪共享和缓存一致性MESI

    什么是伪共享 计算机系统中为了解决主内存与CPU运行速度的差距,在CPU与主内存之间添加了一级或者多级高速缓冲存储器(Cache),这个Cache一般是集成到CPU内部的,所以也叫 CPU Cache ...

  5. Cache Line 伪共享发现与优化

    https://yq.aliyun.com/articles/465504 Cache Line 伪共享发现与优化 作者:吴一昊,杨勇 1. 关于本文 本文基于 Joe Mario 的一篇博客 改编而 ...

  6. C++性能榨汁机之伪共享

    C++性能榨汁机之伪共享 来源  http://irootlee.com/juicer_false_sharing/ 前言 在多核并发编程中,如果将互斥锁的争用比作“性能杀手”的话,那么伪共享则相当于 ...

  7. 3.3.1 Cache一致性的基本概念

    PCI设备对可Cache的存储器空间进行DMA读写的操作的过程较为复杂,有关Cache一致性的话题可以独立成书.而不同的处理器系统使用的Cache Memory的层次结构和访问机制有较大的差异,这部分 ...

  8. 线程基础:多任务处理——MESI协议以及带来的问题:伪共享

    1.概述 本文和后续文章将着眼CPU的工作原理阐述伪共享的解决方法和volatile关键字的应用. 2.复习CPU工作原理2.1.CPU工作原理要清楚理解本文后续内容,就需要首先重新概述一下JVM的内 ...

  9. cache line 伪共享

    https://blog.csdn.net/qq_27680317/article/details/78486220认识CPU Cache CPU Cache概述 随着CPU的频率不断提升,而内存的访 ...

随机推荐

  1. PostgreSql数据库安全加固

    1.确保通过"主机" TCP / IP套接字登录已正确配置 描述 大量的身份验证方法可用于使用 TCP / IP套接字,包括: ?信任 ? 拒绝 ?md5 ?scram-sha-2 ...

  2. 转:Sed使用

    awk于1977年出生,今年36岁本命年,sed比awk大2-3岁,awk就像林妹妹,sed就是宝玉哥哥了.所以 林妹妹跳了个Topless,他的哥哥sed坐不住了,也一定要出来抖一抖. sed全名叫 ...

  3. 2021 .NET 开发者峰会顺利在网上落幕,线上直播回看汇总

    .NET Conf China 2021 是面向开发人员的社区峰会,基于 .NET Conf 2021的活动,庆祝 .NET 6 的发布和回顾过去一年来 .NET 在中国的发展成果展示,它是由中国各地 ...

  4. 『与善仁』Appium基础 — 25、APP模拟手势高级操作

    目录 1.手指轻敲操作 2.手指按下和抬起操作 3.等待操作 4.手指长按操作 5.手指移动操作 6.综合练习 APP模拟手势的动作都被封装在TouchAction类中,TouchAction是App ...

  5. 联盛德 HLK-W806 (十一): 软件SPI和硬件SPI驱动ST7567液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  6. 针对HttpClient 重写 HttpRequestRetryHandler针对特定异常 增加重试

    调用方法: public static String doGet(String url) { try { RequestConfig defaultRequestConfig = RequestCon ...

  7. C# 将PDF转为线性化PDF

    线性化PDF文件是PDF文件的一种特殊格式,可以通过Internet更快地进行查看.线性化的PDF,在页面数量很多的情况下,更能突出表现出快速浏览的优势.下面是通过后端.NET程序实现将PDF文件转为 ...

  8. 【LeetCode】252. Meeting Rooms 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 排序 日期 题目地址:https://leetcode ...

  9. 【LeetCode】509. Fibonacci Number 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetc ...

  10. 【LeetCode】318. Maximum Product of Word Lengths 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 set 位运算 日期 题目地址:https://le ...