测量代码执行时间是困难的。学习如何消除系统和随机测量误差,并获得更可靠的结果。
我们经常需要测量代码的特定部分执行需要多长时间。不幸的是,简单地测量函数调用之前和之后的系统时间并不是很严谨,而且容易受到系统和随机测量错误的影响。这对于测量非常短的间隔(< 100毫秒)来说尤其如此。
系统和随机误差
那么,下面这种测量方法有什么问题呢?
首先,这里会有一个系统误差:通过调用time.perf_counter(), 一个未知量的时间会被加入到my_function()的执行时间中。多少时间呢?这取决于操作系统、特定的实现和其他不可控因素。
其次,还存在一个随机误差:对my_function()调用的执行时间在一定程度上会有变化。
我们可以通过多次测量并取其平均值来抵抗随机误差。然而,消除系统误差的难度要大得多。
直线拟合
卡洛斯·莫雷诺和塞巴斯蒂安·菲什迈斯特提出了一种新技术来减小这种系统性错误。基本思想是首先测量一个函数调用的时间,然后测量两个函数调用的时间,然后测量三个函数调用的时间,依此类推。最终的方法可能是这样的:
然后你可以通过测量结果来拟合一条直线:
总执行时间可以通过获取该直线y = a x + b的斜率a得到。
在上面的例子中,直线是y = 205.91 x + 29.56;因此,执行时间等于205.91毫秒。
作者指出,这种测量方法对于偶尔会出现大误差的测量是非常可靠的。这可以通过人为地改变第4次测量并重新运行直线拟合过程来视觉化:
尽管有一个值是完全偏离的,但我们得出的斜率(201.15)仍然非常接近之前的测量值。
想要更多地了解这种方法的数学基础知识,我邀请你阅读这篇原创性论文:https://uwaterloo.ca/embedded-software-group/sites/ca.embedded-software-group/files/uploads/files/ieee-esl-precise-measurements.pdf
Python实现
你可以在我的公共GitLab仓库中找到我对所展示算法的实现:https://gitlab.com/bernhard.knasmueller/accurate-time-measurements-python
这个算法和想法都要归功于Moreno 和 Fischmeister。
编辑于2020年1月18日:更正了perf_counter()的用法。
英文原文:https://knasmueller.net/measure-code-execution-time-accurately-in-python
译者:忧郁的红秋裤