取得高解析度時間戳記

Windows 提供 API,可讓您用來取得高解析度時間戳記,或測量時間間隔。 原生程式碼的主要 API 是 QueryPerformanceCounter (QPC) 。 針對設備磁碟機,核心模式 API 是 KeQueryPerformanceCounter。 針對 Managed 程式碼, System.Diagnostics.Stopwatch 類別會使用 QPC 做為其精確時間基礎。

QPC 與任何外部時間參考無關且未同步處理。 若要擷取可以同步處理至外部時間參考的時間戳記,例如,國際標準時間 (UTC) ,以用於高解析度的日期度量,請使用 GetSystemTimePreciseAsFileTime

時間戳記和時間間隔度量是電腦和網路效能測量不可或缺的一部分。 這些效能測量作業包括回應時間、輸送量和延遲的計算,以及分析程式碼執行。 這些作業都牽涉到在時間間隔內發生的活動測量,該時間間隔是由開始和結束事件所定義,而該事件可以與任何外部時間參考無關。

QPC 通常是用來時間戳記事件的最佳方法,並測量在相同系統或虛擬機器上發生的小型時間間隔。 當您想要跨多部電腦進行時間戳記事件時,請考慮使用 GetSystemTimePreciseAsFileTime ,前提是每部電腦都參與時間同步處理配置,例如網路時間通訊協定 (NTP) 。 QPC 可協助您避免其他時間測量方法遇到的困難,例如直接讀取處理器的時間戳記計數器 (TSC) 。

Windows 版本中的 QPC 支援

QPC 是在 Windows 2000 和 Windows XP 中引進,並已演進以利用硬體平臺和處理器的改善。 在這裡,我們將說明不同 Windows 版本 QPC 的特性,以協助您維護在這些 Windows 版本上執行的軟體。

Windows XP 和 Windows 2000

QPC 可在 Windows XP 和 Windows 2000 上使用,且適用于大部分的系統。 不過,某些硬體系統的 BIOS 未指出硬體 CPU 特性正確 (非變異 TSC) ,而某些多核心或多處理器系統則搭配無法跨核心同步處理的 TSC 使用處理器。 如果系統使用 TSC 作為QPC的基礎,則執行這些 Windows 版本的韌體可能會提供不同核心的相同QPC讀取。

Windows Vista 與 Windows Server 2008

隨附于 Windows Vista 和 Windows Server 2008 的所有電腦都使用平臺計數器 (高精確度事件計時器 (HPET) ) 或 ACPI 電源管理計時器 (PM 計時器) 作為 QPC的基礎。 這類平臺計時器具有比 TSC 更高的存取延遲,而且會在多個處理器之間共用。 如果從多個處理器同時呼叫 QPC,這會限制 QPC 的延展性。

Windows 7 與 Windows Server 2008 R2

大部分的 Windows 7 和 Windows Server 2008 R2 電腦都有具有固定速率 TSC 的處理器,並使用這些計數器作為 QPC的基礎。 TSC 是每一處理器硬體計數器的高解析度,可根據處理器類型) ,以非常低的延遲和額外負荷來存取 (。 Windows 7 和 Windows Server 2008 R2 使用 TSC 作為單一時鐘網域系統的 QPC 基礎,其中作業系統 (或 Hypervisor) 能夠在系統初始化期間緊密同步處理所有處理器上的個別 TSC。 在這類系統上,相較于使用平臺計數器的系統,讀取效能計數器的成本會大幅降低。 此外,並行呼叫和使用者模式查詢不會增加額外負荷,通常會略過系統呼叫,進一步降低額外負荷。 在 TSC 不適合計時的系統上,Windows 會自動選取平臺計數器, (HPET 計時器或 ACPI PM 計時器) 作為 QPC的基礎。

Windows 8、Windows 8.1、Windows Server 2012 和 Windows Server 2012 R2

Windows 8、Windows 8.1、Windows Server 2012和 Windows Server 2012 R2 會使用 TSC 作為效能計數器的基礎。 TSC 同步處理演算法大幅改善,以更妥善地容納具有許多處理器的大型系統。 此外,還新增了新的精確當日 API 支援,可讓您從作業系統取得精確的時鐘時間戳記。 如需詳細資訊,請參閱 GetSystemTimePreciseAsFileTime。 在使用 Arm 處理器的Windows RT和Windows 11和Windows 10裝置上,效能計數器是以專屬的平臺計數器或 Arm 一般計時器所提供的系統計數器為基礎。如果平臺具備這類功能,則效能計數器會根據 Arm 一般計時器所提供的系統計數器。

取得時間戳記的指引

Windows 已持續投資提供可靠且有效率的效能計數器。 當您需要解析度為 1 微秒或更佳的時間戳記,而且您不需要將時間戳記同步處理至外部時間參考時,請選擇 QueryPerformanceCounterKeQueryPerformanceCounterKeQueryInterruptTimePrecise。 當您需要 UTC 同步處理的時間戳記,解析度為 1 微秒或更佳時,請選擇 GetSystemTimePreciseAsFileTimeKeQuerySystemTimePrecise

例如,基於硬體計時器資訊中所述的原因,在相對較少的平臺上,無法使用 TSC 註冊作為QPC基礎,取得高解析度時間戳記的成本可能比取得較低解析度的時間戳記更昂貴。 如果解析度為 10 到 16 毫秒,您可以使用GetTickCount64QueryInterruptTime、QueryUnbiasedInterruptTime、KeQueryInterruptTime 或 KeQueryUnbiasedInterruptTime來取得未同步至外部時間參考的時間戳記。 針對 UTC 同步時間戳記,請使用 GetSystemTimeAsFileTimeKeQuerySystemTime。 如果需要較高的解析度,您可以使用 QueryInterruptTimePreciseQueryUnbiasedInterruptTimePreciseKeQueryInterruptTimePrecise 來改為取得時間戳記。

一般而言,即使在不同的執行緒或進程上測量,效能計數器結果在多核心和多處理器系統中的所有處理器之間仍一致。 以下是此規則的一些例外狀況:

  • 在特定處理器上執行的 Windows Vista 作業系統可能會因為下列其中一個原因而違反此一致性:

    • 硬體處理器具有非變異 TSC,且 BIOS 未正確指出此狀況。
    • 使用的 TSC 同步處理演算法不適用於具有大量處理器的系統。
  • 當您比較從不同執行緒取得的效能計數器結果時,請考慮± 1 刻度不同的值,以具有模棱兩可的順序。 如果時間戳記取自相同的執行緒,則不適用此± 1 個刻度不確定。 在此內容中,刻度一詞是指一段時間等於 1,÷ (從 QueryPerformanceFrequency 取得的效能計數器頻率) 。

當您在大型伺服器系統上使用效能計數器搭配硬體中未同步處理的多時鐘網域時,Windows 會判斷 TSC 無法用於計時用途,並選取平臺計數器作為 QPC的基礎。 雖然此案例仍然會產生可靠的時間戳記,但存取延遲和延展性會受到負面影響。 因此,如先前的使用指引所述,只有在需要這類解析時,才使用提供 1 微秒或更佳解析的 API。 TSC 是針對包含所有處理器時鐘網域的硬體同步處理之多時鐘網域系統 進行 QPC 的基礎,因為這樣能有效地讓它們成為單一時鐘網域系統。

效能計數器的頻率會在系統開機時固定,而且在所有處理器上都是一致的,因此您只需要在應用程式初始化時查詢 QueryPerformanceFrequency 的頻率,然後快取結果。

虛擬化

效能計數器預期可在已正確實作 Hypervisor 上執行的所有客體虛擬機器上可靠地運作。 不過,符合 Hypervisor 1.0 版介面的 Hypervisor,並呈現參考時間啟發式可能會大幅降低額外負荷。 如需 Hypervisor 介面和啟發式的詳細資訊,請參閱 Hypervisor 規格

直接 TSC 使用方式

我們強烈建議不要使用 RDTSCRDTSCP 處理器指令直接查詢 TSC,因為您無法在某些版本的 Windows、虛擬機器的即時移轉和硬體系統上取得可靠結果,而不需要不可變或緊密同步的 TSC。 相反地,建議您使用 QPC 來運用它所提供的抽象、一致性和可攜性。

取得時間戳記的範例

這些章節中的各種程式碼範例示範如何取得時間戳記。

在機器碼中使用 QPC

此範例示範如何在 C 和 C++ 原生程式碼中使用 QPC

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;

QueryPerformanceFrequency(&Frequency); 
QueryPerformanceCounter(&StartingTime);

// Activity to be timed

QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;


//
// We now have the elapsed number of ticks, along with the
// number of ticks-per-second. We use these values
// to convert to the number of elapsed microseconds.
// To guard against loss-of-precision, we convert
// to microseconds *before* dividing by ticks-per-second.
//

ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;

從 Managed 程式碼取得高解析度時間戳記

此範例示範如何使用 Managed 程式碼 System.Diagnostics.Stopwatch 類別。

using System.Diagnostics;

long StartingTime = Stopwatch.GetTimestamp();

// Activity to be timed

long EndingTime  = Stopwatch.GetTimestamp();
long ElapsedTime = EndingTime - StartingTime;

double ElapsedSeconds = ElapsedTime * (1.0 / Stopwatch.Frequency);

System.Diagnostics.Stopwatch類別也提供數個方便的方法來執行時間間隔測量。

從核心模式使用 QPC

Windows 核心透過 KeQueryPerformanceCounter 提供效能計數器的核心模式存取權,而效能計數器和效能頻率都可以從中取得。 KeQueryPerformanceCounter 僅適用于核心模式,並且提供給設備磁碟機和其他核心模式元件的寫入器使用。

此範例示範如何在 C 和 C++ 核心模式中使用 KeQueryPerformanceCounter

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;

StartingTime = KeQueryPerformanceCounter(&Frequency);

// Activity to be timed

EndingTime = KeQueryPerformanceCounter(NULL);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;

QPC 和 TSC 的一般常見問題

以下是 一般 QPC 和 TSC 常見問題的解答。

QueryPerformanceCounter () 是否與 Win32 GetTickCount () 或 GetTickCount64 () 函式相同?

不會。 GetTickCount 和 GetTickCount64QPC無關。 GetTickCountGetTickCount64 會傳回啟動系統之後的毫秒數。

我應該使用 QPC 或直接呼叫 RDTSC/RDTSCP 指示嗎?

為了避免不正確和可攜性問題,強烈建議您使用QPC,而不是使用 TSC 暫存器或RDTSC 或 RDTSCP處理器指示。

QPC 與外部時間 epoch 有何關聯?它可以同步處理至外部 epoch,例如 UTC 嗎?

QPC 是以無法同步至外部時間參考的硬體計數器為基礎,例如 UTC。 如需可同步至外部 UTC 參考的精確當日時間戳記,請使用 GetSystemTimePreciseAsFileTime

QPC 是否受到系統管理員所做的日光節約時間、閏秒、時區或系統時間變更的影響?

不會。 QPC 完全獨立于系統時間和 UTC。

QPC 精確度是否受到電源管理或 Turbo Boost 技術所造成的處理器頻率變更影響?

不會。 如果處理器有不可變的 TSC, QPC 不會受到這類變更的影響。 如果處理器沒有不可變的 TSC, QPC 會還原為不會受到處理器頻率變更或 Turbo Boost 技術影響的平臺硬體計時器。

QPC 是否可靠地在多處理器系統、多核心系統和具有超執行緒的系統上運作?

是的。

如何?判斷並驗證 QPC 是否可以在我的電腦上運作?

您不需要執行這類檢查。

哪些處理器具有非變異 TSC?如何檢查我的系統是否有非非變異 TSC?

您不需要自行執行這項檢查。 Windows 作業系統會在系統初始化時執行數項檢查,以判斷 TSC 是否適合作為 QPC的基礎。 不過,針對參考用途,您可以使用下列其中一項來判斷處理器是否有非變異 TSC:

  • 來自 Windows Sysinternals 的 Coreinfo.exe 公用程式
  • 檢查與 TSC 特性相關的 CPUID 指令所傳回的值
  • 處理器製造商的檔

以下顯示 Windows Sysinternals Coreinfo.exe 公用程式所提供的 TSC-INVARIANT 資訊, (www.sysinternals.com) 。 星號表示 「True」。

> Coreinfo.exe 

Coreinfo v3.2 - Dump information on system CPU and memory topology
Copyright (C) 2008-2012 Mark Russinovich
Sysinternals - www.sysinternals.com

 <unrelated text removed>

RDTSCP          * Supports RDTSCP instruction
TSC             * Supports RDTSC instruction
TSC-DEADLINE    - Local APIC supports one-shot deadline timer
TSC-INVARIANT   * TSC runs at constant rate

QPC 是否可在Windows RT硬體平臺上可靠地運作?

是。

QPC 變換的頻率為何?

從最近的系統開機不到 100 年,而且根據所使用的基礎硬體計時器,可能更長。 對於大部分的應用程式而言,變換不是問題。

呼叫 QPC 的計算成本為何?

QPC的計算呼叫成本主要取決於基礎硬體平臺。 如果 TSC 暫存器用來作為 QPC 的基礎,計算成本主要取決於處理器處理 RDTSC 指令所需的時間。 此時間範圍從 10 個 CPU 週期到數百個 CPU 週期,視使用的處理器而定。 如果無法使用 TSC,系統會選取不同的硬體時間基礎。 因為這些時間基底位於主機板 (例如,在 PCI 南橋或 PCH) 上,每個呼叫計算成本會高於 TSC,而且經常會根據處理器速度和其他硬體因素而接近 0.8 - 1.0 微秒。 這項成本是由存取主機板上硬體裝置所需的時間所主導。

QPC 是否需要 (系統呼叫) 進行核心轉換?

如果系統可以使用 TSC 註冊作為 QPC的基礎,則不需要核心轉換。 如果系統必須使用不同的時間基底,例如 HPET 或 PM 計時器,則需要系統呼叫。

效能計數器單調 (是否不減少) ?

是。 QPC 不會向後移動。

效能計數器是否可以用來及時排序事件?

是。 不過,在比較從不同執行緒取得的效能計數器結果時,與± 1 刻度不同的值會有模棱兩可的順序,就像它們具有相同的時間戳記一樣。

效能計數器的精確度如何?

答案取決於各種因素。 如需詳細資訊,請參閱 低階硬體時鐘特性

使用 QPC 和 TSC 進行程式設計的常見問題

以下是使用 QPC 和 TSC 進行程式設計常見問題的解答。

我需要將 QPC 輸出轉換成毫秒。如何避免在轉換成雙精度或浮點數時遺失精確度?

在整數效能計數器上執行計算時,請記住幾個事項:

  • 整數除法將會遺失餘數。 在某些情況下,這可能會造成精確度遺失。
  • 64 位整數與浮點數之間的轉換 (雙精度) 可能會導致精確度遺失,因為浮點數尾數不能代表所有可能的整數值。
  • 乘 64 位整數可能會導致整數溢位。

一般原則是盡可能延遲這些計算和轉換,以避免複合導入的錯誤。

如何將 QPC 轉換成 100 奈秒刻度,以便將它新增至 FILETIME?

檔案時間是 64 位值,代表自 12:00 A.M.M. 1601 國際標準時間 (UTC) 起經過的 100 奈秒間隔數目。 WIN32 API 呼叫會使用傳回當日時間的檔案時間,例如 GetSystemTimeAsFileTimeGetSystemTimePreciseAsFileTime。 相反地, QueryPerformanceCounter 會傳回值,以單位 1/ (從 QueryPerformanceFrequency) 取得的效能計數器頻率來表示時間。 兩者之間的轉換需要計算 QPC 間隔和 100 奈秒間隔的比例。 請小心避免遺失有效位數,因為值可能很小, (0.0000001 / 0.000000340) 。

為什麼從 QPC 傳回的時間戳記是帶正負號的整數?

涉及 QPC 時間戳記的計算可能涉及減法。 藉由使用帶正負號的值,您可以處理可能會產生負值的計算。

如何從 Managed 程式碼取得高解析度時間戳記?

System.Diagnostics.Stopwatch類別呼叫Stopwatch.GetTimeStamp方法。 如需如何使用 Stopwatch.GetTimeStamp的範例,請參閱 從 Managed 程式碼取得高解析度時間戳記

在哪些情況下,QueryPerformanceFrequency 會傳回 FALSE,或 QueryPerformanceCounter 會傳回零?

這不會發生在任何執行 Windows XP 或更新版本的系統上。

我需要將執行緒親和性設定為單一核心才能使用 QPC 嗎?

不會。 如需詳細資訊,請參閱 取得時間戳記的指引。 此案例並非必要或不需要。 執行此案例可能會藉由將處理限制為一個核心,或在呼叫 QueryPerformanceCounter時,如果多個執行緒將其親和性設定為相同的核心,在單一核心上建立瓶頸,可能會對應用程式的效能造成負面影響。

低階硬體時鐘特性

這些區段顯示低階硬體時鐘特性。

絕對時鐘和差異時鐘

絕對時鐘提供精確的當日讀數。 它們通常是以國際標準時間 (UTC) 為基礎,因此其精確度取決於同步處理到外部時間參考的方式。 差異時鐘會測量時間間隔,而且通常不是以外部時間 Epoch 為基礎。 QPC 是差異時鐘,且不會同步處理至外部時間 Epoch 或參考。 當您將 QPC 用於時間間隔測量時,通常比使用衍生自絕對時鐘的時間戳記來取得的精確度更好。 這是因為同步處理絕對時鐘時間的程式可能會造成階段和頻率班次,以增加短期時間間隔測量的不確定度。

解析度、精確度、精確度和穩定性

QPC 會使用硬體計數器做為其基礎。 硬體計時器包含三個部分:刻度產生器、計算刻度計數器,以及擷取計數器值的方法。 這三個元件的特性會決定 QPC的解析度、精確度、精確度和穩定性。

如果硬體產生器以固定速率提供刻度,只要計算這些刻度即可測量時間間隔。 產生刻度的速率稱為 frequency,並以 Hertz (Hz) 表示。 頻率的倒數稱為句點或刻度間隔,並以適當的國際單位系統表示, (SI) 時間單位 (例如秒、毫秒、微秒或奈秒) 。

時間間隔

計時器的解析度等於句點。 解決方式決定區分任兩個時間戳記,並將下限放在可測量的最小時間間隔上。 這有時稱為刻度解析。

時間的數位測量會產生± 1 刻度的測量不確定度,因為數位計數器會以離散步驟前進,而時間會持續前進。 這種不確定性稱為量化錯誤。 對於典型的時間間隔測量,通常可以忽略此效果,因為量化錯誤遠小於測量的時間間隔。

數位時間測量

不過,如果測量的期間很小,而且接近計時器的解決方式,您必須考慮此量化錯誤。 引進的錯誤大小是一個時鐘週期的大小。

下圖說明使用解析度為 1 個時間單位的計時器,± 1 個刻度不確定的影響。

刻度不確定

QueryPerformanceFrequency 會傳回 QPC的頻率,而句點和解析度等於此值的相互值。 QueryPerformanceFrequency傳回的效能計數器頻率會在系統初始化期間決定,而且在執行系統時不會變更。

注意

QueryPerformanceFrequency通常不會傳回硬體刻度產生器的實際頻率。 例如,在某些舊版 Windows 中,QueryPerformanceFrequency會傳回 TSC 頻率除以 1024;在實作Hypervisor 1.0 版介面Hypervisor下執行 時 (,或一律在某些較新版本的 Windows) 中執行時,效能計數器頻率會固定為 10 MHz。 因此,請勿假設 QueryPerformanceFrequency 會傳回衍生自硬體頻率的值。

 

QueryPerformanceCounter 會讀取效能計數器,並傳回自 Windows 作業系統啟動時所發生的刻度總數,包括電腦處於睡眠狀態的時間,例如待命、休眠或連線待命。

這些範例示範如何計算刻度間隔和解析度,以及如何將刻度計數轉換成時間值。

範例 1

QueryPerformanceFrequency 會在特定電腦上傳回值 3,125,000。 此電腦上 QPC 測量的刻度間隔和解析度為何? 刻度間隔或句號是 3,125,000 的相互值,也就是 0.0000000320 (320 奈秒) 。 因此,每個刻度都代表 320 奈秒的傳遞。 無法在此電腦上測量小於 320 奈秒的時間間隔。

刻度間隔 = 1/ (效能頻率)

刻度間隔 = 1/3,125,000 = 320 ns

範例 2

在與上述範例相同的電腦上,從兩個連續呼叫 QPC 傳回的值差異為 5。 兩個呼叫之間經過的時間多長? 5 個刻度乘以 320 奈秒會產生 1.6 微秒。

ElapsedTime = Ticks * Tick Interval

ElapsedTime = 5 * 320 ns = 1.6 μs

從軟體讀取 (讀取) 刻度計數器需要時間,而此存取時間可以減少時間測量的精確度。 這是因為最小間隔時間 (可測量) 的最小時間間隔是解析度和存取時間的較大。

Precision = MAX [ Resolution, AccessTime]

例如,假設的硬體計時器具有 100 奈秒解析度和 800 奈秒的存取時間。 如果使用平臺計時器,而不是 TSC 註冊作為 QPC的基礎,則可能是這種情況。 因此,精確度會是 800 奈秒,而不是 100 奈秒,如此計算所示。

Precision = MAX [800 ns,100 ns] = 800 ns

這兩個圖描述此效果。

qpc 存取時間

如果存取時間大於解析度,請勿嘗試透過猜測來改善精確度。 換句話說,假設時間戳記是在中間,或是在呼叫的開頭或結尾進行時,是一個錯誤。

相反地,請考慮下列範例,其中 QPC 存取時間只有 20 奈秒,而硬體時鐘解析度為 100 奈秒。 如果 TSC 暫存器作為 QPC的基礎,這可能是這種情況。 此處的精確度受限於時鐘解析度。

qpc 精確度

在實務上,您可以尋找讀取計數器所需的時間大於或小於解析度的時間來源。 不論是哪一種情況,精確度都會大於兩者。

下表提供有關各種時鐘的近似解析度、存取時間和精確度的資訊。 請注意,某些值會因不同的處理器、硬體平臺和處理器速度而有所不同。

時鐘來源 標準時鐘頻率 時鐘解析度 存取時間 (一般) 精確度
PC RTC 64 Hz 15.625 毫秒 N/A N/A
使用 TSC 搭配 3 GHz 處理器時鐘查詢效能計數器 3 MHz 333 奈秒 30 奈秒 333 奈秒
具有 3 GHz 週期時間之系統上的RDTSC機器指示 3 GHz 333 picoseconds 30 奈秒 30 奈秒

 

因為 QPC 使用硬體計數器,所以當您瞭解硬體計數器的一些基本特性時,您會瞭解 QPC的功能和限制。

最常使用的硬體刻度產生器是一種玻璃。 玻璃是一小部分的金屬或其他金屬材質,可展示圓形圖特性,以提供具有絕佳穩定性和精確度的低成本頻率參考。 這個頻率是用來產生時鐘所計算的刻度。

計時器的正確性是指對 true 或標準值的正確性。 這主要取決於蝪石以指定頻率提供刻度的能力。 如果震動頻率太高,時鐘會「快速執行」,而測量的間隔會比實際還要長;如果頻率太低,則時鐘會「執行緩慢」,而測量的間隔看起來會比實際短。

例如,針對短期的一般時間間隔測量, (回應時間測量、網路延遲測量等等) ,硬體感應器的精確度通常就已足夠。 不過,對於某些度量而言,頻率精確度會變得很重要,特別是針對很長的時間間隔,或當您想要比較不同機器上所採取的度量時。 本節的其餘部分會探索精確度的效果。

在製造程式期間會設定振動的穩定頻率,並且由製造商根據指定的頻率加上或減去以 ppm) (ppm) 表示的製造容錯, 稱為最大頻率位移。 如果實際頻率介於 999,990 Hz 和 1,000,010 Hz 之間的實際頻率介於 999,990 Hz 和 1,000,010 Hz 之間,則其最大頻率位 ±移為 1,000,010 ppm,則會在規格限制內。

藉由以每秒微秒取代片語部分,我們可以將此頻率位移錯誤套用至時間間隔度量。 具有 + 10 ppm 位移的松子每秒會有 10 毫秒的錯誤。 因此,測量 1 秒間隔時,它會快速執行,並將 1 秒間隔測量為 0.9999990 秒。

方便的參考是頻率錯誤 100 ppm 會導致 24 小時後 8.64 秒的錯誤。 此表格顯示測量不確定度,因為累積錯誤較長的時間間隔。

時間間隔持續時間 測量不確定,因為累積錯誤與 +/- 10 PPM 頻率容錯
1 微秒 ± 10 picoseconds (10-12)
1 毫秒 ± 10 奈秒 (10-9)
1 秒 ± 10 微秒
1 小時 ± 60 微秒
1 日 ± 0.86 秒
1 週 ± 6.08 秒

 

上表顯示,對於小型時間間隔,通常可以忽略頻率位移錯誤。 不過,對於很長的時間間隔,即使是較小的頻率位移,也可能會導致大量的測量不確定。

在個人電腦和伺服器中使用的穩定性通常以每百萬個元件 30 到 50 個零件的頻率 ±承受度來製造,而且很少會關閉最多 500 ppm。 雖然具有更緊密頻率位移容錯的玻璃可用,但成本較高,因此不會在大部分電腦上使用。

若要降低此頻率位移錯誤的負面影響,Windows 的最新版本特別是Windows 8,請使用多個硬體計時器來偵測頻率位移,並盡可能補償它。 此校正程式會在 Windows 啟動時執行。

如下列範例所示,硬體時鐘的頻率位移錯誤會影響可達到的精確度,而時鐘的解析度可能較不重要。

頻率位移錯誤會影響可達到的精確度

範例 1

假設您使用 1 MHz 測量來執行時間間隔測量,其解析度為 1 微秒,而最大頻率位移誤差為 ±50 ppm。 現在,讓我們假設位移剛好是 +50 ppm。 這表示實際頻率會是 1,000,050 Hz。 如果我們測量的時間間隔為 24 小時,則測量時間會太短, (23:59:55.700000 測量的時間間隔與 24:00:00.000000 實際) 。

一天中的秒數 = 86400

頻率位移錯誤 = 50 ppm = 0.00005

86,400 秒 * 0.00005 = 4.3 秒

範例 2

假設處理器 TSC 時鐘是由冰箱控制,且指定頻率為 3 GHz。 這表示解析度會是 1/3,000,000,000 或大約 333 picoseconds。 假設用來控制處理器時鐘的穩定性具有±50 ppm 的頻率容錯,而且實際上是 +50 ppm。 雖然解析度相當令人印象令人印象驚歎,但時間間隔測量 24 小時仍然太短。 (測量的 23:59:55.700000000000 與 24:00:00:00.00000000000 實際) 。

一天中的秒數 = 86400

頻率位移錯誤 = 50 ppm = 0.00005

86,400 秒 * 0.00005 = 4.3 秒

這顯示高解析度 TSC 時鐘不一定提供比較低解析度時鐘更精確的測量。

範例 3

請考慮使用兩部不同的電腦來測量相同的 24 小時時間間隔。 這兩部電腦都有最大頻率位移的± ppm。 這兩個系統上相同時間間隔的測量距離有多遠? 如先前的範例所示,± 50 ppm 會產生 24 小時之後± 4.3 秒的最大錯誤。 如果一個系統執行 4.3 秒快速,而另一個 4.3 秒的速度緩慢,則 24 小時後的最大錯誤可能是 8.6 秒。

一天中的秒數 = 86400

頻率位移錯誤 = ±50 ppm = ±0.00005

± (86,400 秒 * 0.00005) = ±4.3 秒

兩個系統之間的最大位移 = 8.6 秒

總而言之,測量長時間間隔和比較不同系統之間的度量時,頻率位移錯誤會變得越來越重要。

計時器的穩定性描述刻度頻率是否隨著時間而變更,例如溫度變更的結果。 用來做為電腦上刻度產生器之溫度的核發器,會以溫度的函式來呈現小幅頻率變更。 相較于常見溫度範圍的頻率位移錯誤,熱漂移所造成的錯誤通常很小。 不過,適用于可攜式設備或設備的軟體設計工具,可能會需要考慮此影響。

硬體計時器資訊

TSC Register (x86 和 x64)

所有新式 Intel 和 AMD 處理器都包含 TSC 暫存器,這是以高速率增加的 64 位暫存器,通常等於處理器時鐘。 此計數器的值可以透過 RDTSCRDTSCP 機器指令讀取,根據處理器,提供非常低的存取時間和計算成本,以數十或數百個機器週期的順序。

雖然 TSC 暫存器似乎很理想的時間戳記機制,但以下是無法可靠地運作以供計時用途的情況:

  • 並非所有處理器都有可用的 TSC 暫存器,因此在軟體中使用 TSC 暫存器會直接建立可攜性問題。 (Windows 在此案例中會選取 QPC 的替代時間來源,以避免可攜性問題。)
  • 某些處理器可能會改變 TSC 時鐘的頻率,或停止 TSC 暫存器進展,這讓 TSC 不適用於這些處理器上的計時用途。 這些處理器稱為具有非變異 TSC 暫存器。 (Windows 會自動偵測到此問題,並選取 QPC) 的替代時間來源。
  • 即使虛擬化主機具有可用的 TSC,當目標虛擬化主機沒有或利用硬體輔助 TSC 調整時,執行虛擬機器的即時移轉可能會導致來賓可見的 TSC 頻率變更。 (如果客體可以進行這種類型的即時移轉,Hypervisor 就會清除 CPUID.) 中的非變異 TSC 功能位
  • 在多處理器或多核心系統上,某些處理器和系統無法將每個核心上的時鐘同步處理至相同的值。 (Windows 會自動偵測到此問題,並選取 QPC) 的替代時間來源。
  • 在某些大型多處理器系統上,即使處理器具有不可變的 TSC,您可能無法將處理器時鐘同步處理至相同的值。 (Windows 會自動偵測到此問題,並選取 QPC) 的替代時間來源。
  • 某些處理器會依序執行指令。 當 RDTSC 用於時間指令序列時,這可能會導致不正確的週期計數,因為 RDTSC 指令可能會在與程式中指定的不同時間執行。 已針對某些處理器引進 RDTSCP 指令,以回應此問題。

與其他計時器一樣,TSC 是以未事先知道確切頻率且具有頻率位移錯誤的玻璃為基礎。 因此,必須先使用另一個計時參考來校正它,才能使用它。

在系統初始化期間,Windows 會檢查 TSC 是否適合計時用途,並執行必要的頻率校正和核心同步處理。

PM 時鐘 (x86 和 x64)

ACPI 計時器也稱為 PM 時鐘已新增至系統架構,以提供與處理器速度無關的可靠時間戳記。 因為這是此計時器的單一目標,因此它會在單一時鐘週期中提供時間戳記,但不會提供任何其他功能。

HPET Timer (x86 和 x64)

Intel 和 Microsoft 共同開發高精確度事件計時器 (HPET) ,以符合多媒體和其他時間敏感性應用程式的計時需求。 不同于 TSC,這是每一處理器資源,HPET 是共用且全平臺的資源,但系統可能會有多個 HPET。 HPET 支援自 Windows Vista 起已在 Windows 中,且 Windows 7 和Windows 8硬體標誌認證需要硬體平臺中的 HPET 支援。

一般計時器系統計數器 (Arm)

Arm 型平臺沒有 TSC、HPET 或 PM 時鐘,因為 Intel 或 AMD 平臺上有。 相反地,Arm 處理器會提供一般計時器 (有時稱為「一般間隔計時器」或 GIT) ,其中包含系統計數器暫存器 (例如,CNTVCT_EL0) 。 泛型計時器系統計數器是固定頻率的全平臺時間來源。 它會在啟動時從零開始,並以高速率增加。 在 Armv8.6 或更高版本中,這會定義為完全相同的 1 GHz,但應該藉由讀取早期開機韌體所設定的時鐘頻率暫存器來決定。 For more details, see the chapter "The Generic Timer in AArch64 state" in "Arm Architecture Reference Manual for A-profile architecture" (DDI 0487).

迴圈計數器 (Arm)

Arm 型平臺提供效能監視器迴圈計數器註冊 (,例如,PMCCNTR_EL0) 。 此計數器會計算處理器時鐘週期。 它是非變異的,而且其單位可能不會與即時相互關聯。 不建議使用此暫存器來取得時間戳記。