我正在使用PAPI高级API检查循环数组的简单程序中的TLB未命中,但看到的数字比预期的要多。
在其他简单的测试用例中,结果似乎非常合理,这使我认为结果是真实的,额外的遗漏是由硬件预取或类似的。
在使用PAPI时,有人可以解释这些数字或指出我的错误吗?
int events[] = {PAPI_TLB_TL};
long long values[1];
char * databuf = (char *) malloc(4096 * 32);
if (PAPI_start_counters(events, 1) != PAPI_OK) exit(-1);
if (PAPI_read_counters(values, 1) != PAPI_OK) exit(-1); //Zeros the counters
for(int i=0; i < 32; ++i){
databuf[4096 * i] = 'a';
}
if (PAPI_read_counters(values, 1) != PAPI_OK) exit(-1); //Extracts the counters
printf("%llu\n", values[0]);
我预计打印的数字在32或至少一些倍数的区域内,但始终得到93或更高的结果(不一致地高于96,即每次迭代不仅仅是3次未命中)。我正在运行固定到核心,没有别的东西(除了计时器中断)。
我在Nehalem并没有使用大页面,所以DTLB中有64个条目(L2中有512个)。
答案 0 :(得分:5)
根据评论:
malloc()
,则calloc()
或者数组是事先迭代完毕,则会错过32次。原因是由于懒惰分配。在你触摸它之前,操作系统实际上并没有给你记忆。
首次触摸该页面时,将导致页面错误。操作系统将捕获此页面错误并正确分配它(which involves zeroing等)。这是导致所有额外TLB未命中的开销。
但是如果您使用calloc()
或提前触摸所有内存,则在启动计数器之前将此开销移至。因此结果较小。
至于剩下的32个未命中......我不知道 (或者如评论中提到的那样,可能是PAPI干扰。)
答案 1 :(得分:0)
原因可能是因为你在每次循环迭代中都跳了4096:
for(int i=0; i < 32; ++i){
databuf[4096 * i] = 'a';
}
很有可能每次访问都会丢失缓存。