分析伪共享(False Sharing)产生原因

什么是伪共享呢(False Sharing)呢,讲清楚伪共享出现的原因,我们要先理清楚高速缓存和 MESI 缓存一致性协议

Posted by ChenJY on January 26, 2019 | Viewed times

之前读了一篇美团点评技术博客 2016 年发表的文章:高性能队列——Disruptor,里面提到了 ArrayBlockingQueue会因为加锁和伪共享等出现严重的性能问题。

什么是伪共享呢(False Sharing)呢,讲清楚伪共享出现的原因,我们要先理清楚高速缓存和MESI缓存一致性协议。

Cache Memory

我们都知道 CPU 和主内存之间的运算速度是差异巨大的,在现今的 SMP(Symmetric Multiprocessor)System 中,会在 CPU 和主存间设置三级高速缓存,L1L2L3,读取顺序由先到后。实际上 Cache 的设计是经历过变更的,Intel AMD 的实现细节都不尽相同,本文你可以简单理解为,L1 Cache 分为指令缓存和数据缓存两种,L2 Cache 只存储数据,L1L2 都是每个核心都有,而 L3 被多核共享。

MESI

那么问题来了,多核CPU的情况下有多个 L1 和 L2 缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个一致性的协议MESI

MESI规定了一个cache line存在四种状态:ModifiedExclusiveShared Invalid,这有点像状态机的转换,理清全部的状态较复杂,我们关注简单的:

  1. Modified:该缓存行只被缓存在该CPU的缓存中,并且是被修改过的,即与主存中的数据不一致,该缓存行中的内存需要在未来的某个时间点(允许其它CPU读取请主存中相应内存之前)写回主存。当被写回主存之后,该缓存行的状态会变成Exclusive状态。

  2. Exclusive:该缓存行只被缓存在该CPU的缓存中,它是未被修改过的,与主存中数据一致。该状态可以在任何时刻当有其它CPU读取该内存时变成Shared状态。同样地,当CPU修改该缓存行中内容时,该状态可以变成Modified状态。

  3. Shared:该状态意味着该缓存行可能被多个CPU缓存,并且各个缓存中的数据与主存数据一致,当有一个CPU修改该缓存行中,其它CPU中该缓存行可以被作废。

  4. Invalid:该缓存是无效的(可能有其它CPU修改了该缓存行)。

False Sharing

了解了这些之后,我们再来看伪共享问题,为什么它会影响到性能呢?

上图中thread0位于core0,而thread1位于core1,二者均想更新彼此独立的两个变量,但是由于两个变量位于同一个cache line中,此时可知的是两个cache line的状态应该都是Shared,而对于cache line的操作core间必须争夺主导权(ownership),如果core0抢到了,thread0因此去更新cache line,会导致core1中的cache line状态变为Invalid,随后thread1去更新时必须通知core0cache line刷回主存,然后它再从主从中loadcache line进高速缓存之后再进行修改,但令人抓狂的是,该修改又会使得core0cache line失效,重复上演历史,从而高速缓存并未起到应有的作用,反而影响了性能。

License


这是一个不定时更新的、披着程序员外衣的文青小号。

在这里,既分享极客技术,也记录人间烟火,欢迎关注。


Comment