用Python的timeit模块测量处理时间。

商业

使用Python标准库的timeit模块,你可以很容易地测量你代码中一个进程的执行时间。这对于快速检查很有用。

这里将讨论以下两个案例。

  • 在一个Python文件中测量。timeit.timeit(),timeit.repeat()
  • 用Jupyter笔记本测量。%timeit,%%timeit

另一种方法是使用time.time()来测量程序中经过的时间。

Python文件中的测量:timeit.timeit(), timeit.repeat()

作为一个例子,我们将测量一个简单的函数test(n)的处理时间,它计算n个连续数字的总和。

import timeit

def test(n):
    return sum(range(n))

n = 10000
loop = 1000

result = timeit.timeit('test(n)', globals=globals(), number=loop)
print(result / loop)
# 0.0002666301020071842

如果你把你想测量的代码作为一个字符串传给timeit.timeit()函数,它将被执行N次,并返回它所花费的时间。
数字的默认值是1,000,000。请注意,如果你对一个耗时的过程使用默认值,它将花费大量时间。

通过传递 globals() 作为参数 globals,代码将在全局命名空间执行。
如果不这样做,上面的例子中的函数test和变量n就无法识别。

要指定的代码可以是一个可调用的对象,而不是一个字符串,所以它可以被指定为一个没有参数的lambda表达式;在这种情况下,参数globals不需要被指定。

result = timeit.timeit(lambda: test(n), number=loop)
print(result / loop)
# 0.00027574066299712287

结果的单位是秒。这里,输出结果是每次执行的处理时间除以执行次数。

如果你不进行分割,结果值会随着你执行次数的增加而变大。

print(timeit.timeit(lambda: test(n), number=1))
print(timeit.timeit(lambda: test(n), number=10))
print(timeit.timeit(lambda: test(n), number=100))
# 0.0003999490290880203
# 0.0038685189792886376
# 0.03517670702422038

使用timeit.repeat()函数,timeit()可以被重复执行。结果将以列表的形式获得。

repeat = 5
print(timeit.repeat(lambda: test(n), repeat=repeat, number=100))
# [0.044914519996382296, 0.039663890027441084, 0.02868645201670006, 0.022745631984435022, 0.023260265996214002]

用Jupyter笔记本测量。%timeit, %%timeit

在Jupyter笔记本(IPython)中,你可以使用以下神奇的命令;不需要导入timeit模块。

  • %timeit
  • %%timeit

%timeit

在%timeit中,指定目标代码,像命令行参数一样用空格分隔。

默认情况下,timeit.timeit()中的数字和重复是自动确定的。你也可以用-n和-r选项指定它们。

结果以平均值和标准差计算。

%timeit test(n)
# 259 µs ± 4.87 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit -r 3 -n 10000 test(n)
# 237 µs ± 6.44 µs per loop (mean ± std. dev. of 3 runs, 10000 loops each)

%timeit

神奇的命令%timeit可以用来测量整个单元的处理时间。

作为一个例子,让我们用NumPy运行同样的过程。-n和-r选项可以省略。

由于我们测量的是整个单元格的处理时间,下面的例子包括导入NumPy的时间。

%%timeit -r 3 -n 10000
import numpy as np
a = np.arange(n)
np.sum(a)
# 19.7 µs ± 9.57 µs per loop (mean ± std. dev. of 3 runs, 10000 loops each)

不需要指定目标代码作为%%timeit的参数。你所要做的就是在单元格的开头写上%timeit,所以它是最容易使用的。