如何使用timeit模块

本文翻译自:How to use timeit module

I understand the concept of what timeit does but I am not sure how to implement it in my code. 我明白什么概念timeit做,但我不知道如何实现它在我的代码。

How can I compare two functions, say insertion_sort and tim_sort , with timeit ? 我如何比较两个功能,说insertion_sorttim_sort ,与timeit


#1楼

参考:https://stackoom.com/question/YUbZ/如何使用timeit模块


#2楼

I'll let you in on a secret: the best way to use timeit is on the command line. 我会告诉您一个秘密:最好的使用timeit是在命令行上。

On the command line, timeit does proper statistical analysis: it tells you how long the shortest run took. 在命令行上, timeit会进行适当的统计分析:它告诉您最短运行时间。 This is good because all error in timing is positive. 这很好,因为所有计时错误都是正的。 So the shortest time has the least error in it. 因此,最短的时间误差最小。 There's no way to get negative error because a computer can't ever compute faster than it can compute! 没有办法得到负错误,因为计算机的计算速度永远不可能超过其计算速度!

So, the command-line interface: 因此,命令行界面:

%~> python -m timeit "1 + 2"
10000000 loops, best of 3: 0.0468 usec per loop

That's quite simple, eh? 这很简单,是吗?

You can set stuff up: 您可以设置以下内容:

%~> python -m timeit -s "x = range(10000)" "sum(x)"
1000 loops, best of 3: 543 usec per loop

which is useful, too! 也是有用的!

If you want multiple lines, you can either use the shell's automatic continuation or use separate arguments: 如果需要多行,则可以使用外壳程序的自动延续或使用单独的参数:

%~> python -m timeit -s "x = range(10000)" -s "y = range(100)" "sum(x)" "min(y)"
1000 loops, best of 3: 554 usec per loop

That gives a setup of 这给出了一个设置

x = range(1000)
y = range(100)

and times 和时代

sum(x)
min(y)

If you want to have longer scripts you might be tempted to move to timeit inside a Python script. 如果您想要更长的脚本,则可能会timeit在Python脚本中转到timeit I suggest avoiding that because the analysis and timing is simply better on the command line. 我建议避免这种情况,因为在命令行上分析和计时会更好。 Instead, I tend to make shell scripts: 相反,我倾向于制作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

This can take a bit longer due to the multiple initialisations, but normally that's not a big deal. 由于要进行多次初始化,因此可能需要更长的时间,但是通常这没什么大不了的。


But what if you want to use timeit inside your module? 但是,如果您在模块中使用timeit怎么办?

Well, the simple way is to do: 好吧,简单的方法是:

def function(...):
    ...

timeit.Timer(function).timeit(number=NUMBER)

and that gives you cumulative ( not minimum!) time to run that number of times. 这样您就可以累积( 而不是最短!)时间来运行该次数。

To get a good analysis, use .repeat and take the minimum: 为了获得良好的分析效果,请使用.repeat并至少进行以下操作:

min(timeit.Timer(function).repeat(repeat=REPEATS, number=NUMBER))

You should normally combine this with functools.partial instead of lambda: ... to lower overhead. 通常应将此与functools.partial而不是lambda: ...结合使用,以降低开销。 Thus you could have something like: 因此,您可能会遇到以下情况:

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

You can also do: 您也可以:

timeit.timeit("...", setup="from __main__ import ...", number=NUMBER)

which would give you something closer to the interface from the command-line, but in a much less cool manner. 这将使您从命令行更接近界面 ,但是方式要少得多。 The "from __main__ import ..." lets you use code from your main module inside the artificial environment created by timeit . "from __main__ import ..."使您可以在timeit创建的人工环境中使用主模块中的代码。

It's worth noting that this is a convenience wrapper for Timer(...).timeit(...) and so isn't particularly good at timing. 值得注意的是,这是Timer(...).timeit(...)的方便包装,因此在计时方面不是特别好。 I personally far prefer using Timer(...).repeat(...) as I've shown above. 如上所示,我个人更喜欢使用Timer(...).repeat(...)


Warnings 警告事项

There are a few caveats with timeit that hold everywhere. 有带有一些告诫timeit持有无处不在。

  • Overhead is not accounted for. 开销不占。 Say you want to time x += 1 , to find out how long addition takes: 假设您要对x += 1计时,以找出加法需要多长时间:

     >>> python -m timeit -s "x = 0" "x += 1" 10000000 loops, best of 3: 0.0476 usec per loop 

    Well, it's not 0.0476 µs. 好吧,这不是 0.0476 µs。 You only know that it's less than that. 您只知道它比这还 All error is positive. 所有错误均为正。

    So try and find pure overhead: 因此,尝试找到开销:

     >>> python -m timeit -s "x = 0" "" 100000000 loops, best of 3: 0.014 usec per loop 

    That's a good 30% overhead just from timing! 仅从定时开始,这就是30%的开销! This can massively skew relative timings. 这会大大歪曲相对的时间安排。 But you only really cared about the adding timings; 但是您只真正关心添加的时间。 the look-up timings for x also need to be included in overhead: x的查找时间也需要包含在开销中:

     >>> python -m timeit -s "x = 0" "x" 100000000 loops, best of 3: 0.0166 usec per loop 

    The difference isn't much larger, but it's there. 差别不大,但是就在那里。

  • Mutating methods are dangerous. 变异方法很危险。

     >>> python -m timeit -s "x = [0]*100000" "while x: x.pop()" 10000000 loops, best of 3: 0.0436 usec per loop 

    But that's completely wrong! 但这是完全错误的! x is the empty list after the first iteration. x是第一次迭代后的空列表。 You'll need to reinitialize: 您需要重新初始化:

     >>> python -m timeit "x = [0]*100000" "while x: x.pop()" 100 loops, best of 3: 9.79 msec per loop 

    But then you have lots of overhead. 但是那样您就会有很多开销。 Account for that separately. 分别说明。

     >>> python -m timeit "x = [0]*100000" 1000 loops, best of 3: 261 usec per loop 

    Note that subtracting the overhead is reasonable here only because the overhead is a small-ish fraction of the time. 请注意,在这里减去开销是合理的, 仅是因为开销只是时间的一小部分。

    For your example, it's worth noting that both Insertion Sort and Tim Sort have completely unusual timing behaviours for already-sorted lists. 对于你的榜样,值得一提的, 无论插入排序和蒂姆排序对已排序的列表完全不同寻常的时刻的行为。 This means you will require a random.shuffle between sorts if you want to avoid wrecking your timings. 这意味着如果您想避免破坏时间安排,则需要在各排序之间使用random.shuffle


#3楼

If you want to compare two blocks of code / functions quickly you could do: 如果要快速比较两个代码/功能块,可以执行以下操作:

import timeit

start_time = timeit.default_timer()
func1()
print(timeit.default_timer() - start_time)

start_time = timeit.default_timer()
func2()
print(timeit.default_timer() - start_time)

#4楼

lets setup the same dictionary in each of the following and test the execution time. 让我们在以下每个目录中设置相同的字典并测试执行时间。

The setup argument is basically setting up the dictionary setup参数基本上是在设置字典

Number is to run the code 1000000 times. 编号是要运行的代码1000000次。 Not the setup but the stmt 不是设置而是stmt

When you run this you can see that index is way faster than get. 运行此命令时,您可以看到索引比获取索引快得多。 You can run it multiple times to see. 您可以运行它多次查看。

The code basically tries to get the value of c in the dictionary. 该代码基本上试图获取字典中c的值。

import timeit

print('Getting value of C by index:', timeit.timeit(stmt="mydict['c']", setup="mydict={'a':5, 'b':6, 'c':7}", number=1000000))
print('Getting value of C by get:', timeit.timeit(stmt="mydict.get('c')", setup="mydict={'a':5, 'b':6, 'c':7}", number=1000000))

Here are my results, yours will differ. 这是我的结果,您的结果会有所不同。

by index: 0.20900007452246427 按索引:0.20900007452246427

by get: 0.54841166886888 通过获取:0.54841166886888


#5楼

# Генерация целых чисел

def gen_prime(x):
    multiples = []
    results = []
    for i in range(2, x+1):
        if i not in multiples:
            results.append(i)
            for j in range(i*i, x+1, i):
                multiples.append(j)

    return results


import timeit

# Засекаем время

start_time = timeit.default_timer()
gen_prime(3000)
print(timeit.default_timer() - start_time)

# start_time = timeit.default_timer()
# gen_prime(1001)
# print(timeit.default_timer() - start_time)

#6楼

The built-in timeit module works best from the IPython command line. 内置的timeit模块在IPython命令行中效果最佳。

To time functions from within a module: 要从模块内计时功能:

from timeit import default_timer as timer
import sys

def timefunc(func, *args, **kwargs):
    """Time a function. 

    args:
        iterations=3

    Usage example:
        timeit(myfunc, 1, b=2)
    """
    try:
        iterations = kwargs.pop('iterations')
    except KeyError:
        iterations = 3
    elapsed = sys.maxsize
    for _ in range(iterations):
        start = timer()
        result = func(*args, **kwargs)
        elapsed = min(timer() - start, elapsed)
    print(('Best of {} {}(): {:.9f}'.format(iterations, func.__name__, elapsed)))
    return result
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值