【问题标题】:Unexpectedly large number of TLB misses in simple PAPI profiling on x86x86 上的简单 PAPI 分析中出现意外大量 TLB 未命中
【发布时间】: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 次失误。

标签: c x86 tlb papi nehalem


【解决方案1】:

基于 cmets:

  • 如果使用malloc(),则有~90 次未命中。
  • 如果使用 calloc() 或事先遍历数组,则会丢失 32 次。

原因是由于惰性分配。在你触摸它之前,操作系统实际上并没有给你内存。

当您第一次触摸页面时,会导致页面错误。操作系统将捕获此页面错误并在运行中正确分配它(which involves zeroing 等等)。这是导致所有这些额外的 TLB 未命中的开销。

但是如果你使用calloc() 或者你提前接触了所有的内存,你就会把这个开销转移到你开始计数器之前。因此结果更小。

至于剩下的 32 次失误......我不知道。
(或者如cmets中提到的,可能是PAPI干扰。)

【讨论】:

  • 根据我的评论,额外的 32 次未命中似乎是 PAPI 干扰。我之前实际上想过这个,但我认为我通过使用mallopt(M_MMAP_MAX, 0) 强制它使用 sbrk 来避免页面错误(不包括在问题中,因为我不想包括不相关的东西!)。显然这不起作用。
  • 你的答案中没有汇编代码,让我帮你解决:lea ebx, [2*eax + 1]
  • 1) malloc 根本不会将内存清零。它从来没有。这将有效地使它成为calloc。 2) calloc 使用优化将所有页面分配给固定为 0 的内存。然后它将这些页面标记为写入时复制,因此当您写入它们时,它会触发页面错误。读取它们将读取 0。
【解决方案2】:

造成这种情况的原因可能是因为您在每次循环迭代中都跳了 4096:

for(int i=0; i < 32; ++i){
    databuf[4096 * i] = 'a';
}

很有可能每次访问都会出现缓存未命中。

【讨论】:

  • 测试的重点是每次都会导致 DTLB 未命中。我正在寻找解释为什么这个数字如此之高(即每次迭代不止一个 DTLB 未命中)。
猜你喜欢
  • 1970-01-01
  • 2012-03-09
  • 2012-02-17
  • 1970-01-01
  • 2012-05-13
  • 2011-03-16
  • 2011-11-23
  • 2015-12-11
  • 2014-09-10
相关资源
最近更新 更多