c++ - 非英特尔编译器的 mkl_get_clocks_frequency() 等价物

标签 c++ c clock rdtsc

我在 Intel 编译器中使用 _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 值在最好的情况下完全没有用,在最坏的情况下会产生微妙的误导。

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

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

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

关于c++ - 非英特尔编译器的 mkl_get_clocks_frequency() 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29740239/

相关文章:

c++ - 如何布局程序?

C 和 Linux : Reusing a closed socket/Alternatives

c - WINAPI:按 NT 名称获取设备列表

c - C MIPS 环境中延迟 1 微秒

android - android 开发者可以访问系统时钟/闹钟应用程序吗?

C++ 复制构造函数和运算符

c++ - 为 STL 映射 : "cannot bind lvalue" 重载 << 和 >>

c++ - C 与 C++ 为什么这个宏不扩展为常量?

c - 用 C 编写的简单程序计算不正确的面积和周长

python - time.time() 在重复调用中漂移