【问题标题】:Why do I get bad timing results when I put "%timeit" inside a function with IPython/Jupyter?当我使用 IPython/Jupyter 将“%timeit”放入函数中时,为什么会得到糟糕的计时结果?
【发布时间】:2017-09-03 16:48:13
【问题描述】:

我正在学习如何在 IPython 中使用 %timeit 魔法命令,实际上是在 Python 3 中使用 Jupyter notebook。如果我尝试为各种大小的数组计时 NumPy 排序函数:

n = 10
for i in range(n):
    arr = np.random.rand(2**(i+10))
    %timeit -n 2 np.sort(arr)

然后我得到一个大致增加的时间序列,就像我预期的那样。

但是,如果我尝试将此代码打包到一个函数中,我不会得到我期望的输出:所有时间都差不多!

def my_func(n):
    for i in range(n):
        arr = np.random.rand(2**(i+10))
        %timeit -n 10 np.sort(arr)
my_func(10)

请查看显示结果的 Jupyter notebook here

谁能解释我做错了什么,或者我误解了什么?

【问题讨论】:

  • %timeit 是 Jupyter 支持的一种特殊语法,它实际上不是有效的 Python 代码。所以我希望 Jupyter 会单独解析它,它会对整个执行的命令产生影响。尝试直接使用timeit 模块。
  • 在第二种情况下,您只是在重复排序您在第一个单元格中创建的全局 arr,而不是本地 arr。将局部变量名称更改为其他名称,您将看到 %timeit 抱怨的内容。

标签: python function ipython timeit ipython-magic


【解决方案1】:

%timeit 不应该正确在函数内部工作(目前)。如果你开始一个新的笔记本(或重新启动你的)并且只使用:

import numpy as np
def my_func(n):
    for i in range(n):
        arr = np.random.rand(2**(i+10))
        %timeit -n 10 np.sort(arr)

my_func(10)

它会抛出一个NameError:

NameError: 名称“arr”未定义

那是因为%timeit 只检查全局变量而不是本地变量(因此它忽略了在你的函数中定义的变量arr = np.random.rand(2**(i+10)))。

如果你使用这段代码,那就很明显了:

import numpy as np

arr = np.array([1, 2, 3])

def my_func(n):
    for i in range(n):
        arr = np.random.rand(2**(i+10))
        %timeit -n 2 -r 1 print(arr)

my_func(10)

哪个打印:

[1 2 3] [1 2 3] 每个循环 3.44 ms ± 0 ns(平均值 ± 标准偏差。1 次运行,每个循环 2 个) [1 2 3] [1 2 3] 每个循环 670 µs ± 0 ns(1 次运行的平均值 ± 标准偏差,每次 2 个循环) [1 2 3] [1 2 3] 每个循环 2.04 ms ± 0 ns(平均值 ± 标准偏差。1 次运行,每个循环 2 个) [1 2 3] [1 2 3] 每个循环 451 µs ± 0 ns(平均值 ± 标准偏差。1 次运行,每个循环 2 个) [1 2 3] [1 2 3] 每个循环 906 µs ± 0 ns(平均值 ± 标准偏差。1 次运行,每个循环 2 个) [1 2 3] [1 2 3] 每个循环 1.01 ms ± 0 ns(平均值 ± 标准偏差。1 次运行,每个循环 2 个) [1 2 3] [1 2 3] 每个循环 767 µs ± 0 ns(平均值 ± 标准偏差。1 次运行,每次 2 个循环) [1 2 3] [1 2 3] 每个循环 890 µs ± 0 ns(平均值 ± 标准偏差。1 次运行,每次 2 个循环) [1 2 3] [1 2 3] 每个循环 1.28 ms ± 0 ns(平均值 ± 标准偏差。1 次运行,每个循环 2 个) [1 2 3] [1 2 3] 每个循环 919 µs ± 0 ns(平均值 ± 标准偏差。1 次运行,每次 2 个循环)

所以在你的情况下,它总是从你的非函数运行中找到最后一个arr(这是全局的)。这也解释了为什么函数的时间大致相同。因为它总是找到相同的arr

【讨论】:

    猜你喜欢
    • 2021-06-01
    • 2018-04-23
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多