【问题标题】:Time running backwards with QueryPerformanceCounter()使用 QueryPerformanceCounter() 倒计时
【发布时间】:2014-12-11 09:20:48
【问题描述】:

我在this post 中找到了有关使用 QueryPerformanceCounter 的有用信息,但我遇到了一个尚未找到答案的问题。

我正在为 Windows CE 6.0 开发一个应用程序,并且需要 GetTickCount 可以提供的更好的分辨率。这就是我选择 QueryPerformanceCounter 函数的原因。

我观察到我得到的计数器值来回移动。虽然它不是最终的应用程序,但这个小例子说明了这个问题:

int i;
BOOL bRet;
LARGE_INTEGER liCounter;


for ( i = 0; i < 100; i++)
{
    bRet = QueryPerformanceCounter(&liCounter);
    if(bRet)
    {
        printf("Counter Value: %llu \n", liCounter.QuadPart);
    }

}

它打印一系列 100 个计数器值,这些值预计是递增的。但是,有一些计数器值相对于先前的值递减。例如:

...

计数器值:6536266821

计数器值:6536266262

计数器值:6536266604

...

这种行为是有问题的,因为在最终应用程序中执行 (endCounterValue-startCoutnerValue) 类型操作,并且在相同情况下发现负时间间隔。

我已阅读 (here) 在使用多核平台时会发现此问题。但是,情况并非如此,因为 Windows CE 6.0 不支持多核处理。

任何帮助找到发生这种情况的原因和/或任何避免此问题的解决方法将不胜感激。

[编辑]

我编辑问题以包含更多信息:

更长的连续读取列表(与上面的列表不同):

计数器值:15234261579

计数器值:15234261594

计数器值:15234261609

计数器值:15234261624

计数器值:15234261640

计数器值:15234261064

计数器值:15234261079

计数器值:15234261094

计数器值:15234261109

计数器值:15234261125

计数器值:15234261140

计数器值:15234261155

计数器值:15234261170

计数器值:15234261185

计数器值:15234261201

计数器值:15234261216

计数器值:15234261231

计数器值:15234261246

在硬件方面,使用的是 Intel Celeron 1047UE 处理器和 HM76 芯片组。

调用 QueryPerformanceFrequency 时,读取 1.19MHz 频率。

【问题讨论】:

  • 如果结果小于前一个,则忽略该结果。另外:msdn.microsoft.com/en-us/library/windows/desktop/…
  • 如果我忽略结果,我将丢失该间隔的时间数据。我必须防止这种情况发生。
  • 闻起来像 BSP 错误。您可能需要就此联系您的设备/BSP 供应商。

标签: c++ timer embedded windows-ce performancecounter


【解决方案1】:

QueryPerformanceCounter 导致 OAL(BSP 的一部分)内部调用,其中系统中可用的最高分辨率渐进计数器应用于返回 64 位值。 看起来该特定 BSP 存在问题。 在 x86 上,硬件计时器的数量是有限的,可能是某些驱动程序正在使用 QueryPerformanceCounter 使用的计数器来获得分辨率小于 1 毫秒的计时器。似乎该值被重新设置然后继续增加,这可能是由于驱动程序为自己设置了一个计时器(可能只使用了计时器寄存器的低 32 位部分)。 如果您有 BSP 的源代码,您可以搜索 OEMQueryPerformanceCounter 实现,检查正在使用的寄存器并检查 BSP 的其他组件是否正在访问它们(或其他可能影响其操作性的寄存器)。

【讨论】:

    【解决方案2】:

    计数器值:6536266821

    计数器值:6536266262

    计数器值:6536266604

    即使第三次读取也比第一次小!但这里的相关性是什么?您应该使用QueryPerformanceFrequency() 阅读性能计数器频率,以研究几百个计数的差异实际上意味着什么。对于 MHz 范围内的频率,这仍然比毫秒要好得多。能否提供更长的QueryPerformanceCounter()连续读取列表

    您还应该提供有关硬件的更多详细信息。性能计数器使用什么资源? Acquiring high-resolution time stamps 可以帮助您获得更详细的视图。

    考虑到循环的线性行为,您可以绘制值与时间的关系图。这可能会具体化问题。它还可以允许建立拒绝/插值方案。

    【讨论】:

    • 感谢您的回答。我已编辑问题以包含更多信息
    • 1.19MHz 通过 QueryPerformanceFrequency 读取。举个例子,400 次计数为 0.335 毫秒。在最终应用程序中,执行给定函数所需的时间是通过进行 (endCounterValue - startCounterValue) 类型操作来测量的。因此,即使向后跳跃“小”,这种跳跃也是不可接受的,因为出现了负时间间隔。
    • 1.19 MHz 是 8253 定时器芯片的签名。你有考虑过使用 cpu TSC 吗?
    • 你是对的,看来 QueryPerformanceCounter 正在使用 8253 计时器或类似的。我尝试通过读取 TSC 寄存器来测量时间,这工作正常。谢谢你的建议。但是我仍然不明白为什么在使用 8253 定时器芯片时计数器值有时会向后跳。对此有什么想法吗?
    猜你喜欢
    • 2013-03-17
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    • 2016-03-25
    • 1970-01-01
    相关资源
    最近更新 更多