为什么numpy.all比python标准慢得多?

时间:2013-08-08 18:35:50

标签: python numpy timeit

我写了一个脚本来在我们的本地集群上进行一些排序相关计算。计算涉及查看长度为5000-10000的两个数组XY,并提取数量

all((X[i], Y[i]))
all((X[i], not Y[i]))
all((not X[i], Y[i]))

数千倍的计算(因为我随机播放X / Y)。

我们的一个集群正在运行python2.4,因此我将all更改为numpy.all s。然而,我估计需要约5-6小时的计算时间达到了24小时以上。这导致我进行调查。

以下是一些示例代码:

In [2]: import timeit
In [3]: s = """import numpy as np
   ...: x, y = np.random.rand(1000), np.random.rand(1000)
   ...: [all((x[i], y[i])) for i in range(1000)]
   ...: """
In [4]: timeit.timeit(s, number=1000)
Out[4]: 0.39837288856506348

In [5]: s_numpy = """import numpy as np
   ...: x, y = np.random.rand(1000), np.random.rand(1000)
   ...: [np.all((x[i], y[i])) for i in range(1000)]
   ...: """
In [9]: timeit.timeit(s_numpy, number=1000)
Out[9]: 14.641073942184448

任何线索为什么numpy.all需要花费50倍的时间才能计算出来?是numpy.array开销吗?

修改:我的原始数组不是numpy.array,就像它们在这里一样(np.random.rand)。我根本没有使用numpy,直到我需要更改all行。但是,我用

之类的东西替换了我的循环
np.sum(np.logical_and(X, Y))
np.sum(np.logical_and(X, np.logical_not(Y)))
np.sum(np.logical_and(np.logical_not(X), Y))

这加快了初始开销的运行,并且计算了大约3000个这些循环60%左右。谢谢!我会寻找更多使用numpy进行优化的方法。

2 个答案:

答案 0 :(得分:3)

[np.all((x[i], y[i])) for i in range(1000)]

可以改写为

x = []
for i in range(1000):
    x.append(numpy.all((x[i],y[i])))

所以你在一个非常小的名单上调用numpy.all

numpy方法通常会发布更大的列表

timeit.timeit('all(x)','x = numpy.arange(1,100000)',number=1)
#~.0175
timeit.timeit('numpy.all(x)','x = numpy.arange(1,100000)',number=1)
#~.00043

答案 1 :(得分:1)

通过使用生成器理解而不是列表理解,您可以使这两个函数更快,更具可比性。

s = """
import numpy as np; 
x, y = np.random.rand(1000),np.random.rand(1000);     
(all((x[i], y[i])) for i in range(1000)) """

timeit.timeit(s,number=1000)
0.05593514442443848

s_yours = """
import numpy as np; 
x, y = np.random.rand(1000),  np.random.rand(1000);
[all((x[i], y[i])) for i in range(1000)] """

timeit.timeit(s_yours,number=1000)
0.3829691410064697


s_numpy = """import numpy as np; 
x, y = np.random.rand(1000), np.random.rand(1000); 
(np.all((x[i], y[i])) for i in range(1000))"""

timeit.timeit(s_numpy,number=1000)
0.06155896186828613

s_your_numpy = """import numpy as np; 
x, y = np.random.rand(1000), np.random.rand(1000); 
[np.all((x[i], y[i])) for i in range(1000)]"""

timeit.timeit(s_your_numpy,number=1000)
12.162676811218262

Numpy可能仍然会变慢,但就像那个人说的那样,在更大的名单上效果更好。

另外,为什么

x.all(), y.all() 

不是一种选择?