2017-04-11 149 views
0

我通读了Numpy Tutorial,它是说,一个示例代码这样的快速算法:numpy的阵列上

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

是缓慢的,因为它以持有的A值创建了三个不同的中间阵列, 2*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的速度差异?

+0

“在第二个代码,X和Y仍显示为中间阵列中创建” - 什么?不,他们是投入。代码重用它们来保存中间结果(废弃原始数据),而不是分配新数组。 – user2357112

+1

查看http://stackoverflow.com/questions/27293830/utility-of-parameter-out-in-numpy-functions关于使用'out' –

+0

@ThierryLathuille难题,这是有道理的,为什么第二个代码片段可以是有用的。 –

回答

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并没有太大的差别。这是阵列进入元素大小的时候,我们看到数组重用的好处。我怀疑,更大的阵列分配新的相对成本更大 - 难以找到可重用的块,然后需要更多的调用操作系统,等等。

而且,如果我不得不复制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 
2

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

如果您计划重复使用X和Y进行多个不相互依赖的操作(也就是说,您为此操作乘以X和Y而不是未来操作),那么您可能需要使用初始方法你不必撤消操作。

+0

是的,我现在看到了。第二种方法更快,因为它消除了创建新阵列所花费的时间? –