2011-06-13 29 views
1

使用gprofkcachegrind對一些C++數字處理代碼進行剖析,可以得出類似的結果,這些結果對執行時間貢獻最大的函數(50-80%取決於輸入),但對於10-30%的函數,這兩個工具產生不同的結果。這是否意味着其中一個不可靠?你會在這裏做什麼?哪一個是最可靠的剖析工具gprof或k​​cachegrind?

回答

7

gprof其實很原始。這是它的功能。 1)以恆定速率對程序計數器進行採樣,並記錄每個函數(獨佔時間)中有多少樣本落地。 2)它計算任何函數A調用任何函數B的次數。 從中可以找出每個函數總共調用了多少次,以及它的平均排他時間是多少次。 要獲得每個函數的平均包含時間,它會在調用圖中向上傳播獨佔時間。

如果您希望這具有某種準確性,您應該知道一些問題。 首先,它只計算CPU時間在進程中,這意味着它對I/O或其他系統調用是盲目的。其次,遞歸混淆了它。第三,功能始終堅持平均運行時間的前提是無疑的,不管它們何時被調用或誰稱它們。第四,函數(及其調用圖)是您需要了解的概念,而不是代碼行,這只是一個普遍的假設,沒有其他。第五,測量的準確性甚至是相關找到「瓶頸」的概念也只是一個流行的假設,僅此而已。

Callgrind可以在行級別工作 - 這很好。不幸的是,它共享其他問題。

如果您的目標是找到「瓶頸」(與獲得常規測量值相反),則應該查看報表逐行顯示的掛鐘時間採樣器,例如Zoom。 原因很簡單,但可能不熟悉。

假設你有一個程序,有一堆函數互相調用,總共需要10秒。此外,還有一個採樣器不僅對程序計數器進行採樣,還對整個調用堆棧進行採樣,並且它始終以不變的速率進行採樣,例如每秒100次。 (現在忽略其他進程。)

所以最後你有1000個樣本的調用堆棧。 選擇出現在其中一個以上的代碼L的任意一行。 假設您可以以某種方式優化該行,避免它,刪除它,或將它傳遞給一個非常快速的處理器。

這些樣品會發生什麼?由於該行代碼L現在(基本上)沒有時間,所以沒有樣本可以打它,所以這些樣本只會消失,從而減少樣本總數,從而減少總時間!實際上,總體時間將會減少L在堆疊上的時間分數,這大約是包含它的樣本的一小部分。

我不想太統計,但很多人認爲你需要很多樣本,因爲他們認爲測量的準確性很重要。 這不是,如果你這樣做的原因是爲了找出需要加速的東西。 重點是找到什麼修復,而不是測量它。 L行在棧上的時間是F的一小部分,對不對? 所以每個樣本都有一個打F的概率,對嗎?就像翻轉硬幣一樣。 有一個這樣的理論,稱爲Rule of Succession。 它說(在簡化但是一般的假設下),如果你拋硬幣N次,看到「正面」S次,你可以估計硬幣F的平均值爲(S+1)/(N+2)。 所以,如果你拍下三樣樣品,並且看到上上的兩個他們,你知道F是什麼嗎? 當然不是。 但是,你平均知道它是(2 + 1)/(3 + 2)或60%。因此,您可以通過「優化」行L來節省多少時間(平均而言)。 而且,當然,堆棧樣本顯示正好是,其中行L(「瓶頸」**)是。 真的很重要,你沒有測量到兩個或三個小數位?

順便說一句,它對all the other problems mentioned above是免疫的。

**我一直在引用「瓶頸」,因爲什麼使大多數軟件變得緩慢與瓶子的頸部沒有什麼共同之處。 一個更好的比喻是一個「流失」 - 只是無用的浪費時間。

+0

非常具有說服力和全面的答案,謝謝 – flow 2011-06-16 08:35:33

+0

Zoom鏈接導致頁面鏈接中斷。 – 2017-07-08 21:57:33

+0

@FabioA .:看起來網站已經走了(也許是公司)。它發生了。我用維基百科替換了這個鏈接。那還沒有結束。 – 2017-07-10 20:54:34

2

gprof的定時數據是統計的(在details of profiling文檔中閱讀)。

另一方面,KCacheGrind使用valgrind其實際解釋所有的代碼。

所以KCacheGrind可以「更準確」(在更大的開銷爲代價)如果valgrind建模的CPU是接近您的真實CPU。

選擇哪一個也取決於您可以處理的開銷類型。根據我的經驗,gprof增加了更少的運行開銷(即執行時間),但它更具侵入性(即-pg爲每個函數添加代碼)。所以視情況而定,另一方更合適。對於「更好」gprof數據,請更長時間地運行您的代碼(並且可以使用更廣泛的測試數據)。你擁有的越多,統計學上的測量結果就越好。

相關問題