几句话说清楚3:什么是False Sharing

不用图

以为又要见到那几张网上已经用烂了的图了是不是?这次我们不用图来讲这个事。

Cache line是64个Byte,我们经常操作(R/W)的变量是4个或者8个Byte。

于是一个Cache line里就可以放好几个变量,比如说其中有两个变量A和B。

当CPU0写入A,CPU1写入B的时候,就发生了False Sharing,就这么简单。

所谓“假共享”,其实就是你以为你俩自己操作自己的变量是共产国际按需分配互不影响,其实都是假象。

很多材料上说是因为不同的CPU核共享了相同的Cache Line,其实并不严谨。根本因素是不同的CPU核需要更新的缓存出现了地址上的重叠。

那么当其中一个核更新了它的变量A之后,CPU并不能识别出是哪4个Byte或8个Byte地址上的数据被更新,而只能认为该变量所在的整条64Byte Cache Line都应该被更新。

所有有和这64Byte重叠的Cache Line,不管在哪个CPU核上,都需要被更新,这样才能保证大家手头的数据是一致的。

于是乎,和这64Byte地址存在重叠的变量B所在的CPU1中的缓存也需要被更新,自然就影响到了性能。

如果只是读,就没有这个问题,因为不需要关心缓存一致这个事。

示例

这里有一个活生生的代码的例子:

https://github.com/PanZhangg/x86perf/blob/master/false_sharing_padding.c

1
2
3
4
5
6
7
8
9
10
struct counter_t {
uint32_t c1;
#ifdef PADDING_64_BYTE
uint32_t padding[15];
#elif PADDING_128_BYTE
uint32_t padding[31];
#else
#endif
uint32_t c2;
};

本来是打算用来验证在CPU预取开启的情况下到底是应该Padding 64还是128,但在Haswell和Skylake上验证,这两个长度都没有区别。

后来查找资料是在Sandy bridge上需要padding到128,但我这里没有这么老的CPU….先这样吧..

上面的代码注意用-O0编译。

,
© 2020 DecodeZ All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero