为什么写入文件会增加缓存未命中和分支未命中?

时间:2016-07-31 17:38:24

标签: c++ linux g++ perf

以下是我正在分析的代码:

#include <iostream>
#include <fstream>

#define N 10000

using namespace std;

int main()
{
    ofstream fout;
    fout.open("log.txt");

    int A[N], B[N], C[N];

    for(int i=0; i<N; i++)
    {
        A[i] = B[i] = i;
    }   

    int sum = 0;

    for(int j=0; j<N; j++)
    {
        C[j] = A[j]+B[j];
        //fout<<C[j]<<endl;
        sum += C[j];
        sum %= 103;
    }

    cout<<sum<<endl;

    return 0;
}

以下是分析命令:

perf stat -e instructions:u -e instructions:k -e cache-misses -e page-faults -e branch-misses ./test

输出是:

Performance counter stats for './test':

 15,60,186      instructions:u           
  8,35,753      instructions:k           
    24,345      cache-misses                                                
       123      page-faults                                                 
    13,051      branch-misses                                               

 0.001327182 seconds time elapsed

但是,当我取消注释该单个注释行时,我得到以下输出:

Performance counter stats for './test':

         75,72,868      instructions:u           
      12,29,31,625      instructions:k           
          2,18,333      cache-misses                                                
               121      page-faults                                                 
            73,662      branch-misses                                               

       0.525844017 seconds time elapsed

我无法理解是什么导致缓存未命中的大幅增加以及分支未命中的适度高增长。任何见解都将不胜感激!

1 个答案:

答案 0 :(得分:4)

没有&#34; fout<<C[j]<<endl;&#34;您的程序主要在用户空间中运行(我更确切地说,您的程序的重要部分是完全在用户空间中运行)。通过取消注释该行(在循环内),您将引入许多额外的系统调用(这通过探查器报告的instructions:k数量的大幅增加来显示)。系统调用很昂贵,因为它们涉及上下文切换,根据硬件架构和操作系统,它可能会使CPU缓存的显着部分无效。

请注意,这里的主要罪魁祸首是endl(强制刷新缓冲区,从而触发系统调用)。将其替换为'\n',对性能的影响要小得多。