我看到一些非常奇怪的东西。我写了一个小代码定时器来捕获代码块运行多长时间。我不能发布所有的代码,这是相当大的,但我已经通过所考虑的模块并没有什么接近的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变得有点冒险,这就是为什么它更快。我仍在调查,但如果有人能指出我正确的方向来证明这一点,我会非常感激。
你实际上是否使用过一个profiler(比如'gprof'等)并且检查了两次运行的区别?你有没有启用任何优化?你可以添加编译命令吗? – Zeta
tl; dr;将stdout/stderr重定向到某个不阻塞的设备(例如/ dev/null)时,它可能与使用终端或文件的行为不同(性能明智)。 –
嗨Zeta,我没有使用探查器,现在就试试。我已经添加了汇编。有相当多的课程,但他们都建立相同的,然后我把它们都链接到最后。 – joeButler