我写了一个脚本来在我们的本地集群上进行一些排序相关计算。计算涉及查看长度为5000-10000的两个数组X
和Y
,并提取数量
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进行优化的方法。
答案 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()
不是一种选择?