花了很長時間才得到的經驗,與大家分享。
1. RDTSC - 粒度: 納秒級 不推薦
優勢: 幾乎是能夠獲得最細粒度的計數器
拋棄理由:
A) 定義模糊
- 曾經據說是處理器的cycle counter,但是后來似乎又不是了。
有的機器上每秒的TSC增長值等於CPU頻率,有的卻是一個不對應任何配置的數。到底是什么,Intel也沒解釋清楚。
B) 不准確
- 這是最重大的缺陷。再細的粒度,不准的話也沒用,至少不能當時間用。
在有的CPU上,特別是支持變頻技術的筆記本CPU上,TSC增長值會隨着CPU的頻率改變。忙的時候跑得快,閑得時候跑得慢。
2. QueryPerformanceCounter - 粒度: 1~100微秒級 不推薦
優勢: 盡管比RDTSC粒度稍低,但是不存在RDTSC在變頻CPU上的問題。
知道這個API的人估計都傾向於用這個,因為M$對這個API給出了比較明確的定義,就是每秒鍾某個計數器增長的數值。
拋棄理由: 還是不准確
盡管沒有源代碼,但是從M$的幫助文檔和知識庫可以了解到,PerformanceCounter是依賴於主板上與PCI設備有關聯的硬件。這就意味着,PerformanceCounter的結果還是會受到硬件頻率,特別是總線頻率的影響。
事實上,我在EeePC上測試的時候就發現,系統采用節能模式的時候PerformanceCounter出來的結果老是偏慢很多,超頻模式的時候又偏快,而且用電池和接電源的時候效果還不一樣!
3. timeGetTime - 粒度: 毫秒級 推薦
盡管粒度進一步降低,但是其無與倫比的優勢就是,准確。
在任何機器上返回的都是當前系統的啟動時間,精確到1毫秒。
使用注意事項:
A) 在NT系統上(據說)默認精度為10ms,但是可以用timeBeginPeriod來降低到1ms
B) 返回的是一個32位整數,所以要注意大約每49.71天會出現歸零(不像前兩個是64位數,要幾百年才會歸零)。
----------------------------------------------
-
實際上timeGetTime以及GetTickCount也是由QueryPerformanceCounter/QueryPerformanceFrequency得到的,因為做了除以頻率的操作,所以得到的數值比較客觀,准確
明顯不是的。
我的代碼就是用QueryPerformanceCounter / QueryPerformanceFrequency得到實際經過的時間。
測試方法為: 調用時間API, Sleep 500ms, 再調用時間API, 不停的循環。
用 兩次timeGetTime的差值得到經過的毫秒數 (簡稱 Tick)
與 兩次QueryPerformanceCounter的差值/QueryPerformanceFrequency得到經過的毫秒數 (簡稱 Counter)
比較發現:
在EeePC 正常模式下: Tick: 500ms, Counter: 500ms
在超頻模式下: Tick: 500ms, Counter: 535ms
在節能模式下: Tick: 500ms, Counter: 260ms
可見用多媒體時鍾timeGetTime始終是穩定的,但是PerformanceCounter就不行了。
----------------------------------------------
-
M$的有一個KB上提到芯片組Bug導致QueryPerformanceCounter有時候會往前跳幾秒。描述原因的時候說是因為芯片組在PCI Bus上的Bug導致系統接受到奇怪的消息,系統為了保證穩定就會往PerformanceCounter上加幾秒鍾。從這個描述上就可以看出,PerformanceCounter是以PCI Bus的某個硬件作為基礎的。
事實上,有的人說PerformanceCounter是系統接受的IRQ#0的計數器,但是還有一種說法是,在有的系統上PerformanceCounter會使用CPU的TSC...
總之,Performance Counter也不是一個可以100%靠得住的時間源。
要想你的代碼在大量配置不同的機器上不出問題,目前只有依賴timerGetTime這個多媒體時鍾。
----------------------------------------------
-
大概瞅了一下intel manual,vol3b (system programming guide B)里ch18第11和20節講的是關於計時的
手冊2b里RDTSC中除了說3b的18章外,還提到了3b的21章,這些你都仔細讀過了之后得到上述關於RDTSC的結論的么?
er... 我的是經驗,不是結論。靠讀manual是不可能得到的,是我花了很長時間在很多機器上試驗得到的結果。
有的機器上RDTSC的增幅是和頻率一致的,但是多數是台式機,而且是老型號。
新的台式機和筆記本CPU的RDTSC的增幅明顯不是頻率,有說法是總線的主頻。
Pentium M的TSC會隨着speedstep變化;服務器的好像還挺穩定,但是我沒有打開Linux內核的CPU Frequency Scaling,說不定打開了以后也會出現這個現象。
在多CPU下,每一個CPU的RDTSC是獨立的;SMP下運行的線程可能會被放到不同的CPU下運行,這意味着兩次讀TSC可能會出現后面比前面小的情況,所以最好還要SetThreadAffinity,綁定在一塊CPU上。
總之TSC用起來也很麻煩,而且太底層,很難在不同的配置下兼容。這個東西用來做單個機器的Profiling不錯(本來就是為了這個目的),但是如果當成時間源的話就差了。
----------------------------------------------
-
我建議吧,和硬件有關的東西還是直接看官方的manual,貸是人家設計的,手冊不可能還沒你的經驗靠譜
下面這段是vol 3b ch18.20中最開頭的部分,建議你在自己已經做過之前,不要輕易下“靠讀manual是不可能得到的”這種結論
The count of cycles, also known as clockticks, forms a the basis for measuring how
long a program takes to execute. Clockticks are also used as part of efficiency ratios
like cycles per instruction (CPI). Processor clocks may stop ticking under circum-
stances like the following:
? The processor is halted when there is nothing for the CPU to do. For example, the
processor may halt to save power while the computer is servicing an I/O request.
When Intel Hyper-Threading Technology is enabled, both logical processors must
be halted for performance-monitoring counters to be powered down.
? The processor is asleep as a result of being halted or because of a power-
management scheme. There are different levels of sleep. In the some deep sleep
levels, the time-stamp counter stops counting.
In addition, processor core clocks may undergo transitions at different ratios relative
to the processor’s bus clock frequency. Some of the situations that can cause
processor core clock to undergo frequency transitions include:
? TM2 transitions
? Enhanced Intel SpeedStep Technology transitions (P-state transitions)
----------------------------------------------