当我将“%timeit”放入带有 IPython/Jupyter 的函数中时,为什么会得到错误的计时结果?
Why do I get bad timing results when I put "%timeit" inside a function with IPython/Jupyter?
我正在学习如何在 IPython 中使用 %timeit
魔术命令,实际上是在 Python 中使用 Jupyter notebook 3. 如果我尝试为各种大小的 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
不应该在函数内部正确 工作(目前)。如果你开始一个新的笔记本(或重新启动你的)并且只使用:
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: name 'arr' is not defined
那是因为 %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 per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
670 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
2.04 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
451 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
906 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
1.01 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
767 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
890 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
1.28 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
[1 2 3]
[1 2 3]
919 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
所以在你的情况下,它总是从你的非函数运行(这是全局的)中找到最后一个 arr
。这也解释了为什么函数的时间大致相同。因为它总能找到相同的arr
.
我正在学习如何在 IPython 中使用 %timeit
魔术命令,实际上是在 Python 中使用 Jupyter notebook 3. 如果我尝试为各种大小的 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
不应该在函数内部正确 工作(目前)。如果你开始一个新的笔记本(或重新启动你的)并且只使用:
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: name 'arr' is not defined
那是因为 %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 per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 670 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 2.04 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 451 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 906 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 1.01 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 767 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 890 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 1.28 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each) [1 2 3] [1 2 3] 919 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 2 loops each)
所以在你的情况下,它总是从你的非函数运行(这是全局的)中找到最后一个 arr
。这也解释了为什么函数的时间大致相同。因为它总能找到相同的arr
.