C++ std::system_clock 和 std::steady_clock 的区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13263277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:08:05  来源:igfitidea点击:

Difference between std::system_clock and std::steady_clock?

c++c++11timerchrono

提问by Vincent

What is the difference between std::system_clockand std::steady_clock? (An example case that illustrate different results/behaviours would be great).

std::system_clock和 和有std::steady_clock什么区别?(说明不同结果/行为的示例案例会很棒)。

If my goal is to precisely measure execution time of functions (like a benchmark), what would be the best choice between std::system_clock, std::steady_clockand std::high_resolution_clock?

如果我的目标是精确测量函数的执行时间(如基准),那么std::system_clock,std::steady_clock和之间的最佳选择是std::high_resolution_clock什么?

采纳答案by Billy ONeal

From N3376:

来自 N3376:

20.11.7.1 [time.clock.system]/1:

20.11.7.1 [时间.时钟.系统]/1:

Objects of class system_clockrepresent wall clock time from the system-wide realtime clock.

类的对象system_clock表示来自系统范围实时时钟的挂钟时间。

20.11.7.2 [time.clock.steady]/1:

20.11.7.2 [time.clock.steady]/1:

Objects of class steady_clockrepresent clocks for which values of time_pointnever decrease as physical time advances and for which values of time_pointadvance at a steady rate relative to real time. That is, the clock may not be adjusted.

类对象steady_clock代表时钟,其值time_point永远不会随着物理时间的前进而减少,并且其值以time_point相对于实时的稳定速率前进。也就是说,时钟可能不会被调整。

20.11.7.3 [time.clock.hires]/1:

20.11.7.3 [time.clock.hires]/1:

Objects of class high_resolution_clockrepresent clocks with the shortest tick period. high_resolution_clockmay be a synonym for system_clockor steady_clock.

类对象high_resolution_clock表示具有最短滴答周期的时钟。high_resolution_clock可能是system_clock或的同义词steady_clock

For instance, the system wide clock might be affected by something like daylight savings time, at which point the actual time listed at some point in the future can actually be a time in the past. (E.g. in the US, in the fall time moves back one hour, so the same hour is experienced "twice") However, steady_clockis not allowed to be affected by such things.

例如,系统范围的时钟可能会受到夏令时之类的影响,此时列出的未来某个时间点的实际时间实际上可能是过去的时间。(例如在美国,在下降时间后移一小时,因此同一小时经历“两次”)但是,steady_clock不允许受此类事情的影响。

Another way of thinking about "steady" in this case is in the requirements defined in the table of 20.11.3 [time.clock.req]/2:

在这种情况下,另一种考虑“稳定”的方式是在 20.11.3 [time.clock.req]/2 表中定义的要求:

In Table 59 C1and C2denote clock types. t1and t2are values returned by C1::now()where the call returning t1happens before the call returning t2and both of these calls occur before C1::time_point::max(). [ Note: this means C1did not wrap around between t1and t2. —end note ]

Expression: C1::is_steady
Returns: const bool
Operational Semantics: trueif t1 <= t2is always true and the time between clock ticks is constant, otherwise false.

在表 59 中C1C2表示时钟类型。t1t2C1::now()调用返回t1发生在调用返回之前的位置返回的值,t2并且这两个调用都发生在 之前C1::time_point::max()。[注意:这意味着C1没有在t1和之间环绕t2。——尾注]

表达式:C1::is_steady
返回:const bool
操作语义:true如果t1 <= t2始终为真,并且时钟滴答之间的时间是恒定的,否则为false

That's all the standard has on their differences.

这就是标准对它们的差异的全部内容。

If you want to do benchmarking, your best bet is probably going to be std::high_resolution_clock, because it is likely that your platform uses a high resolution timer (e.g. QueryPerformanceCounteron Windows) for this clock. However, if you're benchmarking, you should really consider using platform specific timers for your benchmark, because different platforms handle this differently. For instance, some platforms might give you some means of determining the actual number of clock ticks the program required (independent of other processes running on the same CPU). Better yet, get your hands on a real profiler and use that.

如果您想进行基准测试,您最好的选择可能是std::high_resolution_clock,因为您的平台很可能使用高分辨率计时器(例如QueryPerformanceCounter在 Windows 上)作为该时钟。但是,如果您要进行基准测试,您真的应该考虑将特定于平台的计时器用于您的基准测试,因为不同的平台对此有不同的处理方式。例如,某些平台可能会提供一些方法来确定程序所需的实际时钟滴答数(独立于在同一 CPU 上运行的其他进程)。更好的是,获得一个真正的分析器并使用它。

回答by Mateusz Pusz

Billy provided a great answer based on the ISO C++ standard that I fully agree with. However there is another side of the story - real life. It seems that right now there is really no difference between those clocks in implementation of popular compilers:

Billy 根据我完全同意的 ISO C++ 标准提供了一个很好的答案。然而,故事还有另一面——现实生活。现在看来,在流行编译器的实现中,这些时钟之间确实没有区别:

gcc 4.8:

海湾合作委员会 4.8:

#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
   ...
#else
  typedef system_clock steady_clock;
#endif
  typedef system_clock high_resolution_clock;

Visual Studio 2012:

视觉工作室 2012:

class steady_clock : public system_clock
{   // wraps monotonic clock
public:
  static const bool is_monotonic = true;    // retained
  static const bool is_steady = true;
};

typedef system_clock high_resolution_clock;

In case of gcc you can check if you deal with steady clock simply by checking is_steadyand behave accordingly. However VS2012 seems to cheat a bit here :-)

在 gcc 的情况下,您可以通过检查is_steady和相应的行为来检查您是否处理稳定时钟。然而 VS2012 在这里似乎有点作弊:-)

If you need high precision clock I recommend for now writing your own clock that conforms to C++11 official clock interface and wait for implementations to catch up. It will be much better approach than using OS specific API directly in your code. For Windows you can do it like that:

如果您需要高精度时钟,我建议您现在编写自己的符合 C++11 官方时钟接口的时钟,并等待实现赶上。与直接在代码中使用特定于操作系统的 API 相比,这将是更好的方法。对于 Windows,您可以这样做:

// Self-made Windows QueryPerformanceCounter based C++11 API compatible clock
struct qpc_clock {
  typedef std::chrono::nanoseconds                       duration;      // nanoseconds resolution
  typedef duration::rep                                  rep;
  typedef duration::period                               period;
  typedef std::chrono::time_point<qpc_clock, duration>   time_point;
  static bool is_steady;                                                // = true
  static time_point now()
  {
    if(!is_inited) {
      init();
      is_inited = true;
    }
    LARGE_INTEGER counter;
    QueryPerformanceCounter(&counter);
    return time_point(duration(static_cast<rep>((double)counter.QuadPart / frequency.QuadPart *
                                                period::den / period::num)));
  }

private:
  static bool is_inited;                                                // = false
  static LARGE_INTEGER frequency;
  static void init()
  {
    if(QueryPerformanceFrequency(&frequency) == 0)
      throw std::logic_error("QueryPerformanceCounter not supported: " + std::to_string(GetLastError()));
  }
};

For Linux it is even easier. Just read the man page of clock_gettimeand modify the code above.

对于Linux,它甚至更容易。只需阅读手册页clock_gettime并修改上面的代码即可。

回答by Silviu

Maybe, the most significant difference is the fact that the starting point of std::chrono:system_clockis the 1.1.1970, so-called UNIX-epoch. On the other side, for std::chrono::steady_clocktypically the boot time of your PC and it's most suitable for measuring intervals.

也许,最显着的区别在于起点std::chrono:system_clock是 1.1.1970,即所谓的 UNIX-epoch。另一方面,std::chrono::steady_clock通常用于PC 的启动时间,它最适合测量间隔。