std :: system_clock和std :: steady_clock之间的区别?

时间:2012-11-07 04:48:41

标签: c++ c++11 timer chrono

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

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

5 个答案:

答案 0 :(得分:61)

来自N3376:

20.11.7.1 [time.clock.system] / 1:

  

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

20.11.7.2 [time.clock.steady] / 1:

  

steady_clock的对象表示time_point的值随着物理时间的推移而永远不会减少的时钟,time_point的值相对于实时以稳定的速率前进。也就是说,时钟可能无法调整。

20.11.7.3 [time.clock.hires] / 1:

  

high_resolution_clock的对象表示具有最短刻度周期的时钟。 high_resolution_clock可能是system_clocksteady_clock的同义词。

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

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

  

在表59中,C1C2表示时钟类型。 t1t2C1::now()返回的值,其中呼叫返回t1在呼叫返回t2之前发生,并且这两个呼叫都发生在C1::time_point::max()之前}。 [注意:这意味着C1没有在t1t2之间徘徊。 - 后注]

     

表达:C1::is_steady
  退货:const bool
  操作语义:true如果t1 <= t2始终为真且时钟滴答之间的时间不变,则为false

这就是他们的差异所有标准。

如果您想进行基准测试,最好的选择可能是std::high_resolution_clock,因为您的平台很可能会为此时钟使用高分辨率计时器(例如Windows上为QueryPerformanceCounter)。但是,如果您正在进行基准测试,则应该考虑使用特定于平台的计时器作为基准测试,因为不同的平台会以不同的方式处理这种情况例如,某些平台可能会为您提供一些方法来确定程序所需的实际时钟周期数(与在同一CPU上运行的其他进程无关)。更好的是,抓住真实的探查器并使用它。

答案 1 :(得分:45)

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

gcc 4.8:

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

Visual Studio 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;

如果是gcc,您可以通过选中is_steady来检查您是否处理稳定的时钟,并相应地采取行动。然而VS2012似乎在这里作弊: - )

如果您需要高精度时钟,我建议您现在编写符合C ++ 11官方时钟接口的自己的时钟,并等待实现赶上。与在代码中直接使用特定于OS的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()));
  }
};

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

答案 2 :(得分:14)

GCC 5.3.0实施

C ++ stdlib在GCC源代码中:

  • high_resolution_clockC->Draw();
  • 的别名
  • system_clock转发到以下第一个可用的内容:
    • system_clock
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
  • steady_clock转发到以下第一个可用的内容:
    • time
    • clock_gettime(CLOCK_MONOTONIC, ...)

然后在Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?

解释system_clock vs CLOCK_REALTIME

答案 3 :(得分:2)

Relevant talk about chrono by Howard Hinnantchrono的作者:

请勿使用high_resolution_clock,因为它是其中之一的别名:

  • system_clock:就像一个普通的时钟,用于与时间/日期相关的事情
  • steady_clock:就像秒表,用于计时。

答案 4 :(得分:1)

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