numpy.cross和类似函数:他们是否在每次调用时分配一个新数组?

时间:2016-09-27 08:49:05

标签: python numpy

当我使用numpy.cross时,它将返回包含结果的数组。无法将计算到现有数组中。其他功能也是如此。

  1. 在每次通话时分配新阵列效率极低吗?
  2. 如果有,有办法加快速度吗?

2 个答案:

答案 0 :(得分:2)

函数x = np.cross(x, y)存在开销,因为它会创建一个新的NumPy数组。您可以执行if (n3 === 0) { // show error return; } for(var i = n1; n3 > 0 && i < n2 || n3 < 0 && i >= n2; i += n3) { nArr.push(i); } ,但不会抑制开销。

如果你有一个程序,这实际上是一个问题(例如通过分析程序来诊断),你最好转向特定的优化策略。想到the documentationCython

答案 1 :(得分:1)

当前版本的np.cross(截至1.9)需要花费大量精力来避免临时数组。尽可能使用输入视图,即使它必须滚动轴。它创建输出数组

cp = empty(shape, dtype)

然后注意使用out multiply-=种任务进行就地计算。

multiply(a0, b1, out=cp)
cp -= a1 * b0

然而,大多数这些操作仍然是缓冲的。即a1*b0写入临时缓冲区数组,然后从cp中减去。

通常我们不担心那些临时数组。我们让开发人员担心效率和可靠性。处理临时缓冲区是编译代码的责任,而不是我们的责任。

无缓冲的add.at文档提供了有关缓冲与否的使用的一些见解。这种无缓冲的.at方法用于常规缓冲版本无法处理的某些串行操作。但它并不是加速代码的一种方式。

听起来您希望np.cross采用out参数,认为如果可以使用

cp = np.empty(rightsize)
for a,b in zip(A,B):
   np.cross(A,B,out=cp)
   <use cp>

它会比

快很多
for a,b, in zip(A,B):
   cp = np.cross(A,B)
   <use cp>

我怀疑这是否会有所帮助。在大图中,cp=np.empty(...)是次要消费者。

但是,让我们使用np.multiply进行时间测试,这需要out

In [18]: x = np.ones((1000,1000))
In [19]: %%timeit 
    ...: y = np.multiply(x,x)
    ...: 
100 loops, best of 3: 12.4 ms per loop
In [20]: %%timeit y = np.empty(x.shape) 
    ...: np.multiply(x,x, out=y)
    ...: 
100 loops, best of 3: 6.48 ms per loop

好的,从时序循环中取出分配确实将时间缩短了一半。

但是如果你反复调用np.cross(或类似其他函数),我认为你应该更多关注重复次数而不是数组重用等细节。

np.cross(np.ones((N,3)), np.ones((N,3)))

快得多
for i in range(N):
    np.cross(np.ones(3), np.ones(3))

但是复制np.cross(它的纯Python)很容易,并修改它以取out。试一试,看看它是否有所作为。只要您使用正确大小的cp它就应该有效。您必须决定是否绕过shape行之前的dtypecp=empty...检查。