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



当我们测量例程的执行时间(始终使用相同的输入)时,即使我们应该得到的结果(时间),我们也不会得到相同的结果(时间),因为程序在多任务环境中运行。即使我们以"高优先级"运行我们的程序,来自CPU中运行的其他程序的一些干扰当然也会对结果产生轻微影响。

测量的目的是在代码优化之前和之后对该例程进行计时。

大多数人会多次对函数进行计时并做平均值。为什么我们不看最短的执行时间而不是平均值?

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

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

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

另一个循环重置上下文,这有时会有所帮助。这很重要,例如,如果 JIT 编译器启动得很晚。外部循环会对其进行重置更改。

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

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

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

一切和厨房水槽剖析
如果这是不可能的,你将不得不取平均值,但请注意,在这种情况下,你不再只是对代码进行计时,你还要考虑系统开销、硬盘中断和后台进程。

最新更新