std::system_clock
和std::steady_clock
之间有什么区别? (说明不同结果/行为的示例案例会很棒)。
如果我的目标是精确测量函数的执行时间(如基准),那么std::system_clock
,std::steady_clock
和std::high_resolution_clock
之间的最佳选择是什么?
答案 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_clock
或steady_clock
的同义词。
例如,系统范围的时钟可能会受到夏令时等因素的影响,此时在未来的某个时刻列出的实际时间实际上可能是过去的时间。 (例如,在美国,在下降时间后退一小时,所以同一小时经历“两次”)但是,steady_clock
不允许受此类事件的影响。
在这种情况下,另一种考虑“稳定”的方法是在20.11.3 [time.clock.req] / 2表格中定义的要求:
在表59中,
C1
和C2
表示时钟类型。t1
和t2
是C1::now()
返回的值,其中呼叫返回t1
在呼叫返回t2
之前发生,并且这两个呼叫都发生在C1::time_point::max()
之前}。 [注意:这意味着C1
没有在t1
和t2
之间徘徊。 - 后注]表达:
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_clock
是C->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 Hinnant,chrono
的作者:
请勿使用high_resolution_clock
,因为它是其中之一的别名:
system_clock
:就像一个普通的时钟,用于与时间/日期相关的事情steady_clock
:就像秒表,用于计时。答案 4 :(得分:1)
也许最大的区别是std::chrono:system_clock
的起点是1.1.1970,即所谓的UNIX-epoch。
另一方面,对于std::chrono::steady_clock
,通常是PC的启动时间,它最适合用于测量间隔。