我需要更多关于您的代码的知识,但让我强调一下 MSDN 中的一些内容:
计算增量时,[来自 QueryPerformanceCounter] 的值应该是clamped确保计时值中的任何错误都不会导致崩溃或与时间相关的计算不稳定。
尤其是这个:
使用 Windows API SetThreadAffinityMask 将单个线程设置为保留在单个处理器上...虽然 QueryPerformanceCounter 和 QueryPerformanceFrequency 通常会针对多个处理器进行调整,BIOS 或驱动程序中的错误可能会导致这些例程返回不同的值当线程从一个处理器移动到另一个处理器时。因此,最好将线程保留在单个处理器上。
你的情况might利用其中之一bugs。简而言之:
- 您应该始终从一个线程查询时间戳(设置相同的 CPU 关联性以确保它不会更改)并从任何其他线程读取该值(只是一种互锁读取,不需要花哨的同步)。
- 限制计算出的增量(至少确保它不是负数)...
Notes:
QueryPerformanceCounter()
如果可能的话,使用 TSC(参见MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx)。从 Windows 7 到 Windows 8,同步 TSC 的算法(如果可用并且在您的情况下应该如此)发生了很大变化,但请注意:
随着多核/超线程 CPU、具有多个 CPU 的系统和休眠操作系统的出现,不能依赖 TSC 提供准确的结果 — 除非非常小心地纠正可能的缺陷:滴答率以及是否所有内核(处理器)在其计时寄存器中都具有相同的值。不保证单个主板上多个 CPU 的时间戳计数器会同步。所以,程序只有限制自己在一个特定的CPU上运行才能得到可靠的结果.
然后,即使理论上 QPC 是单调的,您也必须始终从同一线程调用它以确保这一点。
另请注意:如果同步是通过软件进行的,您可以从英特尔文档中读到:
...软件可能很难以某种方式做到这一点,而不是确保所有逻辑处理器在给定时间点具有相同的 TSC 值...
Edit:如果您的应用程序是多线程的,并且您不能(或不想)设置 CPU 关联性(特别是如果您需要精确的时间戳,但代价是线程之间的值不同步),那么您可以使用GetSystemTimePreciseAsFileTime()
在 Win8(或更高版本)上运行并回退到timeGetTime()
对于 Win7(将粒度设置为 1 毫秒后)timeBeginPeriod(1)
并假设 1 ms 分辨率就足够了)。非常有趣的读物:Windows 时间戳项目 http://www.windowstimestamp.com/description.
Edit 2: OP直接建议!如果适用(因为它是系统设置,而不是应用程序的本地设置),这可能是一个简单的解决方法。您可以使用 bcdedit 强制 QPC 使用 HPET 而不是 TSC(请参阅MSDN https://msdn.microsoft.com/en-us/library/windows/hardware/ff542202(v=vs.85).aspx)。延迟和分辨率应该更差,但本质上是这样safe从上述问题来看。