2013-03-10 62 views
1

我想徹底測量和調整我的C/C++代碼,以便在x86_64系統上使用緩存更好地執行代碼。我知道如何用計數器(我的Windows機器上的QueryPerformanceCounter)來測量時間,但我想知道如何測量每個週期的指令或每個週期相對於工作集的讀取/寫入。如何測量讀取/循環或指令/循環?

我該如何着手測量這些值?

+2

在Linux上,'valgrind --tool = cachegrind'似乎很適合IYAM – sehe 2013-03-10 12:52:52

+0

現代處理器不僅執行多條指令每個週期,但時鐘週期本身因節能\動態而變化rclock功能。但是,仍然可以輕鬆獲得平均值 - 基準測試幾個不同大小的數據集,知道已用時間和處理器時鐘,無需任何特殊工具即可輕鬆獲得近似估計值。 – dtech 2013-03-10 15:14:40

回答

2

現代處理器(即那些不是非常受約束的小於20歲左右的處理器)是超標量的,即它們一次執行多於一條指令(給定正確的指令排序)。最新的x86處理器將CISC指令轉換爲內部RISC指令,對其重新排序並執行結果,甚至有幾個regster bank,因此使用「相同寄存器」的指令可以並行完成。目前沒有任何合理的方式來定義「執行指令的時間」。

當前的CPU是很多比內存更快(幾百條指令是訪問內存的典型成本),它們都嚴重依賴於緩存的性能。然後你有各種核心共享(或不)緩存的各種有趣的影響,...

調整代碼的最大性能開始於軟件體系結構,繼續進行程序組織,算法和數據結構選擇(這裏有一點緩存/虛擬內存意識也很有用),仔細的編程和(如最極端的措施來排除最後2%的性能)考慮因素,比如你提到的那些(以及另一個最喜歡的「重新組裝」 )。而排序就是這樣,因爲第一個等級爲相同的成本提供了更多的性能。 措施挖掘之前,程序員出了名的找到瓶頸不可靠的。並考慮重組代碼的性能成本,包括工作本身,說服自己這些複雜的代碼是否正確,以及維護。鑑於計算機和人員的相對成本,極端的性能調整很少有意義(可能是流行操作系統中的重要代碼路徑,編譯器生成的通用代碼路徑,但幾乎沒有其他地方)。

0

你可能會感興趣的RDTSC x86指令,其內容爲週期的相對數。

用於讀取許多編譯器櫃檯的實現見http://www.fftw.org/cycle.h

不過,我建議乾脆用QueryPerformanceCounter的測量。實際循環次數很重要,調整代碼通常只需要能夠比較相對時間測量結果,而rdtsc卻有很多缺陷(儘管可能不適用於您所描述的情況):

  • 在多處理器系統上,沒有單個相干循環計數器值。
  • 現代處理器通常會調整頻率,改變週期變化率。
+0

英特爾在幾年前改變了rdtsc的規格說它返回實時,而不是週期。 – 2013-03-10 16:05:24

1

如果你在你的代碼是打緩存,它更是創下內存真正感興趣的,並且處理器小於其設計約10-15歲,那麼在處理器性能計數器。您需要驅動程序級別的軟件來訪問這些寄存器,因此您可能不希望爲此編寫自己的工具。幸運的是,你不需要。

有像英特爾的VTune,AMD的CodeAnalyst和Linux的oprofile(可與AMD和Intel處理器兼容)的工具。

有一系列不同的寄存器可以計算實際完成的指令數量,處理器正在等待的週期數。您還可以計算「內存讀取次數」,「緩存未命中次數」,「TLB未命中次數」,「FPU指令數量」等。

下一個更棘手的部分當然是試圖解決這些問題,正如另一個答案中提到的,程序員並不總是擅長調整這些事情 - 而且這當然是耗時的,更不用說在X型處理器上運行良好的型號不一定能在Y型上運行得很快(早期的奔騰4有一些調整技巧,在AMD處理器上運行非常糟糕 - 如果另一方面,您可以調整AMD代碼處理器的年齡,你會得到在同一代英特爾處理器上運行良好的代碼!)