【问题标题】:Trying to use timeit.timeit [duplicate]尝试使用 timeit.timeit [重复]
【发布时间】:2013-09-26 22:32:24
【问题描述】:

我想测量两个代码的运行时间,我尝试在python文档中查找timeit,但我并没有真正理解。 有人可以用更初级的词汇来解释吗?

【问题讨论】:

标签: python timeit


【解决方案1】:

注意:复制到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
    

    请注意,这里减去开销是合理的只是因为开销只是时间的一小部分。

【讨论】:

    【解决方案2】:

    我发现 IPython 的 %timeit 和 %%timeit 魔术函数比 timeit.timeit 更容易使用(尤其是在使用 ipython notebook 时)。几个例子here

    【讨论】:

      【解决方案3】:
      >>> "-".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
      这个文档真的难以理解吗?我觉得很清楚。

      【讨论】:

      • 我的意思是:我不明白如何将它用于我自己类型的功能代码
      猜你喜欢
      • 2021-01-25
      • 2013-07-24
      • 1970-01-01
      • 2014-08-01
      • 2014-08-13
      • 2017-05-30
      • 2020-08-19
      • 1970-01-01
      • 2020-10-13
      相关资源
      最近更新 更多