跨C ++实现的std :: chrono :: system_clock与std :: chrono :: steady_clock的精度?

时间:2019-02-18 06:53:17

标签: c++ c++17 chrono

以下程序:

#include <chrono>
#include <iostream>
#include <vector>

inline uint64_t now() {
    return std::chrono::duration_cast
       <std::chrono::nanoseconds> 
       (std::chrono::system_clock::now()
          .time_since_epoch())
       .count();
}

int main() {
        std::vector<uint64_t> v;
        for (int i = 0; i < 1000; i++)
                v.push_back(now());

        for (int i = 0; i < v.size()-1; i++)
                std::cout << v[i+1] - v[i] << std::endl;
}

在以下位置打印大约250到300之间的数字:

g++ (Ubuntu 8.2.0-7ubuntu1) 8.2.0

具有:

Linux 4.18.0-15-generic #16-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

在此系统上,标准std :: chrono :: system_clock的精确度是纳秒(很可能是gettimeofday对吗?)。我有几个问题:

  1. std::chrono::system_clockstd::chrono::steady_clock在此系统上有什么区别? (是的,我知道标准中对它们的指定有所不同,我正在考虑这种实现。)

  2. 所有libstdc ++目标的答案是否相同?

  3. 所有libc ++目标的答案是否相同?

  4. 在Windows / MSVC目标上答案是否相同?

1 个答案:

答案 0 :(得分:3)

我不确定您是在问要回答的问题。我看到的一件事是,您询问的是稳定时钟和系统时钟之间的差异,即它们的精度。第二个,仅从代码片段来看,是关于system_clock :: now,duration_cast,vector :: push_back / vector :: insert和(隐式)vector :: resize的性能。

如果您不介意,我将尝试回答这两个问题中的第一个:

  • 这些时钟的症结在于,一个(system_clock)可以与任何物理日历互操作,因此有时可以返回(夏/冬时间转换,当某人或某物更改系统时在机器上的时间,请参见Difference between std::system_clock and std::steady_clock?),而保证其他时间(steady_clock)仅前进,例如测量push_back多长时间。
  • 不能保证这些时钟的分辨率。这就是为什么您应该将时钟的持续时间类型保持尽可能长的时间,并且仅在打印之前使用.count()访问器;但是,由于无法保证所用的时间,您可能应该
    1. 对稳定的内容进行duration_cast,
    2. 或使用句点作为某些元程序的参数来执行一些花哨的后缀选择。
  • 无法保证time_since_epoch()的含义,并且在C ++ 20之前,无法比较属于两个不同时钟的time_points / durations
  • 并且,请记住,在任何系统上都无法保证任何时钟的周期分辨率;我发现了困难的方法(编写一些精美的模板),甚至无法保证周期可以被1000整除...对于其中一个时钟,其中一个库使用10 ^ 8以上的周期作为周期。 。

因此,不建议询问任何特定的实现,并希望它们的常量也将用于其他实现中,即使对于同一供应商也是如此。我总是尝试使用clock's :: time_point或其:: duration,或者作为最后的选择,使用毫秒或纳秒,这取决于我测量的内容以及所测量的东西飞行的速度。

还请注意,有一些system_clock::( to / from)_time_t()函数,即使system_clock :: duration的周期更短,也肯定会产生1比1的值(秒)。

使用steady_clock,其time_point和尽可能早地调用duration_cast的经修改的代码段将是:

#include <chrono>
#include <iostream>
#include <vector>

int main() {
        using namespace std::chrono;
        using clock = steady_clock;

        std::vector<clock::time_point> v;
        for (int i = 0; i < 1000; i++)
                v.push_back(clock::now());

        for (size_t i = 0; i < v.size()-1; i++) {
                std::cout
                        << duration_cast<nanoseconds>(
                                v[i+1] - v[i]
                                ).count()
                        << "ns\n";
        }
}

编辑:哦,另一件事是,原始代码中没有任何内容可以证明您的库在system_clock中使用了nano作为周期。您正在执行一个duration_cast (如果需要,则使用整数除法)并从中获取周期,但是使用不同的持续时间,例如duration_cast >,您还可以在下面的某个地方获取非零值最低的1000。不可能,但永远不会更少。

编辑2:,此很复杂。更改了第一个项目符号中system_clock不稳定的原因。