我想测量运行两个代码的时间,我试着查看python文档的timeit,但我真的不明白。 有人可以用更初级的词汇来解释吗?
答案 0 :(得分:3)
注意:已复制到How to use timeit module。
我会告诉你一个秘密:使用timeit
的最佳方法是在命令行上。
在命令行上,timeit
进行适当的统计分析:它会告诉您最短的运行时间。这很好,因为时间上的所有错误都是正的。因此,最短的时间内错误最少。没有办法得到负面错误,因为计算机无法计算得比计算速度快!
所以,命令行界面:
%~> python -m timeit "1 + 2"
10000000 loops, best of 3: 0.0468 usec per loop
这很简单,嗯?
你可以设置内容:
%~> python -m timeit -s "x = range(10000)" "sum(x)"
1000 loops, best of 3: 543 usec per loop
也很有用!
如果你想要多行,你可以使用shell的自动延续或使用单独的参数:
%~> python -m timeit -s "x = range(10000)" -s "y = range(100)" "sum(x)" "min(y)"
1000 loops, best of 3: 554 usec per loop
这给出了
的设置x = range(1000)
y = range(100)
和时间
sum(x)
min(y)
如果您想要更长的脚本,可能会想要在Python脚本中移动到timeit
。我建议避免这种情况,因为在命令行上分析和计时更好。相反,我倾向于制作shell脚本:
SETUP="
... # lots of stuff
"
echo Minmod arr1
python -m timeit -s "$SETUP" "Minmod(arr1)"
echo pure_minmod arr1
python -m timeit -s "$SETUP" "pure_minmod(arr1)"
echo better_minmod arr1
python -m timeit -s "$SETUP" "better_minmod(arr1)"
... etc
由于多次初始化,这可能会花费更长的时间,但通常这不是什么大问题。
但是如果你希望在你的模块中使用timeit
怎么办?
嗯,简单的方法是:
def function(...):
...
timeit.Timer(function).timeit(number=NUMBER)
这会给你累积(不最小!)的时间来运行这么多次。
要获得良好的分析,请使用.repeat
并采取此分钟:
min(timeit.Timer(function).repeat(repeat=REPEATS, number=NUMBER))
您通常应将其与functools.partial
而不是lambda: ...
结合使用,以降低开销。因此,您可以拥有类似的内容:
from functools import partial
def to_time(items):
...
test_items = [1, 2, 3] * 100
times = timeit.Timer(partial(to_time, test_items)).repeat(3, 1000)
# Divide by the number of repeats
time_taken = min(times) / 1000
你也可以这样做:
timeit.timeit("...", setup="from __main__ import ...", number=NUMBER)
它可以让您从命令行更接近接口,但却不那么酷。 "from __main__ import ..."
允许您在timeit
创建的人工环境中使用主模块中的代码。
值得注意的是,这是Timer(...).timeit(...)
的便利包装,因此在时间上并不是特别好。我个人更喜欢使用Timer
,如上所示。
timeit
有一些警告随处可见。
不计入间接费用。假设您想要花时间x += 1
,以了解添加需要多长时间:
>>> python -m timeit -s "x = 0" "x += 1"
10000000 loops, best of 3: 0.0476 usec per loop
嗯,不0.0476μs。你只知道少。所有错误都是正面的。
因此,尝试找到纯开销:
>>> python -m timeit -s "x = 0" ""
100000000 loops, best of 3: 0.014 usec per loop
从时间开始,这是一个很好的<强> 30%开销!这可以大大扭曲相对时间。但你真的很关心添加时间; x
的查找时间也需要包含在开销中:
>>> python -m timeit -s "x = 0" "x"
100000000 loops, best of 3: 0.0166 usec per loop
差别不大,但它就在那里。
变异方法很危险。
python -m timeit -s "x = [0]*100000" "while x: x.pop()"
10000000 loops, best of 3: 0.0436 usec per loop
但是完全错误了! x
是第一次迭代后的空列表。您需要重新初始化:
>>> python -m timeit "x = [0]*100000" "while x: x.pop()"
100 loops, best of 3: 9.79 msec per loop
但是你有很多开销。单独说明。
>>> python -m timeit "x = [0]*100000"
1000 loops, best of 3: 261 usec per loop
请注意,减去开销在这里是合理的,因为的开销是时间的一小部分。
答案 1 :(得分:1)
我发现IPython的%timeit和%% timeit魔术函数比timeit.timeit更容易使用(特别是在使用ipython笔记本时)。几个例子here。
答案 2 :(得分:0)
>>> "-".join(str(n) for n in range(100))
'0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40-41-42-43-44-45-46-47-48-49-50-51-52-53-54-55-56-57-58-59-60-61-62-63-64-65-66-67-68-69-70-71-72-73-74-75-76-77-78-79-80-81-82-83-84-85-86-87-88-89-90-91-92-93-94-95-96-97-98-99'
>>>
假设这是您想要运行的命令
导入timeit
。将命令设为字符串,添加您想要运行它的次数。
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=100)
0.011214537887298093
Documentation
这个文件真的难以理解吗?我发现它清晰明了。