6

時間を測定するために使用できるx86命令を知っている人はいますか?タスクスイッチにつながるタイマーはソフトウェアでアクセスできますか?

4

3 に答える 3

12

x86 プラットフォームで時間を測定する方法:

  • リアルタイム クロック - OS の時刻と日付のソース。1 秒の精度。絶対時間の測定に使用できる標準 PC の唯一のタイム ソース。

  • 8254 カウンター/タイマー- PC の黎明期からマザーボードに搭載されている標準のカウンター/タイマー チップ (現在はチップセット内の機能ブロック)。これは、ほとんどの古い OS でタスク切り替えを行うタイマー割り込みである IRQ0 の従来のソースです。

  • RDTSC アセンブリ命令 - CPU クロック サイクルをカウントします。使用法の詳細については、Anon ymous が投稿した回答を参照してください。x86 のタイム ソースとしては、ほぼ最高レベルの精度です。ただし、精度には問題があります。また、アセンブリで記述している場合に最も便利なオプションです。

  • RDTSCP アセンブリ命令 - RDTSC に似ていますが、シリアル化されているため、RDTSC の精度の問題がいくつか解決されています。最新のプロセッサでのみ見つかります。

  • HPET - PC の Core Duo 時代に導入されました。由緒ある 8254 の代替となることが意図されています。最新の OS は、タスク スケジューリング割り込みとしてこれを使用します (Vista 以降)。

  • チップセットの独自タイマー - 一部のチップセットには、電源管理およびマルチメディア機能用の特別なタイマーが組み込まれています。汎用 PC ではなく、機能が固定された組み込みシステムを扱っていると仮定すると、これらを独自のアプリケーションに使用できる場合があります。

OS やハードウェアによっては、これらのオプションのすべてが利用できるわけではないことに注意してください。最新の OS (Windows、Linux) で実行している場合、8254/HPET は独自のタイミング ニーズに合わせて制御されるため、それらは使用できなくなります。

最新のオペレーティング システムでは、通常、OS が提供するタイミング関数を使用するのが最適です。OS 開発者は、使用しようとした場合に自分で遭遇する多くの問題をおそらく解決してきました。(OS によって複数のタイミング関数が提供される場合があることに注意してください。アプリケーションに適したものを選択してください。)

于 2012-09-04T13:00:07.917 に答える
2

rdtsc現在価値から前の値を差し引くだけで、時間差を計算できます。

プロセッサのタイムスタンプカウンタ(64ビットMSR)の現在の値をEDX:EAXレジスタにロードします。EDXレジスタにはMSRの上位32ビットがロードされ、EAXレジスタには下位32ビットがロードされます。(Intel 64アーキテクチャーをサポートするプロセッサーでは、RAXとRDXのそれぞれの上位32ビットがクリアされます。)

これは、この命令を実装するCコードです:-

unsigned long long int rdtsc(void)
{
   unsigned long long int x;
   unsigned a, d;

   __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));

   return ((unsigned long long)a) | (((unsigned long long)d) << 32);;
}
于 2012-09-01T17:07:42.983 に答える
0

これを行う FORTRAN 呼び出し可能ルーチンを次に示します。

アセンブラ命令 RDTSC は、年のドットからの CPU クロック カウント数である 64 ビット整数を返します。FORTRAN に 64 ビット整数がある場合、引数 KOUNT は INTEGER*8 として宣言されます。それ以外の場合は、2 つの 32 ビット INTEGER*4 の配列であると宣言します

したがって、FORTRAN プログラムで次のように記述します。

CALL TIMERR(KOUNT)

最初に KOUNT の値を保存し、最後に繰り返します。次に、2 つの 64 ビット値を減算して、経過時間を決定します。通常、時間はシステムクロックの 2^32 未満なので、下の 2 つの単語を差し引くだけです。

Cからも呼び出せますが、私はCを話せません。

; C This assembler routine looks to FORTRAN like this:
;       SUBROUTINE TIMERR(KOUNT)
;       INTEGER*4 KOUNT(2);  or INTEGER*8 KOUNT
;       ...get a 64-but system time value into KOUNT......
;       RETURN
;       END
;
.Code
_TIMERR@4: RDTSC
         Push Eax
    Push Ecx
    Push Edx
    Mov Ecx, [Esp + 16]
    Mov [Ecx], Eax
    Mov [Ecx + 4], Edx
    Pop Edx
    Pop Ecx
    Pop Eax
    Ret 4
于 2013-01-23T05:29:04.770 に答える