我目前正在尝试编写一个程序,使其L1缺失率尽可能高。
为了测量L1缺失率,我正在使用Intel Core i7处理器上的MEM_LOAD_RETIRED.L1_MISS和MEM_LOAD_RETIRED.L1_HIT性能计数器事件(我不关心填充缓冲区命中情况)。我修改了Linux内核以在每个上下文切换时给出精确的测量结果,以便我可以确定每个程序获得的命中和缺失次数。
硬件预取器已禁用。
这是我目前的代码:
#define LINE_SIZE 64
#define CACHE_SIZE 4096 * 8
#define MEM_SIZE CACHE_SIZE * 64
void main(int argc, char* argv[])
{
volatile register char* addr asm ("r12") = mmap(0, MEM_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
volatile register unsigned long idx asm ("r13") = 0;
volatile register unsigned long store_val asm ("r14") = 0;
volatile register unsigned long x64 asm ("r15") = 88172645463325252ull;
while(1)
{
x64 ^= x64 << 13;
x64 ^= x64 >> 7;
x64 ^= x64 << 17;
store_val = addr[x64 % MEM_SIZE];
}
}
这段代码每个循环迭代都只产生一次内存访问,那么我的问题是:为什么我在这里得到的缺失率接近0%?即使没有异或移位操作,只是线性访问数组(编辑:每次访问增加64个索引),我应该获得接近100%的缺失率,对吗?我错了什么?
提前感谢! :)
更新:使用callgrind进行线性访问时,我得到了预期的99.9% miss率。我不理解。
使用perf-tool和以下命令: “perf stat -r 10 -B -e mem_load_retired.l1_miss,mem_load_retired.l1_hit ./thrasher” 给出的结果与我使用修改过的内核输出得到的结果类似。