2013-11-20 81 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

您是否嘗試過使用窗口關閉窗口或其他窗口後面的窗口來運行它,以便它不必繪製?我一直在某些系統上繞過窗口的重畫。

相關問題