【问题标题】:Should we measure the average or the minimum execution time of a function?我们应该测量函数的平均执行时间还是最短执行时间?
【发布时间】:2017-10-11 20:51:07
【问题描述】:

我感兴趣的是比较两个不同函数的速度,两个函数使用相同的输入数据 (BMP)。


当我们测量函数的执行时间(始终使用相同的输入)时,即使我们应该得到相同的结果(时间),我们也不会得到相同的结果(时间),因为程序在多任务环境中运行。即使我们以“高优先级”运行我们的程序,来自其他程序的一些干扰也会减慢我们的程序(为了简化,让我们考虑单核计算机)。

因此,大多数人会多次对该函数计时并取平均值。我的问题是为什么我们不记录最小的执行时间而不是平均时间?最小执行时间应该比平均执行时间更接近真实情况。

【问题讨论】:

  • 只有在没有不同的执行路径可以走的情况下才反映真正的执行时间。一个执行路径可能比另一个执行路径更长/更慢。例如,如果不满足某些条件,最短的(及时)可能只是提前返回。这并不反映典型的执行时间,这是大多数人想知道的。以我的 BigInteger.divide() 为例。如果传入的除数为零,则执行时间很短。但如果不是这种情况,它也可以非常长。
  • 更长的执行时间的存在证明该函数可能需要比最小测量时间更长的时间。大多数人都对任意时间任意负载下的性能感兴趣。
  • 对不起。我还没有很好地定义问题。我添加了这个:“测量函数的执行时间(使用始终相同的输入)” - 所以,现在没有不同的执行路径。再次抱歉。
  • 这仍然不能为您提供太多信息,除非您使用许多不同的输入进行测试。
  • @SertacAkyuz - “更长的执行时间的存在证明该函数可能需要比最小值更长的时间” - 是的。自然。如果计算机忙于其他任务,人们可能会期待这一点。我同意。但是当我们测量一个函数的速度时,我们通常希望看到一些代码优化前后的速度。我们必须排除这种随机条件/测试环境。因此,我认为如果环境给出了相当大的差异,它就不能用于测试。

标签: c++ delphi profiling execution timing


【解决方案1】:

您应该始终以最短时间为目标。
因为如果你这样做,你确定你只是在为你自己的代码计时,而不是别的。

争取最短时间
如果您的代码只有一个执行路径,那么您应该始终将最短时间(在多次重复中)作为实际所用时间。
通过这种方式,您可以获得精确到一两个 CPU 周期内的时序。 为了清楚起见,您将代码 sn-p 运行了数百万次,并将该运行的最低样本作为时间。
然后,您将数百万次运行包装在一个运行 10 倍或 100 倍的循环中,并再次采用最低时间。像这样:

Lowest = MaxInt;
loop 100x 
  loop million times
     Clock.Start;
     DoTest;
     Timing = Clock.Time;
     if (timing < Lowest) {Lowest = timing}

另一个循环重置有时会有所帮助的上下文。这很重要,例如如果 JIT 编译器启动较晚。外部循环给它一个重置的变化。

如果代码 sn-p 特别快,您也可以在外循环中计时,然后除以一百万。在这种情况下,您将运行一个额外的空计时循环,并从繁忙循环所用的时间中减去空循环所用的时间。
您必须变得聪明,以防止代码优化消除空循环:-)。

如果您的代码有多个可能的路径,那么您就无法真正确定其执行时间。只运行一个带有固定输入的简单循环,因为这只会给你一个代码路径的部分时间。这可能并不代表真实世界的表现。

让您的运行具有确定性
始终尝试修复代码,以便代码只能采用一条路径。
或者尝试设置测试,以便连续采用所有可能的路径,然后计算一切所需的最短时间并除以测试的代码路径数。

一切和厨房水槽配置文件
如果这不可能,您将不得不取平均值,但请注意,在这种情况下,您实际上不再只为代码计时,您还需要考虑系统开销、HDD 中断和后台进程。

【讨论】:

    猜你喜欢
    • 2013-03-28
    • 2011-04-15
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多