测量CPU频率(x86 / x64)

6
我正在寻找一种库,可以在32位和64位的Windows系统上准确地周期性地给出Intel和AMD处理器的CPU频率值。
这样做的目的是为了准确测量给定计算机的CPU负载。问题在于调用QueryPerformanceCounter()返回时钟滴答数(用于测量活动的持续时间),但由于SpeedStep或TurboBoost,底层CPU频率并不是恒定的。我发现有些计算机即使在BIOS中关闭了SpeedStep / TurboBoost也无法防止基于负载的CPU频率缩放。
我试图看看是否有可用的库可用于检测CPU频率变化(就像Throttlestop / CPU-Z或甚至Windows 7的Resource Monitor概述选项卡那样),以便我可以查询并保存此信息以及其他测量结果。性能计数器似乎不能提供可靠的信息,因为我有一些计算机始终返回100%的CPU频率,即使其他工具显示动态频率更改。
我搜索了这样的库,但大多数结果都是无用的小工具等。

为了得到可靠的结果,您需要直接从 CPU 读取 CPU 频率。这就是 CPU-Z 等工具的工作方式。虽然当前的 Linux/Windows 提供了一些 cpu 统计信息(如 /proc/cpuinfo),其中包含 一些 频率,但通常不考虑 turboboost/overclocking 等因素。 - Gunther Piez
3个回答

8

您可以将高分辨率计时器与时钟周期计数器结合使用,以计算当前时钟速率。在现代CPU上,可以使用此函数读取周期计数器:

static inline uint64_t get_cycles()
{
  uint64_t t;
  asm volatile ("rdtsc" : "=A"(t));
  return t;
}

注意这是每个CPU的情况,所以如果您的程序在不同的CPU之间移动,就会出现问题。如果您了解平台上的CPU固定技术,可以尝试使用这些技术。
对于高分辨率时间测量,您可以使用中的工具;这里有一个关于该主题的半有用的我的帖子

@Kerrer SB:感谢您的回答,但我无法理解您的代码——我不熟悉您在汇编位中使用的语法。这是VC++语法还是其他语法? - xxbbcc
1
@xxbbcc 这是gcc内联汇编。 - Gunther Piez
@drhirsch:谢谢你。我认为“=A”位的意思是将RDTSC的返回值存储在t中。 - xxbbcc
@xxbbcc 话虽如此,但在这里使用TSC的任何答案很可能都不起作用 - 在较新的CPU上,TSC运行的速率是固定的,并且独立于实际的CPU频率。 - Gunther Piez
@drhirsch:你知道“新一代CPU”是什么意思吗?我的问题是,我可能需要在三年以上的电脑上获取这些信息。如果在2008年左右使用了固定频率TSC,那么很可能没问题,我可以依靠它,但如果它只是最近添加的(根据我的阅读看起来是这样),那么这并不是一个解决方案。此外,在调用RDTSC时有没有办法控制检查哪个CPU? - xxbbcc
旧款Athlon X2+和第一代Core2处理器没有同步的TSC,这是某些游戏中主要时间问题的原因。之后我不确定,请自行搜索或尝试。 - Gunther Piez

1

试着专注于你想要做什么,而不是如何去做。

你的最终目标是什么?

如果你说你正在尝试“测量给定计算机上的CPU负载”,在Windows上使用“PdhOpenQuery”和“Pdh*”系列函数可能是一个好的实践。

也可以参考这个SO答案:

如何从进程内部确定CPU和内存消耗?


我也发布了一个关于性能计数器的链接,但是后来我看到问题声称这些测量结果不够好。 - Greg Inozemtsev
@friol:谢谢,但是所有的Pdh*函数都返回性能计数器信息,而这些信息都是不可靠的。SO链接对我也没有用——GetProcessTimes()返回时间持续但并没有告诉我在那段时间内CPU运行的频率。如果CPU在60毫秒时以10%的速度运行,然后在另外的60毫秒时以45%的速度运行,显然第二种负载更高,但是我会在两种情况下都得到10毫秒。 - xxbbcc
@GregInozemtsev:是的,不幸的是,“% of Maximum Frequency”给我错误的值(在我们明显有频率变化的计算机上显示为100%)。我不知道是否有其他计数器可以给我正确的数据,但我尝试过的那些都不能可靠地工作。上述计数器在我的Windows 7笔记本电脑上运行良好,但在我的一些服务器上却无法正常工作。 - xxbbcc

1
考虑查看Visual Studio中的__rdtsc内置函数(#include "intrin.h")。
这将直接通过x86/x64函数RDTSC(读取时间戳)从处理器获取时钟计数。

谢谢,其他人也建议了这个。我的理解是,即使这个指令可能受到与电源管理相关的频率变化的影响,因此它是不可靠的。我错了吗? - xxbbcc
RDTSC 返回处理器中的时钟计数器在管道中被访问时的值。如果您需要超精细时间戳控制,则需要在 RDTSC 之前执行序列化指令。此后,这是您机器上最精细的时钟计数器。 - SecurityMatt

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