我正在使用 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 个条目)。
最佳答案
根据评论:
- 如果使用
malloc()
,大约会丢失 90 次。 - 如果使用
calloc()
或事先迭代数组,则会丢失 32 次。
原因是由于延迟分配。在您触摸操作系统之前,操作系统实际上并没有为您提供内存。
当您第一次触摸该页面时,将会导致页面错误。操作系统将捕获此页面错误并动态正确分配它(which involves zeroing等等)。这就是导致所有额外 TLB 未命中的开销。
但是,如果您使用 calloc()
或提前触及所有内存,则会将此开销移至启动计数器之前。因此结果较小。
至于剩下的32次未命中……我不知道。
(或者正如评论中提到的,这可能是 PAPI 干扰。)
关于c - x86 上的简单 PAPI 分析中意外出现大量 TLB 未命中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14960116/