高速缓存一致性系统会尽最大努力向您隐藏此类信息。我认为您将不得不通过使用性能计数寄存器来检测高速缓存未命中,或者通过使用高分辨率计时器仔细测量读取存储位置的时间来间接观察它。
该程序在我的x86_64机器上运行,以演示的效果clflush
。它使用乘以读取全局变量所需的时间rdtsc
。作为一条直接与cpu时钟相关的指令,可以直接利用它来rdtsc
实现这一目标。
花了81刻
花了81刻
同花顺:花了387滴答
花了72刻
您会看到3次试验:第一个确保i
在高速缓存中(之所以如此,因为它只是作为BSS的一部分被清零了),第二个是读取i
应在高速缓存中的内容。然后将其clflush
踢出i
缓存(及其邻居),并显示重新读取将花费更长的时间。最终读取将验证它是否已返回高速缓存。结果是非常可重现的,并且差异足够大,很容易看到高速缓存未命中。如果您要校准开销,则rdtsc()
可以使差异更加明显。
如果你看不懂,你要测试的内存地址(虽然连mmap
的/dev/mem
应该为这些目的工作)你可以推断出你想要的东西,如果你知道的缓存中的缓存行大小和关联性。然后,您可以使用可访问的内存位置来探查您感兴趣的集合中的活动。
#include <stdio.h>
#include <stdint.h>
inline void
clflush(volatile void *p)
{
asm volatile ("clflush (%0)" :: "r"(p));
}
inline uint64_t
rdtsc()
{
unsigned long a, d;
asm volatile ("rdtsc" : "=a" (a), "=d" (d));
return a | ((uint64_t)d << 32);
}
volatile int i;
inline void
test()
{
uint64_t start, end;
volatile int j;
start = rdtsc();
j = i;
end = rdtsc();
printf("took %lu ticks\n", end - start);
}
int
main(int ac, char **av)
{
test();
test();
printf("flush: ");
clflush(&i);
test();
test();
return 0;
}