Assembly 什么';在现代个人电脑中,最准确的测量时间的方法是什么?

Assembly 什么';在现代个人电脑中,最准确的测量时间的方法是什么?,assembly,timer,system,clock,irq,Assembly,Timer,System,Clock,Irq,我知道我可以使用IRQ0,这是系统计时器,但这是基于14.31818MHz的时钟,对吗?有没有更精确的方法 谢谢 编辑:有人知道Windows函数QueryPerformanceCounter使用什么吗?英特尔处理器通常通过指令提供高精度计时器信息 它的精度远高于14MHz。需要注意的是,它可能会在多核和速度步进处理器上出现问题 编辑:有更多关于这个主题的细节 1.实际频率取决于处理器,但通常是处理器频率。显然,在Nehalem处理器上,TSC以前端总线频率(133 MHz)运行。 “精确”

我知道我可以使用IRQ0,这是系统计时器,但这是基于14.31818MHz的时钟,对吗?有没有更精确的方法

谢谢


编辑:有人知道Windows函数QueryPerformanceCounter使用什么吗?

英特尔处理器通常通过指令提供高精度计时器信息

它的精度远高于14MHz。需要注意的是,它可能会在多核和速度步进处理器上出现问题

编辑:有更多关于这个主题的细节


1.实际频率取决于处理器,但通常是处理器频率。显然,在Nehalem处理器上,TSC以前端总线频率(133 MHz)运行。 “精确”和“精确”的含义不同。“地球的周长是40000.000000000公里”是精确的,但并不精确。时钟有点复杂:

  • 分辨率:滴答声之间的时间或滴答声的周期。(你可能会称之为“精确”,但我认为“分辨率”的含义更为明显。)
  • 偏差:标称和实际时钟频率之间的相对差异(ish)
  • 漂移:倾斜的变化率(由于老化、温度等)
  • 抖动:滴答计时的随机变化
  • 延迟:获取时间戳所需的时间
即使“系统定时器”(根据维基百科)运行在1.5兆赫左右,你通常会得到100到1000赫兹之间的IRQ0。您也可以从端口0x40读取两次以获取当前计数器值,但我不确定这有什么样的延迟(然后您会得到下一个中断之前的计数数,所以您需要做一些数学计算)。它也不适用于更现代的“无痒”内核

还有一些其他的高频定时器:

  • 本地APIC,基于总线频率和二次幂分频器。我找不到任何关于如何阅读它的文档(可能是I/O端口?)
  • ACPI电源管理定时器(Linux中的ACPI_pm;我想,还有/UsePMTimer Windows引导标志),根据标准,大约是3.58 MHz。IIRC,读起来有点贵
  • HPET,根据同一链路至少为10 MHz(但可以更高)。它还应该比ACPI PM定时器具有更低的延迟
  • TSC(附带警告)。几乎可以肯定,延迟最低,频率也可能最高。(但很明显,每“滴答”一声,它就会上升超过1次,因此每秒的计数不一定与分辨率相同。)
似乎假定TSC频率不变,并在从TSC未运行的睡眠状态(显然是C4或更高)醒来时调整添加到该频率的基本值。每个CPU有不同的基值,因为TSC不需要跨CPU同步。您必须付出合理的努力才能获得合理的时间戳

IIRC,Linux只选择一个时钟源(TSC,如果它正常的话,然后是HPET,然后是ACPI PM,我想)


IIRC,QueryPerformanceCounter()使用Windows认为最好的方法。它在某种程度上也取决于Windows版本(XP可能不支持HPET用于中断,所以可能也不支持HPET用于时间戳)。您可以调用QueryPerformanceFrequency()进行猜测(我得到1995030000,这可能意味着它是TSC)。

它实际上是14.31818 MHz/12=1.193181 MHz。请注意,这些是兆赫,即每秒数百万个周期,您需要什么样的精度?如果你不需要像TSC一样的精度,也许HPET就足够了?嗯,我得到的信息相互矛盾。一些消息来源说是14.31818MHz,另一些只是说“系统时钟”,现在你说是1.193181MHz。困惑的这是一个关于IIRC的问题的答案,RDTSC从奔腾开始就存在了,曾经是一个循环计数器。它是否正常取决于处理器;它是否随CPU频率变化有一些处理器标志(在Linux上,/proc/cpuinfo中的constant_tsc),但即使使用constant_tsc,它仍然会受到睡眠状态的影响。@tc:另外,它是否在不同的CPU/内核之间同步取决于处理器。