【发布时间】:2013-02-04 06:56:39
【问题描述】:
我正在使用 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 个)。
【问题讨论】:
-
好奇,为什么要关心 TLB 未命中?
-
@Tony 在应用程序上工作,可能会通过预取避免它们(如果跨页面边界预取在特定架构上可用),避免热路径上未命中的开销。我怀疑 tlb 未命中的成本与缓存未命中(这是无法避免的)相比相形见绌,但想验证这个假设并在这样做时遇到了这个问题。
-
@jmetcalfe 尝试使用
calloc()而不是malloc()。 -
@Mysticial 这将报告的未命中次数减少到 32。类似地,如果我事先手动循环遍历数组以有效地预先设置它。我不明白为什么仍然有 32 次未命中(似乎所有这些都应该很高兴地适应 tlb 并留在那里直到第二个循环)。
-
哈!我猜对了。但是,我仍然无法解释剩下的最后 32 次失误。