c – 虚假共享和128字节对齐/填充

前端之家收集整理的这篇文章主要介绍了c – 虚假共享和128字节对齐/填充前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在进行关于无锁/等待免费算法的研究时,我偶然发现了 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操作在大量使用原子操作时可能会相互干扰.
有人可以告诉我如何才能发生这种情况吗?

解决方法

无论是否使用原子操作,缓存都有一个“高速缓存行”,它是缓存操作的最小单位.这取决于处理器型号,从32到128字节.当同一个高速缓存行中的元素在不同的线程(在不同的处理器[1]上运行)之间“共享”时,虚假共享.当这种情况发生时,一个处理器更新“其值”将强制所有其他处理器“摆脱其数据的复制”.在原子操作的情况下,由于执行任何原子操作,执行操作的处理器将变得更糟,执行操作的处理器将需要确保所有其他处理器在更新该值之前已经摆脱了“它们的副本”(以确保没有其他处理器正在使用在更新值之前的“旧”值) – 这需要通过系统传播大量缓存维护消息,并且处理器重新加载先前在缓存中的值.

因此,从性能的角度来看,如果您有一个线程使用的变量,将它们分离到自己的高速缓存行(在原始帖子的示例中,假定为128字节),将数据与该数据对齐值 – 意味着每个数据块都在平均高速缓存线边界上开始,并且没有其他处理器将“共享”相同的数据(除非您真正在线程之间共享数据 – 此时您需要执行相关的缓存维护以确保数据在处理器之间正确更新)

[1]或具有多个内核的现代cpu中的处理器核心.为了简单起见,我使用“处理器”或“处理器”一词来对应于一个插槽内的真实处理器插槽或处理器内核.对于这个讨论,这个区别是无关紧要的.

猜你在找的C&C++相关文章