獲取高精度時間注意事項 (QueryPerformanceCounter , QueryPerformanceFrequency)

花了很長時間才獲得的經驗,與你們分享。

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)
----------------------------------------------ios

相關文章
相關標籤/搜索