Windows中高于100ns分辨率的计时器

5

我从事编程语言分析器的工作,正在寻找Windows下分辨率优于100 ns的定时器解决方案。

  • QueryPerformanceCounter应该是一个答案,但是QueryPerformanceFrequency返回的频率在Windows 10上是10 MHz,在Windows 7上甚至更低

  • GetSystemTimePreciseAsFileTime具有100 ns的间隔/步长

  • RDTSC的分辨率优于1ns,但它会随着频率而变化

我的目标分辨率至少为10 ns。

目前最好的解决方案是什么?

QueryPerformanceCounter如何实现?是否可以轻松反汇编并增加分辨率?

是否有可能直接使用RDTSC,并跟踪/中断每次频率变化?


1
运行目标数千/数百万次,然后除以运行次数?使用外部硬件定时器(如果您正在计时对外部刺激的响应时间 - “接收此输入后多长时间产生输出?”这是一个非常好的想法)? - JohnFilleau
当使用RDTSC时,平均化可能有所帮助,但如果频率不是随机变化的(由于热限制),这将无济于事。 QueryPerformanceCounter的平均化不会有太大帮助,因为最短的事件约为100纳秒。它是应该在通用硬件上运行的软件分析器,因此硬件时间也不是一个选择。 - mvorisek
2
https://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html - 0___________
你有兴趣对完成某项工作所需的时钟周期数、墙上时间(真实世界结束时间减去真实世界开始时间)或 CPU 时间(在 CPU 上执行工作的时间)进行分析吗?如果您担心动态频率缩放,那么将程序置于一百万次循环的大负载下甚至可能帮助您获得更为保守的估计。我不建议设置一百万个定时器,然后将它们相加再除以总数。我建议设置一个定时器,启动它,运行一百万次,然后停止它。如果额外的循环时间不可忽略,则添加更多工作来解决这个问题。 - JohnFilleau
1
@mvorisek “但如果频率不是随机变化的” - 不,20年前是正确的。现在它是一个稳定的频率。有关详细信息,请阅读芯片文档。 - 0___________
显示剩余6条评论
1个回答

4
如何实现 QueryPerformanceCounter
QPC计时器在HAL中的实现取决于硬件,它使用TSC、HPET、RTC、APIC、ACPI或8254定时器,具体取决于可用性。
QPC计时器的分辨率硬编码为100纳秒。但这并不重要,因为调用QPC本身需要大于100纳秒的时间。在Windows世界中,100纳秒只是非常非常短的时间。 RDTSC的分辨率优于1ns,但随着频率而变化。
实际上,自Nehalem以来TSC频率非常稳定。请参阅Intel 64架构SDM第3A卷,“17.16不变TSC”:
处理器系列以不同的方式增加时间戳计数器:
对于Pentium M处理器(系列[06H],型号[09H、0DH]);对于Pentium 4处理器、Intel Xeon处理器(系列[0FH],型号[00H、01H或02H]);以及对于P6处理器系列:时间戳计数器会随着每个内部处理器时钟周期增加。内部处理器时钟周期由当前内核时钟到总线时钟比率确定。Intel SpeedStep技术转换也可能影响处理器时钟。
对于Intel Xeon处理器(系列[0FH],型号[03H及更高型号]);对于Intel Core Solo和Intel Core Duo处理器(系列[06H],型号[0EH]);对于Intel Xeon处理器5100系列和Intel Core 2 Duo处理器(系列[06H],型号[0FH]); 对于Intel Core 2和Intel Xeon处理器(系列[06H],DisplayModel [17H]);对于Intel Atom处理器(系列[06H],DisplayModel [1CH]):时间戳计数器以恒定速率递增。该速率可能由处理器的最大核心时钟比总线时钟比设置,也可能由处理器引导时设置的最大可解决频率设置。最大可解决频率可能与处理器基础频率不同,请参阅第18.18.2节了解更多详细信息。在某些处理器上,TSC频率可能与品牌字符串中的频率不同。
较新处理器中的时间戳计数器可能支持一种增强功能,称为不变TSC。处理器对不变TSC的支持由指示。不变TSC将在所有ACPI P、C和T状态下以恒定速率运行。这是未来的体系结构行为。对于支持不变TSC的处理器,操作系统可以使用TSC进行墙上时钟计时器服务(而不是ACPI或HPET计时器)。TSC读取效率更高,不会带来环路转换或访问平台资源的开销。

因此,如果需要快速测量,您应该能够使用__rdtsc__rdtscp。您可以在启动时校准TSC频率,并确保它不依赖于CPU状态。但线程仍然可能会被抢占,因此最好多次重复测量或使用QueryThreadCycleTime(当然,这也带有自己的开销)。在实际应用中,我发现RDTSC并没有像在使用RDTSC计算系统时间中所述那样糟糕,尽管后者仍然是一个不错的阅读资料。


谢谢您的回答!我会更多地测试这些领域。FYI,QueryPerformanceCounter每次调用大约需要15纳秒。 - mvorisek
很有趣。在我上次测试的系统上,i7-7700HQ每个调用需要120纳秒。 - rustyx
1
Nehalem显然引入了TSC不停止在任何低功耗C状态的功能(Can constant non-invariant tsc change frequency across cpu states?)。您引用的文档证实,即使是Core 1和Core 2以及所有x86-64 Intel,也具有固定的TSC频率(当它在滴答时)。是的,TSC测量的是墙上时钟时间,而不是您进程的CPU时间,因为可能会发生中断和上下文切换。编程为仅在用户空间中滴答的HW perf计数器(rdpmc)可以做得更好,但这更难设置(特别是在Windows上)。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接