【问题标题】:How to accurately measure time in c++?如何在 C++ 中准确测量时间?
【发布时间】:2020-11-24 07:03:44
【问题描述】:

我想非常准确地测量函数的执行时间,以皮秒为单位。在 C++ 中可以这么精确吗?我目前知道的测量时间的方法是:

  1. __rdtscp()
  2. std::chrono 时钟
  3. clock.h clock_t

有谁知道这三个函数的准确度如何?哪一种可以实现皮秒时间测量,如果都不能,有什么办法可以降低噪音,让时间测量更准确?

目标系统是 Linux 版本 4.15.0-122-generic (buildd@lcy01-amd64-010) (gcc 版本 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)) #124~16.04.1 -Ubuntu SMP

【问题讨论】:

  • 在没有硬件的情况下,您认为 C++ 方法如何以皮秒为单位测量时间?精度是在 Widows/MSVC 上定义的实现,它以纳秒为单位进行测量,但最小步长可能是 100ns 或更多。如果您需要高精度,则需要购买能够提供该精度并使用其库的硬件。
  • 即使您可以准确地测量时间,但测量仍然存在缺陷,因为您的电脑不仅仅执行单个功能。对于一个有用的度量,您需要运行该函数数千或数百万次并对结果进行平均。这样您甚至不需要精确测量。
  • 你真的需要微微秒分辨率吗?在 4ghz cpu 上 1 纳秒只有 4 个时钟周期,操作系统调度变幻莫测会使你的代码的执行时间变化超过 4 个时钟周期
  • 要超过微秒,您通常需要专门的硬件。
  • 可能没有必要达到皮秒级,但目前哪种方法最准确?

标签: c++ time


【解决方案1】:

消费级计算机上的时钟无法以皮秒精度进行测量。单独获取当前时间的调用至少需要几十纳秒。

但是,您可以循环计时并测量整个经过的时间。然后计算每次迭代的平均时间。 <chrono> 让您可以轻松做到这一点并将结果计算到皮秒精度:

#include <chrono>
#include <iostream>

int
main()
{
    using picoseconds = std::chrono::duration<long long, std::pico>;
    constexpr auto N = 1000;
    auto t0 = std::chrono::steady_clock::now();
    for (int repeat = 0; repeat < N; ++repeat)
    {
        // measure this
    }
    auto t1 = std::chrono::steady_clock::now();
    auto d = picoseconds{t1 - t0}/N;
    std::cout << d.count() << "ps\n";
}

如果您真的想要精确,您可以测量循环开销(确保它没有被优化掉),然后在求平均值之前将其从总数中减去。

for (int repeat = 0; repeat < N; ++repeat)
{
    // measure empty loop overhead
    asm volatile("");
}

阻止优化器删除循环的语法是不可移植的。

【讨论】:

    【解决方案2】:

    如何在c++中准确测量时间?

    测量时间最准确的标准方法是使用std::chrono::high_resolution_clockstd::chrono::steady_clock

    可能存在系统提供的更准确的方法。要弄清楚这一点,第一步是弄清楚目标系统是什么。

    有谁知道这三个函数的准确度如何?

    取决于实现,也可能取决于硬件。

    哪一种可以实现皮秒时间测量

    在实践中可能没有。最快的 CPU 的周期时间以数百皮秒为单位。

    【讨论】:

    • 该标准允许std::chrono::high_resolution_clockstd::chrono::system_clock 相同,这意味着它容易被中断。只有std::chrono::steady_clock 保证单调时间。
    • std::chrono::high_resolution_clock 根据libstdc++-11.2.0 std::chrono::_V2::high_resolution_clock,目前的精度为纳秒级
    猜你喜欢
    • 2011-05-16
    • 2019-05-22
    • 2011-11-14
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2011-11-04
    • 2017-01-25
    • 2022-07-06
    相关资源
    最近更新 更多