【问题标题】:CPU clock frequency and thus QueryPerformanceCounter wrong?CPU时钟频率和QueryPerformanceCounter错误?
【发布时间】:2009-03-13 20:28:27
【问题描述】:

我正在使用 QueryPerformanceCounter 来计时一些代码。当代码开始报告明显错误的时间时,我感到震惊。要将 QPC 的结果转换为“实时”时间,您需要除以 QueryPerformanceFrequency 返回的频率,因此经过的时间为:

时间 = (QPC.end - QPC.start)/QPF

重启后,QPF 频率从 2.7 GHz 变为 4.1 GHz。我不认为实际的硬件频率发生了变化,因为运行程序的挂钟时间没有变化,尽管使用 QPC 报告的时间确实发生了变化(下降了 2.7/4.1)。

我的电脑->属性显示:

英特尔(R) 奔腾(R) 4 CPU 2.80 GHz; 4.11GHz; 1.99 GB 内存;物理地址扩展

除此之外,系统似乎工作正常。

我将尝试重新启动以查看问题是否解决,但我担心这些关键性能计数器可能会在没有警告的情况下失效。

更新:

虽然我很欣赏答案,尤其是链接,但我没有受影响的芯片组之一,也没有会自行变化的 CPU 时钟。根据我的阅读,QPC 和 QPF 基于 PCI 总线中的计时器,不受 CPU 时钟变化的影响。在我的情况下,奇怪的是 QPF 报告的 FREQUENCY 更改为不正确的值,并且这个更改的频率也在 MyComputer -> Properties 中报告,我当然没有写。

重新启动解决了我的问题(QPF 现在报告了正确的频率),但我假设如果您计划使用 QPC/QPF,您应该在信任它之前针对另一个计时器对其进行验证。

【问题讨论】:

  • QPC 和 QPF 是出了名的不可靠,MSDN 文档故意误导(MS 声称如果值错误,那是 BIOS 制造商的错,同时仍然声称事情是可靠的......但是我敢肯定,如果因此出现问题,用户会责怪你,而不是 BIOS 制造商)

标签: timer


【解决方案1】:

显然在某些芯片组上存在带有 QPC 的已知 issue,因此您可能需要确保您没有这些芯片组。此外,一些双核 AMD 也可能导致problem。请参阅 sebbbi 的第二篇文章,他在其中指出:

QueryPerformanceCounter() 和 QueryPerformanceFrequency() 提供一个 更好的分辨率,但有 不同的问题。例如在 Windows XP,所有 AMD Athlon X2 双 核心 CPU 返回任何一个的 PC 核心“随机”(PC有时 向后跳一点),除非你 专门安装AMD双核驱动 包来解决这个问题。我们没有 注意到任何其他双核CPU 有类似的问题(p4 dual、p4 ht、 core2 dual, core2 quad, phenom quad)。

来自这个answer

【讨论】:

  • 绝对是个问题,但恐怕不是他的问题——他在英特尔。我把钱赌在 SpeedStep 咬了他。
  • 哈!我有这个问题。很烦人。
【解决方案2】:

您应该始终预计任何支持 SpeedStepCool'n'Quiet 等技术的 CPU 上的核心频率都会发生变化。挂墙时间不受影响,它使用RTC。您可能应该停止使用性能计数器,除非您可以容忍几(5-50)毫秒的偶尔相位调整,并且愿意执行一些数学运算以便通过连续或定期重新规范化您的性能计数器值基于报告的性能计数器频率和 RTC 低分辨率时间(您可以按需执行此操作,也可以从高分辨率计时器异步执行此操作,具体取决于您的应用程序的最终需求。)

【讨论】:

    【解决方案3】:

    您可以尝试使用 .NET 中的 Stopwatch 类,它可以帮助您解决问题,因为它从所有这些低级的东西中抽象出来。

    使用 IsHighResolution 属性查看计时器是否基于高分辨率性能计数器。

    注意:在多处理器计算机上,它 哪个处理器无关紧要 线程继续运行。然而,由于 BIOS 或硬件中的错误 抽象层(HAL),可以得到 不同的时序结果不同 处理器。指定处理器 线程的亲和力,使用 ProcessThread..::.ProcessorAffinity 方法。

    【讨论】:

      【解决方案4】:

      只是在黑暗中拍摄。

      在我的家用电脑上,我曾经在 BIOS 中启用了“AI NOS”或类似的东西。我怀疑这搞砸了 QueryPerformanceCounter/QueryPerformanceFrequency API,因为尽管系统时钟以正常速率运行,并且正常应用程序运行完美,但所有全屏 3D 游戏的运行速度都太快了大约 10-15%,例如,导致相邻的对话行在游戏中互相绊倒。

      【讨论】:

        【解决方案5】:

        恐怕您在使用 QueryPerformance* 时不能说“我不应该有这个问题” - 虽然文档指出 QueryPerformanceFrequency 返回的值是恒定的,但实际实验表明它确实不是t.

        但是,您也不希望每次调用 QPC 时都调用 QPF。在实践中,我们发现周期性地(在我们的例子中是每秒一次)调用 QPF 来获得一个新的值可以使定时器保持足够好的同步以进行可靠的分析。

        正如已经指出的那样,您需要将所有 QPC 调用保留在单个处理器上以获得一致的结果。虽然这对于分析目的可能无关紧要(因为您可以只使用 ProcessorAffinity 将线程锁定到单个 CPU 上),但您不想为作为适当多线程应用程序的一部分运行的计时执行此操作(因为那时你冒着将一个辛苦工作的线程锁定到一个繁忙的 CPU 的风险)。

        特别是不要随意锁定到 CPU 0,因为您可以保证其他一些编码错误的应用程序也这样做了,然后两个应用程序将在 CPU 0 上争夺 CPU 时间,而 CPU 1(或 2 或 3)就坐闲。从一组可用的 CPU 中随机选择,您至少有机会避免被锁定到过载的 CPU。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-15
          • 1970-01-01
          • 2019-02-09
          • 1970-01-01
          相关资源
          最近更新 更多