std::system_clock 和 std::steady_clock 之间的区别?
Difference between std::system_clock and std::steady_clock?
std::system_clock
和std::steady_clock
有什么区别?(说明不同结果/行为的示例案例会很棒)。
如果我的目标是精确测量函数的执行时间(如基准测试),那么std::system_clock
、std::steady_clock
和std::high_resolution_clock
之间的最佳选择是什么?
从 N3376
:20.11.7.1 [时间-时钟.系统]/1:
类
system_clock
的对象表示系统范围的实时时钟中的挂钟时间。
20.11.7.2 [时间.时钟.稳定]/1:
类
steady_clock
的对象表示时钟,其time_point
值永远不会随着物理时间的推进而减少,并且time_point
的值相对于实时以稳定的速率前进。也就是说,时钟可能无法调整。
20.11.7.3 [时间.时钟.雇用]/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
,因为你的平台很可能使用高分辨率计时器(例如QueryPerformanceCounter
在Windows上)的时钟。但是,如果您正在进行基准测试,则确实应该考虑使用特定于平台的计时器进行基准测试,因为不同的平台处理方式不同。例如,某些平台可能会为您提供一些方法来确定程序所需的实际时钟周期数(独立于在同一CPU上运行的其他进程)。更好的是,使用真正的分析器并使用它。
比利根据我完全同意的ISO C++标准提供了一个很好的答案。然而,故事还有另一面——现实生活。现在看来,在流行编译器的实现中,这些时钟之间真的没有区别:
海湾合作委员会 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官方时钟接口,并等待实现赶上。这比直接在代码中使用特定于操作系统的 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
的手册页并修改上面的代码即可。
GCC 5.3.0 实现
C++ stdlib 在 GCC 源代码中:
high_resolution_clock
是system_clock
的别名system_clock
转发到以下第一个可用的:clock_gettime(CLOCK_REALTIME, ...)
gettimeofday
time
steady_clock
转发到以下第一个可用的选项:clock_gettime(CLOCK_MONOTONIC, ...)
system_clock
然后CLOCK_REALTIME
与CLOCK_MONOTONIC
解释在:CLOCK_REALTIME和CLOCK_MONOTONIC之间的区别?
霍华德·欣南特(Howard Hinnant)关于时间的相关讨论,chrono
的作者:
不要使用high_resolution_clock
,因为它是其中之一的别名:
system_clock
:它就像一个普通的时钟,用于时间/日期相关的东西steady_clock
:它就像一个秒表,用它来计时。
也许,最显着的区别是std::chrono:system_clock
的起点是1.1.1970,即所谓的UNIX纪元。 另一方面,std::chrono::steady_clock
通常是PC的启动时间,它最适合测量间隔。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- IBM AIX std::clock()?
- 为什么常量CLOCKS_PER_SEC不需要用 std:: 命名,但 <ctime> clock() 和 clock_t 可以呢?
- std::clock() and CLOCKS_PER_SEC
- 测量' std::clock() '的分辨率
- CLOCKS_PER_SEC与std::clock()的结果不匹配
- std::clock()在Windows、Mac和Linux上可靠吗?