首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Windows 高精度計時器 KTimer:RDTSC 週期計數實作

     編輯:關於C++

Windows 標準計時器(GetTickCount、timeGetTime)精度僅 1~15 ms。對於效能分析、遊戲迴路、即時系統,需CPU 週期級(納秒級)計時器。本文提供基於 RDTSC 指令的 KTimer 類別,支援 CPU 頻率校準、開銷扣除、週期轉納秒/毫秒。

核心原理

  • RDTSC(Read Time-Stamp Counter):讀取 CPU 內部 64 位元週期計數器,指令級精度。
  • 現代 CPU 支援 Invariant TSC(固定頻率),不受睿頻/節能影響,適合跨核心計時。
  • 首次建構時自動測量 Start()/Stop() 開銷(m_overhead),後續測量自動扣除。
  • Sleep(1000) 校準 CPU 頻率(MHz),假設睡眠誤差可忽略。

完整原始碼(KTimer.h)

#pragma once
#ifndef STRICT
#define STRICT
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>

// 內嵌 RDTSC:_emit 0x0F 0x31
inline unsigned __int64 GetCycleCount() {
    _asm _emit 0x0F
    _asm _emit 0x31
}

class KTimer {
    unsigned __int64 m_startCycle;
    unsigned __int64 m_overhead;  // 開銷週期數

public:
    KTimer() : m_overhead(0) {
        Start();
        m_overhead = Stop();      // 校準開銷
    }

    void Start() {
        m_startCycle = GetCycleCount();
    }

    // 返回扣除開銷後的經過週期
    unsigned __int64 Stop() {
        return GetCycleCount() - m_startCycle - m_overhead;
    }

    // 週期 → 納秒
    static unsigned __int64 CyclesToNanos(unsigned __int64 cycles, unsigned int cpuMHz) {
        return cycles * 1000 / cpuMHz;
    }

    // 週期 → 毫秒
    static unsigned __int64 CyclesToMillis(unsigned __int64 cycles, unsigned int cpuMHz) {
        return cycles / cpuMHz / 1000;
    }

    // 校準 CPU 頻率(MHz)
    unsigned int CPUSpeedMHz() {
        Start();
        Sleep(1000);
        unsigned __int64 cputime = Stop();
        return static_cast<unsigned int>(cputime / 1000000);
    }
};

使用範例

int main() {
    KTimer kt;
    unsigned int cpuMHz = kt.CPUSpeedMHz();  // 校準頻率

    kt.Start();
    Sleep(1234);                             // 模擬待測程式碼
    unsigned __int64 cycles = kt.Stop();

    std::printf("CPU Speed: %.2f GHz\n", cpuMHz / 1000.0);
    std::printf("Elapsed: %llu cycles (%llu ns, %llu ms)\n",
                cycles,
                KTimer::CyclesToNanos(cycles, cpuMHz),
                KTimer::CyclesToMillis(cycles, cpuMHz));
    return 0;
}

注意事項與避坑

議題說明
多核心/多處理器舊 CPU TSC 不同步,跨核心遷移導致時間倒流。現代 CPU(Intel Nehalem+、AMD Bulldozer+)支援 Invariant TSC,可安全跨核心。建議 SetThreadAffinityMask 綁定單核心。
睡眠/休眠系統睡眠期間 TSC 不計數,喚醒後數值不連續。長時間測量需配合 QueryPerformanceCounter 修正。
虛擬機Hypervisor 可能虛擬化 TSC,精度與頻率不可信。生產環境建議改用 QueryPerformanceCounter(QPC)。
編譯器內建MSVC/GCC/Clang 提供 __rdtsc() / __builtin_ia32_rdtsc(),優先使用內建函式替代內嵌組語。
序列化Out-of-order 執行可能導致 RDTSC 提前/延後。嚴格測量需加 CPUID 序列化(RDTSCP 指令隱含序列化)。

現代替代方案

  • QueryPerformanceCounter / QueryPerformanceFrequency:OS 提供、跨平台(Windows)、自動處理 TSC 虛擬化/睡眠修正,精度通常 < 100 ns。
  • std::chrono::high_resolution_clock(C++11):C++ 標準介面,Windows 實作基於 QPC。
  • Linux:clock_gettime(CLOCK_MONOTONIC_RAW) 或 RDTSC(同樣需注意 TSC 同步)。

結語

KTimer 展示了「貼近硬體」的極致計時技術,適合微基準測試、效能計數器開發。
一般應用開發請優先使用 std::chrono 或 QPC,兼具可攜性與正確性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved