测来测去2:CPU缓存读入策略

到底哪些数据写入了CPU缓存

我们知道CPU会在要读写某个数据时,先将数据写入缓存。

我们也知道这个操作一般以Cache Line为操作粒度,并且Cache Line的长度一般为64Byte。

那么这个Cache Line包含的数据到底是哪64Byte呢?

如果要读写的数据的地址正好以64Byte对齐,那么肯定是这个数据和它之后的(64 - sizeof(数据))Byte存在于这个缓存行里。

但是如果要读写的这个数据地址不以64Byte对齐,而是在两个64Byte对齐的地址中间的某个位置,CPU写入Cache Line里的数据还是它和它之后的64Byte吗?CPU会“向前”对64取整作为Cache Line中的数据吗?

用False Sharing证明

根据之前介绍False Sharing的原理链接,通过判断是否发生False Sharing可以判断某两个数据是否存在于同一条Cache Line里。

构造如下结构体:

1
2
3
4
5
6
struct counter_t {
uint32_t front_padding[15];
uint32_t c1;
/* 64 bytes */
uint32_t c2;
};

其中c1c2是分别被两个CPU core写入的变量。

在构造counter_t的实例时,利用GCC attribute确保其起始地址与64Byte对齐:

struct counter_t counter __attribute__((aligned(64)));

在两个CPU核分别开始操作c1c2之前利用clflush指令清除所有相关缓存:

1
2
3
4
5
inline void
clflush(volatile void *p)
{
asm volatile ("clflush (%0)" :: "r"(p));
}

如果发生了False Sharing,则说明这两个变量在一个Cache Line里,则证明CPU是取欲读写变量及其之后64Byte数据写入缓存
如果没有发生False Sharing,则说明这两个变量不在一个Cache Line里,则证明CPU是取欲读写变量向前64取整地址上的数据写入缓存

结果

结果当然是没有发生False Sharing。

不然还搞什么n-way set associative :)

代码:https://github.com/PanZhangg/x86perf/blob/master/cache_line_alignment.c

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