2013-11-20 53 views
1

我看到一些非常奇怪的东西。我写了一个小代码定时器来捕获代码块运行多长时间。我不能发布所有的代码,这是相当大的,但我已经通过所考虑的模块并没有什么接近的std ::法院去当我重定向stdout时,为什么我的程序运行速度更快?

$ bin/profiler 50 
50 repetitions of Generate Config MLP took: 254 microseconds 
50 repetitions of Create Population took: 5318 microseconds 
50 repetitions of Create and Score Population took: 218047 microseconds 

$ bin/profiler 50 > time_times 
$ cat time_times 
50 repetitions of Generate Config MLP took: 258 microseconds 
50 repetitions of Create Population took: 5438 microseconds 
50 repetitions of Create and Score Population took: 168379 microseconds 

$ bin/profiler 50 
50 repetitions of Generate Config MLP took: 269 microseconds 
50 repetitions of Create Population took: 5447 microseconds 
50 repetitions of Create and Score Population took: 216262 microseconds 

$ bin/profiler 50 > time_times 
$ cat time_times 
50 repetitions of Generate Config MLP took: 260 microseconds 
50 repetitions of Create Population took: 5321 microseconds 
50 repetitions of Create and Score Population took: 169431 microseconds 

这里是我使用的时间块,函数ptr只是一个连接到一个void函数的链接,它使得一个函数调用。我意识到可能有更好的方法来计时,我想快速和肮脏,所以我开始改进代码。

void timeAndDisplay(string name,function_ptr f_ptr) { 

    struct timeval start, end; 
    long mtime, seconds, useconds; 

    gettimeofday(&start, NULL); 
    // Run the code 
    for (unsigned x = 0; x < reps; x++) { 
     f_ptr(); 
    } 

    gettimeofday(&end, NULL); 
    seconds = end.tv_sec - start.tv_sec; 
    useconds = end.tv_usec - start.tv_usec; 
    mtime = ((seconds) * 1000000 + useconds/1.0) + 0.0005; 

    std::cout << reps << " repetitions of " << name << " took: " << mtime << " microseconds" << std::endl; 
} 

我编译和链接有:

g++ -c -Wall -O3 -fopenmp -mfpmath=sse -march=native src/profiler.cpp -o build/profiler.o 
g++ build/*.o -lprotobuf -lgomp -lboost_system -lboost_filesystem -o bin/profiler 

我正要开始,所以我想我会保存一个基线进行更改,但创建和得分人口正在执行不同的,当我重定向它!

有人知道发生了什么吗?

更新1: 第一遍与剖析犯规显示任何显著。几乎所有的顶级调用都与程序运行的矢量数学(Eigen库)相关。流行的理论是,控制台有一些阻塞的io,但对std :: cout的调用在函数循环之外,总共只有3个,所以我觉得很难接受它有这样的影响。

更新2: 有这个我发疯了一段时间后,我放弃了一点,并开始进行改进,以我的程序与我有可用的数据。它变得更加怪异,但我想我已经找到了一个主要的影响因素 - 可用的系统熵。我的程序使用了大量的随机数,并且在使用任一方法运行一段时间后,它似乎以更慢的速度运行。我使用了for循环来模拟这两种方法,尽管stdout重定向的速度更快,但我怀疑这个小小的IO会让urandom变得有点冒险,这就是为什么它更快。我仍在调查,但如果有人能指出我正确的方向来证明这一点,我会非常感激。

+0

你实际上是否使用过一个profiler(比如'gprof'等)并且检查了两次运行的区别?你有没有启用任何优化?你可以添加编译命令吗? – Zeta

+1

tl; dr;将stdout/stderr重定向到某个不阻塞的设备(例如/ dev/null)时,它可能与使用终端或文件的行为不同(性能明智)。 –

+0

嗨Zeta,我没有使用探查器,现在就试试。我已经添加了汇编。有相当多的课程,但他们都建立相同的,然后我把它们都链接到最后。 – joeButler

回答

3

写入标准控制台或从标准控制台写入输入/输出系统涉及缓冲区和锁定。所以我会说你通常会因为锁定缓冲区而导致性能下降。

我会推荐以下Profiler找出花费最长的时间。

+0

谢谢,我已经用gprof和Linux perf进行了一次快速浏览。它还没有跳出去的时间丢失,但我会稍后得到适当的看法。可以困在Linux上运行? – joeButler

1

向控制台写入操作涉及图形操作,可能还会处理回车符(移动到行的开头)和换行符(将所有以前的文本移到一行并删除顶行)。

重定向到文件通常会更快,因为输出被附加并且不会发生图形操作。

至少这是我的经验。

+0

当然,我明白了,但我不认为这解释了巨大的差异。整个程序中只有3行输出,它们在时序循环之外,所以我不认为它们对结果有什么实质性影响 – joeButler

0

您是否尝试过使用窗口关闭窗口或其他窗口后面的窗口来运行它,以便它不必绘制?我一直在某些系统上绕过窗口的重画。

相关问题