2

我正在使用 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 个)。

4

2 回答 2

5

根据评论:

  • 如果使用,约 90 次未命中malloc()
  • calloc()如果使用或事先迭代数组,则32 未命中。

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

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

但是,如果您calloc()提前使用或触摸了所有内存,则将这些开销移至启动计数器之前。因此较小的结果。

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

于 2013-02-19T16:09:42.983 回答
0

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

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

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

于 2013-02-19T16:06:53.440 回答