我在英特尔编译器中使用_rdtsc()
获取时间戳计数器。我将_rdtsc()
与mkl_get_clocks_frequency()
结合使用,将时间戳计数器读数转换为秒。它们都是英特尔编译器特有的。
虽然我在使用内联汇编的GNU编译器上有_rdtsc()
,但mkl_get_clocks_frequency()
却没有。
如何以便携方式估算CPU时钟频率?
答案 0 :(得分: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或其他时间同步机制,您还可以获得更接近实际秒数的时钟频率,因为它们还可以跟踪您作为应用程序无法知道的长期和短期频率漂移。
答案 1 :(得分:1)
你不能这样做,如果你这样做,那就毫无意义,如Art's answer中所述。
在Linux上,您可能会解析/proc/cpuinfo
以获取某些信息(在解析时可能会出错),以及某些CPU频率。但这仍然毫无意义。
在Linux上,您应该阅读time(7),并且实际上使用clock_gettime(2),这可以快速运行,这要归功于vdso(7)技术。
使用符合C ++ 11标准的编译器&实施(即libstdc++
),您可以使用<chrono>
POCO框架库(包含多个操作系统)有一些计时器支持。