在现代 PC 中测量经过时间的最准确方法是什么?
我知道我可以使用 IRQ0,它是系统定时器,但这是基于 14.31818MHz 时钟的,对吗?有什么可以提供更高的精度吗?
谢谢。
编辑:有谁知道 Windows 函数 QueryPerformanceCounter 使用什么?
I know I can use IRQ0, which is the system timer, but this is based on a 14.31818MHz clock, right? Is there anything offering greater precision?
Thanks.
Edit: Does anyone know what the Windows function QueryPerformanceCounter uses?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
“精度”和“准确度”的含义不同。 “地球的周长是40000.000000000公里”是精确的,但并不准确。对于时钟来说,情况有点复杂:
即使“系统计时器”(PIT 根据维基百科)运行在 1.something MHz,您通常会在 100 到 1000 Hz 之间获得 IRQ0。 显然您也可以从端口 0x40 读取两次以获取当前计数器值,但我不确定这有什么样的延迟(然后你会得到下一次中断之前的计数,所以你需要做一些数学计算)。它也不适用于更现代的“tickless”内核。
还有一些其他高频定时器:
Darwin(即 OS X) 似乎假设 TSC 频率不会改变,并进行调整从 TSC 未运行的睡眠状态唤醒时添加的基值(显然是 C4 或更大)。每个 CPU 有不同的基值,因为 TSC 不需要在 CPU 之间同步。您必须付出合理的努力才能获得合理的时间戳。
IIRC,Linux 只是选择一个时钟源(TSC,如果它是理智的,然后是 HPET,然后是 ACPI PM,我认为)。
IIRC,QueryPerformanceCounter() 使用 Windows 认为最好的任何内容。这在一定程度上也取决于 Windows 版本(据说 XP 不支持 HPET 中断,因此大概也不支持时间戳)。您可以调用 QueryPerformanceFrequency() 进行猜测(我得到 1995030000,这可能意味着它是 TSC)。
"Precision" and "accuracy" mean different things. "The Earth's circumference is 40000.000000000 km" is precise, but not accurate. It's a bit more complicated with clocks:
Even though the "system timer" (PIT according to Wikipedia) runs at 1.something MHz, you generally get IRQ0 somewhere between 100 and 1000 Hz. Apparently you can also read from from port 0x40 twice to get the current counter value, but I'm not sure what kind of latency this has (and then you get number of counts until the next interrupt, so you need to do some math). It also doesn't work on more modern "tickless" kernels.
There are a few other high-frequency timers:
Darwin (i.e. OS X) appears to assume that the TSC frequency does not change, and adjusts the base value added to it when waking up from a sleep state where the TSC is not running (apparently C4 and greater). There's a different base value per CPU, because the TSC need not be synchronized across CPUs. You have to put in a reasonable amount of effort to get a sensible timestamp.
IIRC, Linux just picks a single clock source (TSC, if it's sane, and then HPET, and then ACPI PM, I think).
IIRC, QueryPerformanceCounter() uses whatever Windows thinks is best. It depends somewhat on Windows version too (XP supposedly doesn't support HPET for interrupts, so presumably it doesn't for timestamps either). You can call QueryPerformanceFrequency() to make a guess (I get 1995030000, which probably means it's the TSC).
英特尔处理器通常通过 rdtsc 指令提供高精度计时器信息。
它的精度远高于 14 MHz1。需要注意的是,它在多核和速度步进处理器上可能会出现问题。
编辑:这个问题有更多细节关于这个话题。
1. 实际频率取决于处理器 - 但通常是处理器频率。显然,在 Nehalem 处理器上,TSC 以前端总线频率 (133 MHz) 运行。
Intel processors usually have high precision timer information available via the rdtsc instruction.
It has much higher precision than 14 MHz¹. The caveat is that it can have issues on multi-core and speed stepping processors.
Edit: This question has a a lot more detail on this subject.
1. The actual frequency depends on the processor - but is often the processor frequency. Apparently on Nehalem processors the TSC runs at the front side bus frequency (133 MHz).