我们应该测量函数的平均执行时间还是最小执行时间?

Should we measure the average or the minimum execution time of a function?

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


当我们测量一个函数的执行时间(始终使用相同的输入)时,我们不会得到相同的结果(时间),即使我们应该得到相同的结果(时间),因为程序 运行 处于多任务环境中。即使我们 运行 我们的程序与 'high priority' 一样,来自其他程序的一些干扰也会减慢我们的程序(为简化起见,让我们考虑单核计算机)。

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

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

以最短时间为目标
如果您的代码只有一个执行路径,那么您应该始终将最短时间(在多次重复中)作为实际花费的时间。
通过这种方式,您可以获得精确到一到两个 CPU 周期内的计时。 需要明确的是,您 运行 数百万 运行 的代码片段,并以该 运行 的最低样本作为时间。
然后你将这数百万个 运行s 包装在一个循环中 运行s 10x 或 100x 并再次采用最低时间。像这样:

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

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

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

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

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

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