数组上的Numpy快速算术

时间:2017-04-11 20:22:30

标签: python arrays numpy

我正在阅读Numpy Tutorial,并且说这样的示例代码如下:

>>> X = np.ones(10, dtype=np.int)
>>> Y = np.ones(10, dtype=np.int)
>>> A = 2*X + 2*Y

很慢,因为它会创建三个不同的中间数组,以保存A2*X2*Y的值。

相反,建议如果速度是个问题,请执行相同的计算:

>>> X = np.ones(10, dtype=np.int)
>>> Y = np.ones(10, dtype=np.int)
>>> np.multiply(X, 2, out=X)
>>> np.multiply(Y, 2, out=Y)
>>> np.add(X, Y, out=X)

但我没看到速度差异在哪里。在第二个代码中,XY似乎仍然被创建为中间数组。区别在于np.multiply而不是2*X的速度吗?

2 个答案:

答案 0 :(得分:2)

这两个代码示例在他们正在做的事情上并不相同。执行2*X时,您必须分配一个新数组。第二个例子虽然速度更快,但有点破坏性,因为你需要直接修改数组而不是为计算制作副本。

如果您打算重复使用X和Y进行多次不相互依赖的操作(也就是说,您将此操作的X和Y相乘,而不是将来的相乘),您可能需要使用初始方法,这样您就可以不必撤消操作。

答案 1 :(得分:2)

我将这两个例子包含在函数中,并尝试了一些时间:

In [136]: timeit foo1(1000)
10000 loops, best of 3: 26.4 µs per loop
In [137]: timeit foo2(1000)
10000 loops, best of 3: 27.4 µs per loop

In [138]: timeit foo1(100000)
100 loops, best of 3: 2.39 ms per loop
In [139]: timeit foo2(100000)

1000 loops, best of 3: 1.24 ms per loop
In [140]: timeit foo1(10000000)
^[[A^[1 loop, best of 3: 571 ms per loop
In [141]: timeit foo2(10000000)
10 loops, best of 3: 175 ms per loop

对于较小的尺寸,使用outs并没有太大的区别。阵列进入10000&我们在数组重用中看到的元素大小。我怀疑使用更大的数组时,分配新数组的相对成本更高 - 更难找到可重用的块,这需要更多的OS调用等。

如果我必须先复制2个初始数组(以便重复使用),那么节省的时间就会消失。

 X = np.ones(N).copy()
 Y = np.ones(N).copy()

当你摆脱迭代时,这是一种需要考虑的变化。即使这样,SO答案也更有可能建议numbacython。我在numpy函数中看到了一些,但它并不突出。我想到的例外是np.crossnp.source(np.cross)),它使用这样的块:

        # cp0 = a1 * b2 - 0  (a2 = 0)
        # cp1 = 0 - a0 * b2  (a2 = 0)
        # cp2 = a0 * b1 - a1 * b0
        multiply(a1, b2, out=cp0)
        multiply(a0, b2, out=cp1)
        negative(cp1, out=cp1)
        multiply(a0, b1, out=cp2)
        cp2 -= a1 * b0