6

有人知道可用于测量时间的 x86 指令吗?软件可以访问导致任务切换的计时器吗?

4

3 回答 3

12

在 x86 平台上测量时间的方法:

  • 实时时钟 - 操作系统的时间和日期来源。1 秒精度。标准 PC 中唯一可用于测量绝对时间的时间源。

  • 8254 计数器/定时器- 自 PC 诞生之初就出现在主板上的标准计数器/定时器芯片(现在是芯片组内的功能块)。这是 IRQ0 的传统来源,这是在大多数旧操作系统中执行任务切换的定时器中断。

  • RDTSC 汇编指令 - 计算 CPU 时钟周期。有关一些使用细节,请参阅 Anon ymous 发布的答案。对于 x86 上的时间源,几乎可以找到最高级别的精度。但是,它有一些准确性问题。如果您在汇编中编写,这也是最方便的选择。

  • RDTSCP 汇编指令 - 类似于 RDTSC,但已序列化,这解决了 RDTSC 的一些准确性问题。只能在最新的处理器上找到。

  • HPET - 在 PC 的 Core Duo 时代推出。旨在替代古老的 8254。现代操作系统将使用它作为他们的任务调度中断(Vista 和更高版本)

  • 芯片组中的专有定时器 - 一些芯片组具有内置的特殊定时器,用于电源管理和多媒体功能。假设您正在处理固定功能的嵌入式系统而不是通用 PC,您有时可以将这些用于您自己的应用程序。

请注意,根据您的操作系统和硬件,并非所有这些选项都可供您使用。如果您在现代操作系统(Windows、Linux)下运行,它将控制 8254/HPET 以满足其自身的时间需求,因此您将无法使用它们。

在现代操作系统下,通常最好使用操作系统提供的计时功能。如果您尝试使用它,操作系统开发人员可能已经解决了很多您自己会遇到的问题。(请注意,操作系统可能提供多种计时功能。请选择适合您应用的一种。)

于 2012-09-04T13:00:07.917 回答
2

您可以使用rdtsc.Just 从当前值中减去以前的值来计算时间差。

将处理器的时间戳计数器(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 返回一个 64 位整数,它是自年点以来的 CPU 时钟计数数。如果您的 FORTRAN 有 64 位整数,则参数 KOUNT 仅声明为 INTEGER*8。否则将其声明为两个 32 位 INTEGER*4 的数组

所以在你的 FORTRAN 程序中你写

CALL TIMERR(KOUNT)

在开始时,保存 KOUNT 的值,然后在结束时重复。然后减去两个 64 位值以确定经过的时间。我通常只费心减去两个较低的单词,因为我的时间通常少于 2^32 系统时钟

它也可以从 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 回答