std::chrono::high_resolution_clock 基于帧定时器

std::chrono::high_resolution_clock based frame timer

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

    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 neveris_steady == true。这实际上不是必需的,但除非您的计算机有一个保持 完美 时间的时钟,否则它需要偶尔调整以将其设置为正确的时间。而一个可以调整的时钟必须有is_steady == false.

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

using frame_clock = std::chrono::steady_clock;

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

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

是的,你应该担心。 high_resolution_clock 是实现定义的。不要让工具pick,直接用steady_clock就可以了

Howard Hinnant 写了一篇很棒的文章 and

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