我_rdtsc()
在英特尔编译器中使用来获取时间戳计数器。我使用_rdtsc()
,mkl_get_clocks_frequency()
将时间戳计数器读数转换为秒。它们都特定于英特尔编译器。
虽然,我在使用内联汇编的 GNU 编译器上有一个等价物,_rdtsc()
但对于mkl_get_clocks_frequency()
.
如何以便携式方式估计 CPU 时钟频率?
我会给你一个不回答的。抱歉,但据我所知,对此没有好的答案。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 或其他一些时间同步机制,您还将获得更接近实际秒数的时钟频率,因为它们还跟踪您作为应用程序不可能知道的长期和短期频率漂移。