错误共享和128字节对齐/填充

2022-02-26 00:00:00 locking c++ false-sharing

在研究无锁/无等待算法时,我偶然发现了false sharing问题。深入研究后,我找到了Folly的源代码(Facebook的C++库),更具体地说,找到了header file和FOLLY_ALIGN_TO_AVOID_FALSE_SHARING宏的定义(当前在第130行)。乍一看,最让我惊讶的是值:128(即:代替64).

/// An attribute that will cause a variable or field to be aligned so that
/// it doesn't have false sharing with anything at a smaller memory address.
#define FOLLY_ALIGN_TO_AVOID_FALSE_SHARING __attribute__((__aligned__(128)))

AFAIK,现代CPU上的缓存块是64字节长,实际上,到目前为止,我在这个问题上找到的所有资源,包括来自英特尔的this article,都谈到了64字节对齐和填充,以帮助解决错误共享问题。

尽管如此,Facebook的人员仍然会在需要时将其类成员对齐并填充到128个字节。然后我在FOLLY_ALIGN_TO_AVOID_FALSE_SHARING的定义上面找到了一个解释的开头:

enum {
    /// Memory locations on the same cache line are subject to false
    /// sharing, which is very bad for performance.  Microbenchmarks
    /// indicate that pairs of cache lines also see interference under
    /// heavy use of atomic operations (observed for atomic increment on
    /// Sandy Bridge).  See FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
    kFalseSharingRange = 128
};

虽然它给了我更多的细节,但我仍然觉得我需要一些洞察力。我很好奇,在大量使用原子操作的情况下,连续缓存行的同步或它们上的任何rmw操作如何会相互干扰。 有人能告诉我这是怎么发生的吗?


解决方案

正如汉斯在评论中指出的,有关这方面的一些信息可以在关于英特尔酷睿微体系结构的3.7.3"二级高速缓存硬件预取"部分"Intel? 64 and IA-32 architectures optimization reference manual"中找到:

"Streamer-将数据或指令从内存加载到二级缓存。要使用Streamer,请将数据或指令组织成128字节的块,并按128字节对齐。第一次访问此挡路中位于内存中的两条缓存线之一时,会触发Streamer预取该对线。"

相关文章