【问题标题】:How to evaluate a program's runtime?如何评估程序的运行时间?
【发布时间】:2020-05-16 23:29:42
【问题描述】:

我开发了一个简单的程序,并想在真机上评估它的运行时性能,例如我的 MacBook。 源代码如下:

#include <stdio.h>
#include <vector>
#include <ctime>

int main () {
    auto beg = std::clock () ;
    for (int i = 0; i < 1e8; ++ i) {

    }
    auto end = std::clock () ;
    printf ("CPU time used: %lf ms\n", 1000.0*(end-beg)/CLOCKS_PER_SEC) ;
}

它是用 gcc 编译的,优化标志设置为默认值。 在 bash 脚本的帮助下,我运行了 1000 次,并在我的 MacBook 上记录了运行时,如下:

[130.000000, 136.000000): 0
[136.000000, 142.000000): 1
[142.000000, 148.000000): 234
[148.000000, 154.000000): 116
[154.000000, 160.000000): 138
[160.000000, 166.000000): 318
[166.000000, 172.000000): 139
[172.000000, 178.000000): 40
[178.000000, 184.000000): 11
[184.000000, 190.000000): 3

“[a, b): n”表示同一程序的实际运行时间在a ms和b ms之间n次。

很明显,实际运行时间变化很大,似乎不是正态分布。有人可以告诉我是什么原因造成的,以及如何正确评估运行时?

感谢您回答这个问题。

【问题讨论】:

  • 对不起,我是用g++编译的,不是gcc
  • 这在很大程度上取决于您的系统有多忙。我确实希望其他空闲系统的偏差更低。您可以尝试使用nice -n -10 调用该进程以提高调度优先级,看看是否会有所不同。
  • 我在本地 (linux) 测试了您的程序,99% 的测试都在 0.5 毫秒的时间间隔内。没有测试超出 10 毫秒的间隔。
  • @Scheff,默认优化级别 (-O0) for 循环似乎没有优化。 OP 使用默认优化级别。
  • @Scheff 是的,默认优化级别是-O0,for循环没有优化出来。

标签: c++ profile


【解决方案1】:

基准测试很难!

简答:使用google benchmark

长答案: 有很多事情会干扰时间。

  • 调度(操作系统代替你运行其他东西)
  • CPU 扩展(操作系统决定它可以通过降低运行速度来节省能源)
  • 内存争用(其他东西在您需要时使用内存)
  • 总线争用(与您要通话的设备通话的其他设备)
  • 缓存(CPU 保持一个值以避免不得不使用内存)
  • CPU 迁移。 (操作系统将您从一个 CPU 转移到另一个 CPU)
  • 不准确的时钟(只有 CPU 时钟在任何程度上都是准确的,但如果您迁移,它们会发生变化)

避免这些影响的唯一方法是禁用 CPU 缩放、执行“缓存刷新”功能(通常只是在启动之前接触大量内存)、以高优先级运行并将自己锁定到单个 CPU。即便如此,您的计时仍然会很嘈杂,所以最后一件事就是重复很多次,并使用平均值。
这就是为什么像 google benchmark 这样的工具可能是你最好的选择。

video from CPPCon
也可直播online

【讨论】:

  • 平均不一定是最好的。例如,中位数允许整理绑定的工件。还应考虑最低,因为干扰较少(即使运行之间的可重复性/可比性较低)。
  • @Jarod42:github.com/google/benchmark#reporting-statistics。您总是可以争论哪个平均值最好,这主要取决于您使用它的目的。不过期待差异。几乎不可能删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多