在现代多核处理器系统中,数据的一致性和访问效率是确保高性能计算的关键因素之一。随着技术的发展和应用需求的增长,传统的单核处理架构已经无法满足日益复杂的计算任务要求。因此,多核乃至多处理器系统的出现成为必然趋势。然而,在这样的并行计算环境中,如何保证各个核心之间的数据同步与一致成为了新的挑战。
缓存一致性问题是多核系统中最为核心的问题之一。当多个处理器核心共享同一块内存区域时,每个核心都可能拥有该内存区域的副本。如果一个核心修改了其缓存中的数据,其他核心必须能够及时感知这一变化,以保持数据的一致性。为了解决这个问题,各种缓存一致性协议应运而生。
本文将从最基本的总线嗅探技术入手,逐步深入探讨几种主流的缓存一致性协议,特别是MESI协议。我们将详细介绍这些协议的工作原理、优缺点以及对系统性能的影响。希望通过本文的讲解,读者能够对缓存一致性问题有一个全面的理解,并掌握解决这一问题的有效方法。
一、详解CPU体系结构和数据读写机制
1.CPU Cache Line是什么
每个CPU都会有自己的二级缓存,其中一级缓存分为数据缓存和指令缓存,这些缓存的数据都是从内存中读取的,而且每次都会加载一个cache line,而CPU Cache Line的物理结构大体如下图所示:
关于cache line的大小可以使用命令键入如下指令进行查看:
cat sysdevicessystemcpucpu0cacheindex0coherency_line_size
以笔者的服务器为例,可以看到对应的输出结果为64:
同时对应的我们给出CPU缓存与内存的体系结构图,其中按照数值减小访问速度越快,不同CPU核心都有独立的二级缓存,而三级缓存则是共享缓冲区,与物理内存空间直接打交道:
如果开发者能够很好的使用缓存技术,那么程序的性能就会很高,具体可以参照笔者之前写的这篇文章
计算机组成原理-基于计组CPU的基础知识进行代码调优:
2.CPU Cache和内存同步技术
(1) 写直达(Write Through)技术
写直达技术解决cache和内存同步问题的方式很简单,例如CPU1要操作变量i,先看看cache中有没有变量i,若有则直接操作cache中的值,然后立刻写回内存。 若变量i不在cache中,那么CPU就回去内存中加载这个变量到cache中进行操作,然后立刻写回内存中。 这样做的好处就是实现简单,缺点也很明显,因为每次都要将修改的数据立刻写回内存,这其中的写入开销对于需要高速运转的CPU是一种灾难:
(2) 回写技术(Write Back)
Write Back即一种延迟写技术,为了避免上一种操作频繁写入内存的资源开销而提出的一种方案,它的工作原理是将数据加载到CPU cache并修改但并不写入内存,仅仅是将数据标记为dirty,由此减少写入内存的次数,如果没有发生缓存置换,这些数据就不会被写入内存中。
举个例子,CPU cache加载data1到缓存中,并进行数次修改操作,随后cpu cache发生data10不在缓存中需要从内存中加载,又因为cpu cache空间不足,此时触发缓存置换算法便将最近最少使用且是dirty的数据写到内存中,并将data10加载到cpu cache里:
可以看出这种写法如果出现在毫秒级的断电场景可能存在数据丢失问题,又因为延迟写的原因,对应的数据加载在读未命中的情况下存在两次操作:
这里我们也补充一下几种比较常见的缓存置换算法:
二、详解CPU缓存一致性问题
1.多核心缓存修改问题
当一台计算机由多核CPU构成的时候,每个CPU都从内存里加载相同的变量i(初值为0)进行累加操作,我们试想这种情况:
而解决这个问题我们只要攻破以下两点问题即可:
2.总线嗅探(Bus Snooping)
总线嗅探是解决写传播的解决方案,举个例子,当CPU1更新Cache中变量i的值时,就会通知其他核心变量i已被修改,当其他CPU发现自己Cache中也有这个值的时候就会将CPU1中cache的结果更新到自己的cache中。 这种方式缺点很明显,CPU必须无时不刻监听变化,而且出现变化的数据自己还不一定有,这样的作法增加了总线的压力:
而且也不能保证事务串行化,如下图,CPU-0加载了变量修改了值通知其他CPU这个值有变化了。 而CPU-1也改了i的值,按照正常的逻辑CPU-2、CPU-3的值应该是先变为100在变为200。 但是CPU-3先收到CPU-2的通知先改为200再收到CPU-0的通知变为100,这就导致的数据不一致的问题,即事务串行化失败:
3.MESI协议如何解决上述问题
MESI是总线嗅探的改良版,他很好的解决了总线的带宽压力,以及很好的解决了数据一致性问题。 在介绍MESI之前,我们必须了解以下MESI是什么。
好了介绍完这几个状态之后,我们不妨用一个例子过一下这个流程:
三、小结
自此,我们从多核CPU体系结构所引发缓存一致性问题为入手,再从总线嗅探到MESI协议深度讲解了缓存一致性问题的解决方案,希望对你有帮助。