0

_rdtsc()在英特尔编译器中使用来获取时间戳计数器。我使用_rdtsc(),mkl_get_clocks_frequency()将时间戳计数器读数转换为秒。它们都特定于英特尔编译器。

虽然,我在使用内联汇编的 GNU 编译器上有一个等价物,_rdtsc()但对于mkl_get_clocks_frequency().

如何以便携式方式估计 CPU 时钟频率?

4

2 回答 2

2

我会给你一个不回答的。抱歉,但据我所知,对此没有好的答案。RDTSC只能在非常特定的条件下在某些 CPU 上工作,返回值在没有操作系统帮助的情况下,其解释介于困难和不可能之间,因此我怀疑没有人费心在可移植编译器/库中实现对它的支持(所有其他期望英特尔编译器)。

长话短说:

RDTSC指令有很长的语义变化历史,在应用程序中很难跟踪。较旧的 Intel 和 AMD CPU 只有 TSC 计算内部周期,这意味着在可变频率(省电模式等)下,频率可能会在不通知应用程序的情况下发生变化。频率可能在两个时间戳之间发生了多次变化,而您无法知道发生了这种情况。

某些 CPU 或 BIOS 版本可以在系统管理模式下暂停 TSC,而其他版本则不会。第一种行为意味着 TSC 对挂钟时间无用,另一种行为意味着 TSC 对基准测试无用。上次我看这个时,除了比较不同的时钟并寻找大的跳跃之外,没有其他方法可以检测到这一点。

一些 CPU 没有在系统中的多个 CPU 之间保持 TSC 和/或其频率同步。这意味着如果操作系统在 CPU 之间移动您的进程,那么您读取的 TSC 值在最好的情况下完全无用,在最坏的情况下会产生微妙的误导。

最近的趋势和稳定性承诺是拥有一个同步的定时器和同步的静态频率(这是你无法实现的,因为时钟对温度很敏感,但那是另一回事了)。我们终于可以毫无问题地稳定使用 RDTSC。

但是后来英特尔突然决定RDTSC不再是序列化指令,这又给我们扔了一个曲线球(这很可能不是一个有意识的决定,这可能只是英特尔通过说“它从未被记录为序列化”而逃避的一个错误)。这意味着如果您在代码中读取计时器两次,则第二个值可能低于第一个值。或者更糟糕的是,您进行基准测试的大部分代码实际上并未运行。新RDTSCP指令“解决”了这个问题,但你需要弄清楚哪些 CPU 实际实现了它,哪些 CPU 足够可靠RDTSC可以使用,哪些你只需要放弃并使用更好的时间源。

除此之外,您不知道您的代码是否实际在两次调用之间运行,RDTSC或者您是否在上下文切换。因此,我建议坚持使用您的操作系统提供的计时工具并测量您的进程运行的时间。那些计时工具速度较慢,但​​操作系统很可能比您能够弄清楚的更好地解决了所有这些问题。作为奖励,如果您使用 NTP 或其他一些时间同步机制,您还将获得更接近实际秒数的时钟频率,因为它们还跟踪您作为应用程序不可能知道的长期和短期频率漂移。

于 2015-04-20T07:18:11.057 回答
1

正如Art 的回答中所解释的那样,您不能以便携的方式做到这一点,如果您这样做了,那将毫无意义。

特别是在 Linux 上,您可能会解析/proc/cpuinfo以获取有关某些 CPU 频率的一些信息(在您解析它时可能是错误的)。但这仍然没有意义。

在 Linux 上,您应该阅读time(7)并实际使用能够快速运行的clock_gettime(2) ,这要归功于vdso(7)技术。

使用符合 C++11 的编译器和实现(即libstdc++),您可以使用<chrono>

POCO框架库(包装多个操作系统)具有一些计时器支持。

于 2015-04-20T08:32:58.063 回答