我看到一些非常奇怪的東西。我寫了一個小代碼定時器來捕獲代碼塊運行多長時間。我不能發佈所有的代碼,這是相當大的,但我已經通過所考慮的模塊並沒有什麼接近的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