60

IPython %timeit 魔术命令可以很好地测量运行某些 Python 代码所需的时间。现在,我想在 Python 脚本中使用类似的东西。我知道 timeit 模块,但是,它有几个缺点,例如,如何自适应地选择运行次数?即,默认代码

import timeit
t=timeit.Timer("code(f)", "from __main__ import code,f")
t.timeit() 

运行代码百万次。%timeit IPyhton 魔术命令会自动执行此操作。我建议我可以使用类似 MATLAB 代码 http://www.mathworks.com/matlabcentral/fileexchange/18798

它会自动完成所有工作(并且还会告诉函数的开销是否很大)。

如何从 Python 脚本中调用 %timeit 魔法(或者也许有更好的计时解决方案)?

4

5 回答 5

77

这取决于您拥有的 IPython 版本。如果你有 1.x:

from IPython import get_ipython
ipython = get_ipython()

如果您有旧版本:

import IPython.core.ipapi  
ipython = IPython.core.ipapi.get()

或者

import IPython.ipapi  
ipython = IPython.ipapi.get()

完成后,运行如下魔术命令:

ipython.magic("timeit abs(-42)")

请注意,脚本必须通过ipython.

于 2013-04-09T09:56:59.193 回答
7

IPython 和timeit模块都在使用 调用时python -m timeit,执行相同的循环,数值不断增加,直到计时结果超过某个阈值,从而保证时间测量几乎不受操作系统干扰。

您可以将魔术的IPython 实现%timeitPythontimeit标准模块进行比较,以发现它们的工作基本相同。

因此,回答您的问题时,您可能应该复制相同的循环,直到找到number参数的正确值。

于 2012-04-28T10:05:50.850 回答
3

如果在 IPython 中以交互方式运行 Python 脚本,则以下方法有效。例如,test.py

def f():
    # Algorithm 1
    pass

def g():
    # Algorithm 2
    pass

# which one is faster?
mgc = get_ipython().magic
mgc(u'%timeit f()')
mgc(u'%timeit g()')

然后在 IPython 中以交互方式运行它

%run -i test.py

吐出时间。开关是必要的-i,以便变量在范围内。我还没有想出如何在不运行 IPython 实例的情况下做到这一点,即通过简单地timeit从 IPython 导入并将其用作函数。但是,此解决方案适用于我的目的,即自动化一些计时运行。

于 2013-11-01T21:43:22.940 回答
3

运行 ipython 魔术函数的一种方法可能是使用嵌入 ipython 实例。
例如:(大部分代码是从ipython网站借来的)

from IPython.terminal.embed import InteractiveShellEmbed

ipshell = InteractiveShellEmbed()
ipshell.dummy_mode = True
print('\nTrying to call IPython which is now "dummy":')
ipshell.magic("%timeit abs(-42)");
ipshell()
print('Nothing happened...')

这可以通过使用 python 解释器
PS:使用 dummy_mode 将阻止调用交互式 shell。

于 2015-04-14T07:42:59.890 回答
3

根据模块的文档,当在命令行模式下运行时,timeit.pytimeit

如果未给出 -n,则通过尝试连续的 10 次方来计算合适的循环次数,直到总时间至少为 0.2 秒。

这就是 IPython 所做的。这就是为什么循环数总是 10 的幂。您可以在自己的代码中执行类似的操作,方法是将调用嵌入到t.timeit()循环中,以确保您不会等待太久:

import timeit
t = timeit.Timer("code(f)", "from __main__ import code, f")

max_time = 0.2
N = 0
curr_time = t.timeit(1)

while curr_time < max_time:
    N += 1
    curr_time = t.timeit(10**N)

mean_time = curr_time / float(10**N)

这将确保分析时间至少为 0.2 秒,但不会显着增加 --- 除非调用该函数一次需要很长时间。

于 2015-08-19T18:42:58.643 回答