標籤:static 頻率 clu orm solution val init 忽略 inter
1.為什麼會寫windows下微秒級延時
在上一篇 實現memcpy()函數及過程總結 中測試memcpy的效率中,測試時間的拷貝效率在微秒層級,需要使用微秒級時間間隔計數。
windows下提供QueryPerformanceCounter(查詢高效能計數器),QPC是基於硬體計數器,擷取高解析度時間戳記。
參考:Acquiring high-resolution time stamps
應用形式:
1 LARGE_INTEGER start, end; 2 LARGE_INTEGER Frequency; 3 QueryPerformanceFrequency(&Frequency); 4 5 QueryPerformanceCounter(&start); 6 7 //已耗用時間體 8 9 QueryPerformanceCounter(&end);10 11 //轉換時間(us) double(end.QuadPart - start.QuadPart) * 1000000 / Frequency.QuadPart
上面通過API查詢高效能計數器,開始tick,結束tick,轉換對應時間間隔。
2.基於QPC實現us延時
1 //timer.c 2 3 #include "timer.h" 4 5 static LARGE_INTEGER start; 6 static LARGE_INTEGER tick; 7 static LONGLONG SecondTick; 8 9 double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency)10 {11 return (double)(EndTick - StartTick) * 1000000 / Frequency;12 }13 14 /*15 * function:us延時初始化16 *17 * parameter:無18 *19 * return value:無20 * 21 */22 void MicrosecondDelayInit(void)23 {24 LARGE_INTEGER frequence;25 QueryPerformanceFrequency(&frequence);26 SecondTick = frequence.QuadPart; 27 }28 29 /*30 * function:MicrosecondDelay();31 * 實現微秒級延時32 * 33 * parameter:34 * n:延時的us數35 * 36 * return value:37 * 無38 */39 40 void MicrosecondDelay(int n)41 {42 QueryPerformanceCounter(&start);43 double endtick = SecondTick * n/1000000.0 + start.QuadPart;44 for(;;)45 {46 QueryPerformanceCounter(&tick);47 if (tick.QuadPart >= endtick)48 break;49 }50 }
1 //timer.h 2 3 #pragma once //編譯器保證標頭檔只編譯一次 4 5 #include <windows.h> 6 #include <stdio.h> 7 8 #ifdef __cplusplus 9 extern "C" {10 #endif 11 double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency);12 void MicrosecondDelayInit(void);13 void MicrosecondDelay(int n);14 #ifdef __cplusplus 15 }16 #endif
3.us延時測試
1 #include <stdio.h> 2 #include <Windows.h> 3 #include"timer.h" 4 5 int main(void) 6 { 7 LARGE_INTEGER Frequency; 8 LARGE_INTEGER StartingTime, EndingTime; 9 10 QueryPerformanceFrequency(&Frequency);11 MicrosecondDelayInit();12 13 QueryPerformanceCounter(&StartingTime);14 MicrosecondDelay(10);15 QueryPerformanceCounter(&EndingTime);16 17 printf("延時:%lf\n", GetMicrosecondTimeInterval(StartingTime.QuadPart, EndingTime.QuadPart, Frequency.QuadPart));18 system("pause");19 return 0;20 }
測試情況:
1.延時情況能達到us級,多次測試回合,個別情況延時會有出入(出現情況較少)。
分析原因:代碼級影響較小,主要運行是在windows下,windows並不是即時作業系統,畢竟windows作業系統時間解析度只能達到ms級。
延時可以被打斷。cpu的頻率會在變化,代碼執行效率也會有影響。
2.這種延時效果明顯好於Sleep的ms級延時。
4.windows下us延時,控制誤差
1.硬體上實現us延時(這種情況對於不涉及底層硬體操作的並不現實)
2.既然windows提供給我們QPC(查詢高效能計數器 <1us),配合著使用我們自己實現的us級延時。
我們延時前擷取StartTick,延時結束後再擷取EndTick,轉換對應對應時間間隔。QueryPerformanceCounter函數2次消耗時間幾乎可以忽略。通過列印我們可以看到us延時數。
大多數運行情況,延時函數效果1us內誤差。大於1us延時我們可以剔除,保證1us時間誤差。(這種做法是我們需要us級延時做測試時採用,保證後面資料結果在特定延時效果下)
5.總結
us延時常用於測試一些效能時使用。windows並未通過us級的延時函數。QPC是基於查詢硬體計數器擷取時間間隔,能達到us層級。
windows下基於(QPC)實現的微秒級延時