基于 std::chrono::high_resolution_clock 的帧计时器

问题描述

多年来,我一直在为帧定时器使用以下时钟定义:

    using frame_clock = std::conditional_t<
        std::chrono::high_resolution_clock::is_steady,std::chrono::high_resolution_clock,std::chrono::steady_clock>;

换句话说,我想要一个使用尽可能高的分辨率定义的时钟,但它必须单调递增。请注意,MSVC 当前使用以下别名来定义 std::chrono::high_resolution_clock

    using high_resolution_clock = steady_clock;

因此,在 MSVC 上,我定义的别名将仅使用 std::chrono::steady_clock。对于 libstdc++ 和 libc++,这不一定是正确的,因此使用别名。

最近,我在这里偶然发现了一个脚注:https://en.cppreference.com/w/cpp/chrono/high_resolution_clock

请注意,cppreference 明确不鼓励使用 std::chrono::high_resolution_clock。他们的基本原理是时钟因实现而异……但对于 std::chrono::steady_clockstd::chrono::system_clock 来说,情况不也是如此吗?例如,我无法找到任何保证时钟之间的时钟周期必须以特定单位表示的内容。事实上,我知道这是设计

我的问题是,在使用 std::chrono::high_resolution_clock 这么多年之后(对于帧计时器和基准测试),我应该比现在更担心吗?即使在这个网站上,我也看到许多使用 std::chrono::high_resolution_clock 的建议,尽管这个脚注是这样说的。对这种差异的任何进一步见解,或可能导致问题的示例,将不胜感激。

解决方法

您所阅读的内容基本上是我过去几年一直在提供的建议。

并不是说 high_resolution_clock 是危险的。只是它比较无用。这是因为它总是别名为 system_clocksteady_clock。因此,您不妨选择 system_clocksteady_clock,这样您就知道自己得到的是哪一个。

steady_clock 总是is_steady == true。这是一个要求。另外system_clock 从不is_steady == true。这实际上不是必需的,但除非您的计算机有一个保持完美时间的时钟,否则它需要偶尔调整以将其设置为正确的时间。而一个可以调整的时钟必须有is_steady == false

您的 frame_clock 别名只是一种奇特的说法:

using frame_clock = std::chrono::steady_clock;
,

出于实际目的,您只有 3 个选择:

  • 为了实时,您唯一的选择是 std::system_clock(如果您想留在 C++ 中,操作系统级别的例程确实存在)
  • 对于测量间隔,如果您想留在 C++ 中,则必须使用 std::steady_clock。没有任何实现可以具有比 std::steady_clock
  • 更高的分辨率的稳定时钟
  • 如果您急于牺牲 C++ 一致性,则上述的可行替代方案是直接使用 TSC 计数器。这是人们所能看到的最高分辨率,也是使用速度最快的。缺点是,如果您想测量时间单位而不是周期,则必须使用 CPU 周期率将周期转换为秒。
,

是的,你应该担心。 high_resolution_clock 是实现定义的。不要让实现选择,直接使用 steady_clock

Howard Hinnant 写了很棒的comparison between steady and system clockswishes he had never added high_resolution_clock in the first place

和以前一样,坚持直接使用 std::chrono::steady_clock 而不是让实现选择。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...