2008年2月20日 星期三

[程式設計] RDTSC -- CPU 測速

因為工作上的需要, 在我的舊資料中找到 2004 年 寫的 RDTSC.EXE, 可以用來在 DOS 底下測量 CPU 時脈。

.

RDTSC 讀的是 CPU 內部的計數器 (counter), 這個計數器會隨著 CPU 的每一個時脈 (clock) 遞增, 所以將 RDTSC 與系統時間 (RTC, real time clock) 互相比對, 即可得知 CPU 時脈。此外, RDTSC 也可以拿來作高精度計時, 當年我就量過 印表機埠 (printer port) 在 SPP 模式底下的每次 I/O 動作大約要 2 us。

Pentium (含) 以後的 CPU 都支援 RDTSC, 而如果編譯器 (complier) 沒有支援時, 可用機械碼 0F31 代替, 再從 EAX, EDX (32 位元暫存器) 取回結果。此外, 純 DOS 底下的一般編譯器 (例如: Turbo C, Turbo Pascal ... 等) 不見得有支援 32 位元的暫存器, 可改用 Symantec C, Watcom C, Dev Pascal ... 等

.

此外, CpuSpeed.exe (CPU Speed - PHP, or Dos App, littleblackdog.com, 2003-03) 也可以測出 CPU 時脈, 但一時間找不到下載連結 ...

.

RDTSC.EXE 使用方式如下,

  • 將RDTSC.exe 與 CWSDPMI.exe 放在 DOS 開機底下的同一個子目錄
  • 執行 RDTSC.exe
    (不需要執行CWSDPMI.exe, 但如果缺少這個檔案, 則會出現 no DPMI 的錯誤)clip_image001

虛擬86模式 (中文 Wiki)

DPMI : DOS Protected Mode Interface - Wikipedia, the free encyclopedia

.

執行結果, (Virtual PC 底下 DOS 執行的擷圖)

  • 會先跑一次 20 cycle 然後再跑 2000 秒, 也可以按 ESC 結束
  • 右欄顯示『迴歸』計算出來的 CPU 頻率
    (在 Virtual PC 底下看到和 NB 實際一樣是 1.6G)
  • 當時用的似乎是 dev-Pascal (待查, http://www.bloodshed.net/devpascal.html ),
    如果確認之前如何compile, 則可以修改程式
    clip_image002
    clip_image003
    clip_image004

.

程式碼, (節錄)

....
type
    TTSC = comp;       { 8-byte (64-bit) long int }
    TCompHalf = record
        Lo, Hi: Longint;
    end;

Function GetTSC: TTSC; {$ifdef myUseInline} inline; {$endif} {assembler;}
var temp: TTSC;
Begin
    asm
            db $0F;
            db $31;
            mov TCompHalf(temp).Lo, EAX;
            mov TCompHalf(temp).Hi, EDX;
    end;
    GetTSC := temp;
end;

....

var
....

    Tsc0, Tsc1, Tsc2: TTSC;
    myT, myT0: TSystemTime;

begin

....
    Tsc0 := GetTsc;
    GetLocalTime(myT);
    t00 := TotalSec(myT); 
....

    while true do begin
....
        Tsc1 := GetTsc;
        GetLocalTime(myT);
        t1 := TotalSec(myT);
....
    end;
....
end.

.

其他範例程式 :

.

相關資料 :

00DE22B9   0FA2             CPUID

00DE22BB   0F31             RDTSC

00DE22BD   2B0424           SUB EAX,DWORD PTR SS:[ESP]

00DE22C0   83C4 04          ADD ESP,4

00DE22C3   3D 00000E00      CMP EAX,0E0000

00DE22C8   77 03            JA SHORT 0x90.00DE22CD

- 簡 - [ 轉為繁體網頁 ]

000012E7: 0F31 rdtsc 000012E9: 668BD8 mov ebx,eax ... This example assumes the system has booted DOS. ... mov ah, 09h ; Execute DOS print function ...
expert.csdn.net/Handler.ashx?id=3727239 - 63k - 頁庫存檔 - 類似網頁 - 加入筆記本

- 簡 - [ 轉為繁體網頁 ]

利用rdtsc 彙編指令可以得到CPU 內部定時器的值, 每經過一個CPU 週期, 這個定時器就加一。 如果在一段時間內數得CPU 的週期數, CPU工作頻率= 週期數/ 時間 ...
www.cppfans.com/articles/system/cpuspd_usdly.asp - 13k -

- 簡 - [ 轉為繁體網頁 ]

回覆於2005-10-30 21:17:46 得分0. inline unsigned __int64 GetCycleCount() { __asm _emit 0x0F __asm _emit 0x31 } 這個函數就是RDTSC,0f31是RDTSC的機器碼Top ...
topic.csdn.net/t/20051030/20/4360076.html - 26k - 頁庫存檔 - 類似網頁 - 加入筆記本

.

0 意見:

發表您的回應

張貼留言