`
noble510520
  • 浏览: 56248 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

内存屏障保证缓存一致性

阅读更多

 在前面内存系统重排序提到,“写缓存没有及时刷新到内存,导致不同处理器缓存的值不一样”,出现这种情况是糟糕的,所幸处理器遵循缓存一致性协议能够保证足够的可见性又不过多的损失性能。

 缓存一致性协议给缓存行(通常为64字节)定义了个状态:独占(exclusive)、共享(share)、修改(modified)、失效(invalid),用来描述该缓存行是否被多处理器共享、是否修改。所以缓存一致性协议也称MESI协议

  • 独占(exclusive):仅当前处理器拥有该缓存行,并且没有修改过,是最新的值。
  • 共享(share):有多个处理器拥有该缓存行,每个处理器都没有修改过缓存,是最新的值。
  • 修改(modified):缓存行被修改过了,需要写回主存,并通知其他拥有者 “该缓存已失效”。
  • 失效(invalid):缓存行被其他处理器修改过,该值不是最新的值,需要读取主存上最新的值。

优化

 处理修改状态是比较耗时的操作,既要发送失效消息给其他拥有者并写回主存,还要等待其他拥有者处理失效信息,直到收到失效消息的响应。如果在这一段时间,处理器都处于空等,那是奢侈的。所以引入缓存失效缓存来让处理器不再“等”。

存储缓存

 存储缓存(Store Buffers),也就是常说的写缓存,当处理器修改缓存时,把新值放到存储缓存中,处理器就可以去干别的事了,把剩下的事交给存储缓存。

失效队列

 处理失效的缓存也不是简单的,需要读取主存。并且存储缓存也不是无限大的,那么当存储缓存满的时候,处理器还是要等待失效响应的。为了解决上面两个问题,引进了失效队列(invalidate queue0)。

 处理失效的工作如下:

  1. 收到失效消息时,放到失效队列中去。
  2. 为了不让处理器久等失效响应,收到失效消息需要马上回复失效响应。
  3. 为了不频繁阻塞处理器,不会马上读主存以及设置缓存为invlid,合适的时候再一块处理失效队列。

引发内存重排序

 下面是处理器A、B,依次写、读内存a的时序图。A、B都缓存了a。

 可以看到即使遵守缓存一致性协议,也会有一段时间缓存不一致(①-⑥)。

 要是读取a的操作在这段时间内,那么处理器B看到的a将是0。处理器执行顺序为写a>读a,而在内存上的顺序为读a>写a,造成了重排序重排序可能会导致不可见性,要是此时线程A、B分别在处理器A、B上执行,那么线程A执行了写操作后,线程B看不到线程A执行的结果,共享内存a不可见,改变了程序运行结果。

避免内存重排序

 引发重排序是糟糕的,可能造成共享内存不可见,改变程序结果。那么该怎么办,不进行MESI优化吗?既不能追求性能,造成重排序,也不能追求可见性(非共享数据可见是不需要的),降低性能。

 处理器还是使用提供了个武器——内存屏障指令(Memory Barrier):

  1. 写内存屏障(Store Memory Barrier):处理器将当前存储缓存的值写回主存,以阻塞的方式。
  2. 读内存屏障(Load Memory Barrier):处理器处理失效队列,以阻塞的方式。

 可以看到内存屏障可以阻止内存系统重排序,保证可见性。但其开销也很大,处理器需要阻塞等待,一般应用在锁的获取和释放中。

上面那段处理器A、B,依次写、读内存a,加了内存屏障后,就不会被重排序了。

boolean finish = false;
int a = 0;

//处理器A:
a = 1;
storeMemoryBarrer(); //保证a一定在主存中,且处理器B中a为invlid
finish = true;

//处理器B:
while(!finish);
loadMemoryBarrier(); //保证缓存到a最新的值,执行后a为share
assert a == 1;

JMM中抽象内存屏障

 

 为了更好的理解如何实现同步的可见性,JMM抽象出了内存屏障Memory Barrier。
内存屏障

1
0
分享到:
评论

相关推荐

    内存屏障原理解析

    因此,内存屏障和缓存一致性协议是现代计算机系统中维持内存操作正确性和效率的关键技术。它们的引入和应用,反映了处理器设计者在性能和一致性之间的权衡取舍。理解这些概念,对于设计和开发高性能多线程和分布式...

    Linux内存屏障

    通过上述讲解,我们了解到内存屏障在保证缓存一致性、解决乱序执行问题上的重要性。并行编程的基石之一就是内存屏障的正确使用,这不仅要求程序员对硬件架构和处理器指令有深入的理解,还要具备对并行算法设计的深刻...

    LINUX内核内存屏障

    - 在使用缓存一致性模型的系统中,内存屏障可以帮助维护缓存一致性。 #### 六、实例分析 考虑下面的一个例子: ```c int A = 1; int B = 2; // CPU1 A = 3; B = 4; // CPU2 int x = A; int y = B; ``` 在这个...

    内存屏障访问顺序

    为了确保数据在多处理器环境下的正确顺序和一致性,通常需要使用内存屏障(Memory Barrier)。内存屏障是一种特殊的指令,它可以强制CPU按照特定的顺序执行内存操作。具体来说,内存屏障可以分为以下几类: 1. **读...

    内核同步机制-优化屏障和内存屏障

    总的来说,优化屏障和内存屏障是Linux内核中确保多处理器系统同步和内存一致性的重要工具。它们通过阻止编译器优化和强制处理器按照特定顺序执行内存操作,保证了内核代码的正确性和系统的稳定性。在编写和理解内核...

    linux 内核内存屏障

    - **Cache一致性与DMA**:在涉及直接内存访问(DMA)操作时,需要特别注意缓存一致性问题。 - **Cache一致性与MMIO**:对于内存映射I/O操作,同样需要注意缓存一致性。 #### 十、CPU所能做到的 不同的CPU架构在内存...

    Linux内核分析、移植、驱动

    遵循最佳实践,比如使用锁和信号量避免数据竞争,利用内存屏障保证缓存一致性,以及遵循内核编程规范,能有效提高内核质量。此外,持续关注Linux社区的更新,及时应用安全补丁和性能改进,也是保持系统安全和高效...

    Linux内存屏障1

    Linux内存屏障是并行编程中一个至关重要的概念,它涉及到多核CPU的缓存一致性问题。在现代计算机系统中,由于CPU的运算速度远超内存访问速度,CPU通常会使用缓存来加速数据读写。然而,当多个CPU核心同时访问同一块...

    Memory Barriers: a Hardware View for Software Hackers 讲解内存屏障的好论文,推荐!

    为了更好地理解内存屏障的作用和它在硬件层面的表现,我们有必要先了解CPU缓存的工作原理,特别是多级缓存结构、缓存一致性协议,以及存储缓冲和失效队列是如何帮助提升缓存和整个系统的性能。 现代CPU的运行速度远...

    中国Linux内核开发者大会十周年演讲稿(中兴通讯谢宝友)-Linux内存屏障

    5. **性能影响**:虽然内存屏障能确保数据一致性,但过度使用会影响性能。他可能讨论了如何平衡内存屏障的使用与系统性能之间的关系。 6. **未来趋势**:随着硬件和软件的不断发展,内存屏障的使用和优化也将面临新...

    memory-barriers.pdf

    文章还提到了内核I/O屏障效果,CPU缓存对一致性的影响(包括缓存一致性cache coherency、缓存一致性与DMA、缓存一致性与MMIO)以及CPU所采取的一些行为(比如Alpha架构的情况)。 在隐式内存屏障方面,包括了与锁定...

    内存相关论文

    通过对CPU缓存的工作原理、缓存一致性协议以及存储缓冲区和失效队列的理解,我们可以更好地认识到内存屏障在现代计算环境中的重要性。 通过本文的介绍,我们可以了解到,内存屏障作为解决高速CPU与较慢主存之间速度...

    why memory barrier

    在理解内存屏障之前,我们首先需要了解CPU缓存以及缓存一致性协议是如何工作的,因为这些都是理解内存屏障原理不可或缺的部分。 缓存是CPU与主存之间的一个高速小型存储区域,它的速度远快于主存,但容量较小。现代...

    Linux-Kernel Memory Model.pdf

    硬件一致性模型,如MESI(修改、独占、共享、无效)协议,是解决缓存一致性的硬件层面手段。Linux内核在软件层面进一步提供了一系列内存屏障和锁操作,确保内存操作的顺序性符合程序员的预期。 Linux内核内存模型中...

    Memory_Barriers_a_Hardware_View_for_Software_Hacke.pdf

    通过对缓存结构、缓存一致性协议以及存储缓冲区和无效队列的理解,我们可以更好地认识到内存屏障的作用及其重要性。尽管它们增加了额外的开销,但内存屏障对于维护多处理器系统中的数据一致性具有至关重要的作用,...

    深入解析volatile关键字:保障多线程下的数据一致性与可见性.pdf

    这条指令会将该变量所在缓存行的数据写回主内存中,并通过缓存一致性协议通知其他处理器使它们缓存中的对应行变为无效状态。 这种方式确保了所有处理器在下次访问该变量时,都能从主内存中读取最新的值。 #### 三...

    Memory Barriers: a Hardware View for Software Hackers

    通过对CPU缓存结构、缓存一致性协议以及店缓冲区与无效队列的理解,我们可以更深入地认识到为什么内存屏障对于提高性能和可扩展性是必不可少的。此外,了解这些底层机制也有助于软件开发者在编写高性能并发程序时...

    深入理解Java内存模型

    Java内存模型中的同步机制,如volatile关键字,就是用来保证顺序一致性的。volatile的特性包括保证对一个volatile变量的写入操作先于后续的读操作,并且volatile的写-读建立的happens-before关系保证了可见性。 重...

    刘先喆shared Memory Consistency1

    因此,需要特定的缓存一致性协议来保证在任意时刻,所有处理器看到的内存状态都是合法的,即满足某种一致性模型,比如MESI(Modified, Exclusive, Shared, Invalidated)或MOESI(Modified, Owned, Exclusive, ...

Global site tag (gtag.js) - Google Analytics