74

在使用范围表达式迭代大型数组时,我应该使用 Python 的内置range函数还是 numpy 的函数arange来获得最佳性能?

到目前为止我的推理:

range可能诉诸本机实现,因此可能更快。另一方面,arange返回一个完整的数组,它占用内存,因此可能会有开销。Python 3 的范围表达式是一个生成器,它不会保存内存中的所有值。

4

2 回答 2

86

对于大型数组,向量化的 numpy 操作是最快的。如果必须循环,请首选xrange/range并避免使用np.arange.

在 numpy 中,您应该使用矢量化计算、ufunc索引的组合来解决您的问题,因为它正在C快速运行。与此相比,循环遍历 numpy 数组效率低下。

range(您可以做的最np.arange糟糕的事情就是使用创建的索引遍历数组

import numpy as np
import sys

sys.version
# out: '2.7.3rc2 (default, Mar 22 2012, 04:35:15) \n[GCC 4.6.3]'
np.version.version
# out: '1.6.2'

size = int(1E6)

%timeit for x in range(size): x ** 2
# out: 10 loops, best of 3: 136 ms per loop

%timeit for x in xrange(size): x ** 2
# out: 10 loops, best of 3: 88.9 ms per loop

# avoid this
%timeit for x in np.arange(size): x ** 2
#out: 1 loops, best of 3: 1.16 s per loop

# use this
%timeit np.arange(size) ** 2
#out: 100 loops, best of 3: 19.5 ms per loop

xrange因此,对于这种情况,如果操作正确,numpy 比使用快 4 倍。根据您的问题,numpy 的速度可能比 4 或 5 倍快得多。

这个问题的答案解释了使用 numpy 数组而不是 python 列表来处理大型数据集的更多优势。

于 2012-05-22T20:23:16.343 回答
12

首先,正如@bmu 所写,您应该使用矢量化计算、ufuncs 和 indexing 的组合。确实在某些情况下需要显式循环,但这种情况确实很少见。

如果需要显式循环,使用 python 2.6 和 2.7,您应该使用xrange(见下文)。从您所说的来看,在 Python 3 中,range与xrange相同(返回一个生成器)。所以也许范围对你有好处。

现在,您应该自己尝试一下(使用 timeit: - 这里是 ipython“魔术函数”):

%timeit for i in range(1000000): pass
[out] 10 loops, best of 3: 63.6 ms per loop

%timeit for i in np.arange(1000000): pass
[out] 10 loops, best of 3: 158 ms per loop

%timeit for i in xrange(1000000): pass
[out] 10 loops, best of 3: 23.4 ms per loop

同样,如上所述,大多数时候可以使用运行 ac speed: much faster的 numpy 向量/数组公式(或 ufunc 等) 。这就是我们所说的“向量编程”。它使程序比 C 更容易实现(并且更具可读性),但最终几乎一样快。

于 2012-05-22T09:52:05.347 回答