【问题标题】:Measuring the runtime of a C++ code?测量 C++ 代码的运行时间?
【发布时间】:2012-06-19 05:45:08
【问题描述】:

我想测量我的 C++ 代码的运行时间。执行我的代码大约需要 12 个小时,我想在我的代码执行结束时编写这个时间。如何在我的代码中做到这一点?

操作系统:Linux

【问题讨论】:

  • 你在什么操作系统上运行你的代码?
  • 我喜欢同时分析多个代码。
  • 启动任何程序时只需使用time 命令。
  • Linux 上有几种时间概念。见time(7)

标签: c++ linux


【解决方案1】:

如果你想用 printf() 打印测量的时间,你可以使用这个:

auto start = std::chrono::system_clock::now();
/* measured work */
auto end = std::chrono::system_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
printf("Time = %lld ms\n", static_cast<long long int>(elapsed.count()));

【讨论】:

    【解决方案2】:

    这是我使用的代码:

      const auto start = std::chrono::steady_clock::now();
    
      // Your code here.
    
      const auto end = std::chrono::steady_clock::now();
      std::chrono::duration<double> elapsed = end - start;
      std::cout << "Time in seconds: " << elapsed.count() << '\n';
    

    您不想使用std::chrono::system_clock,因为它不是单调的!如果用户在您的代码中间更改时间,您的结果将是错误的——甚至可能是负数。 std::chrono::high_resolution_clock 可能会使用 std::chrono::system_clock 来实现,所以我也不建议这样做。

    这段代码还避免了丑陋的演员表。

    【讨论】:

      【解决方案3】:

      您还可以尝试一些自动启动和停止的计时器类,并收集有关在任何代码块中花费的平均、最大和最小时间以及调用次数的统计信息。这些 cxx-rtimer 类在 GitHub 上可用,并支持使用 std::chrono、clock_gettime() 或 boost::posix_time 作为后端时钟源。

      使用这些计时器,您可以执行以下操作:

      void timeCriticalFunction() {
          static rtimers::cxx11::DefaultTimer timer("expensive");
          auto scopedStartStop = timer.scopedStart();
          // Do something costly...
      }
      

      在程序完成时将计时统计信息写入 std::cerr。

      【讨论】:

        【解决方案4】:

        我在我的一个项目中使用了这样的东西:

        #include <sys/time.h>
        
        struct timeval start, end;
        gettimeofday(&start, NULL);
        //Compute
        gettimeofday(&end, NULL);
        double elapsed = ((end.tv_sec - start.tv_sec) * 1000) 
                + (end.tv_usec / 1000 - start.tv_usec / 1000);
        

        这是毫秒,它适用于 C 和 C++。

        【讨论】:

        【解决方案5】:

        使用 std::chrono::steady_clock 而不是 std::chrono::system_clock 在 C++11 中测量运行时间。原因是(引用system_clock的文档):

        在大多数系统上,系统时间可以随时调整

        而 stable_clock 是单调的,更适合测量间隔:

        类 std::chrono::steady_clock 表示单调时钟。时间 这个时钟的点不能随着物理时间的推移而减少。 此时钟与挂钟时间无关,最适合 测量间隔。

        这是一个例子:

        auto start = std::chrono::steady_clock::now();
        // do something
        auto finish = std::chrono::steady_clock::now();
        double elapsed_seconds = std::chrono::duration_cast<
          std::chrono::duration<double> >(finish - start).count();
        

        一个实用的小技巧:如果您正在测量运行时间并想要报告秒数,std::chrono::duration_cast&lt;std::chrono::seconds&gt; 很少需要,因为它为您提供整个 秒数。要以 double 的形式获取时间(以秒为单位),请使用上面的示例。

        【讨论】:

        • 我没有得到实用提示。 std::chrono::duration_cast&lt;std::chrono::seconds&gt; 不是将两个时间点之间的差作为总秒数的方法吗?
        • @Isaac 我的意思是std::chrono::duration_cast&lt;std::chrono::seconds&gt; 将返回 0 如果差异小于一秒。如果您希望将持续时间作为浮点数,请使用 double 而不是 seconds
        • @vitaut 它返回错误的时间,我不明白发生了什么。我将此时间与我从命令行上的“时间”命令得到的时间进行比较,它们是不同的。
        【解决方案6】:

        如果你使用的是 C++11,你可以使用system_clock::now():

        auto start = std::chrono::system_clock::now();
        
        /* do some work */
        
        auto end = std::chrono::system_clock::now();
        auto elapsed = end - start;
        std::cout << elapsed.count() << '\n';
        

        您还可以指定用于表示持续时间的粒度:

        // this constructs a duration object using milliseconds
        auto elapsed =
            std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        
        // this constructs a duration object using seconds
        auto elapsed =
            std::chrono::duration_cast<std::chrono::seconds>(end - start);
        

        如果您不能使用 C++11,请查看来自 Boost 的 chrono

        使用这样的标准库的最大好处是它们的可移植性非常高(例如,它们都可以在 Linux 和 Windows 中工作)。因此,如果您决定在之后移植您的应用程序,您不必太担心。

        这些库也遵循现代 C++ 设计,而不是类似 C 的方法。

        编辑:上面的例子可以用来测量wall-clock time。然而,这并不是衡量程序执行时间的唯一方法。首先,我们可以区分用户时间和系统时间:

        • 用户时间:程序在user space中运行所花费的时间。
        • 系统时间: 程序在系统(或内核)空间中运行所花费的时间。例如,当执行system call 时,程序会进入内核空间。

        根据目标,可能需要或不需要将系统时间视为程序执行时间的一部分。例如,如果目标只是衡量对用户代码的编译器优化,那么最好省略系统时间。另一方面,如果用户想确定系统调用是否是一个显着的开销,那么也有必要测量系统时间。

        此外,由于大多数现代系统都是time-shared,因此不同的程序可能会争夺多个计算资源(例如 CPU)。在这种情况下,可以进行另一种区分:

        • Wall-clock time: 通过使用挂钟时间,程序执行的测量方式与我们使用外部(挂钟)时钟相同。这种方法不考虑程序之间的交互。
        • CPU time: 在这种情况下,我们只计算程序实际在 CPU 上运行的时间。如果一个程序 (P1) 与另一个程序 (P2) 共同调度,并且我们想要获取 P1 的 CPU 时间,这种方法不包括 P2 运行和 P1 等待 CPU 的时间(而不是挂钟时间方法)。

        为了测量 CPU 时间,Boost 包含一个set of extra clocks

        • process_real_cpu_clock,捕获当前进程花费的挂钟 CPU 时间。
        • process_user_cpu_clock,捕获当前进程花费的用户 CPU 时间。
        • process_system_cpu_clock,捕获当前进程花费的系统 CPU 时间。一个类似元组的类 process_cpu_clock,它同时捕获实际、用户 CPU 和系统 CPU 进程时间。
        • thread_clock 线程稳定时钟提供当前线程所花费的时间(当平台支持时)。

        很遗憾,C++11 没有这样的时钟。但是 Boost 是一个广泛使用的库,并且这些额外的时钟可能会在某个时候被合并到 C++1x 中。因此,如果您使用 Boost,那么当新的 C++ 标准添加它们时,您就可以做好准备了。

        最后,如果你想测量一个程序从命令行执行的时间(而不是在你的程序中添加一些代码),你可以看看time 命令,就像@BЈовић 建议的那样.但是,这种方法不允许您测量程序的各个部分(例如,执行一个函数所需的时间)。

        【讨论】:

        • 我的问题是:C++/C++11 的差异和 boost-libraries 怎么样?
        • @loldop 我相信 C++11 实现是 Boost chrono 库的一个子集。所以他们应该有一个非常相似的 API(如果不一样的话)。使用 C++11 的好处是您不需要使用 Boost(如果 chrono 是您想要从 Boost 获得的唯一库)。
        • system_clock 可以跳转(由于用户更改系统时间、NTP 调整时钟、插入闰秒)。它对于时间间隔的测量是没有用的。
        【解决方案7】:

        您可以使用time 来启动您的程序。当它结束时,它会打印有关程序运行的漂亮时间统计信息。配置要打印的内容很容易。默认情况下,它会打印执行程序所花费的用户和 CPU 时间。

        编辑:请注意,代码中的每个度量都不正确,因为您的应用程序会被其他程序阻止,从而给您错误的值*

        * 通过错误的值,我的意思是很容易获得执行程序所花费的时间,但该时间取决于程序执行期间的 CPU 负载。为了获得相对稳定的时间测量,不依赖于 CPU 负载,可以使用time 执行应用程序,并使用 CPU 作为测量结果。

        【讨论】:

        • 我认为阻塞也是程序运行所需时间的一部分,不是吗?
        • @EitanT 不,因为 CPU 负载发生了变化。当前负载不必与 1 小时或明天的负载相同。
        • @BЈовић 好吧,这真的取决于。由用户决定他/她是要测量挂钟时间还是 CPU 时间。这两种方法都是完全有效的,只是针对不同的目标。
        • @betabandido:如果您按照建议使用time,则无需决定。它报告经过的时间和 CPU 时间。
        • @MikeSeymour 我知道。如果您想从命令行测量执行时间,使用time 这不是一个糟糕的解决方案。我只是反对这样一种观点,即测量 CPU 时间是衡量程序运行所需时间的唯一有价值的方法(正如对 EitanT 的回复所暗示的那样)。
        猜你喜欢
        • 2017-09-04
        • 2022-01-03
        • 2013-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-03
        相关资源
        最近更新 更多