2011-09-23 75 views
6

我想写一个函数,对数组执行数学运算并返回结果。一个简单的例子可以是:改变numpy函数输出数组

def original_func(A): 
    return A[1:] + A[:-1] 

对于高速化,并避免分配用于每个函数调用一个新的输出阵列,我想有输出数组作为参数,并改变它在适当位置:

def inplace_func(A, out): 
    out[:] = A[1:] + A[:-1] 

然而,在下面的方式调用这两个函数时,

A = numpy.random.rand(1000,1000) 
out = numpy.empty((999,1000)) 

C = original_func(A) 

inplace_func(A, out) 

原有的功能似乎是快两倍作为就地功能。这怎么解释?不应该因为它不需要分配内存而使得就地功能更快?

回答

5

认为,答案是:

在这两种情况下,你计算A[1:] + A[:-1],并在这两种情况下,你实际上创建中间矩阵。

然而,在第二种情况下会发生什么呢?显式地将复制到一个保留的内存中。复制这样一个数组需要大约与原始操作相同的时间,所以你实际上将时间加倍。

综上所述行动,在第一种情况下,你这样做:

compute A[1:] + A[:-1] (~10ms) 

在第二种情况下,你做

compute A[1:] + A[:-1] (~10ms) 
copy the result into out (~10ms) 
+1

作为一个解决方案:我认为* *你必须自己做循环,以避免在奥利弗的回答中描述的中间阵列。或者,也许像http://code.google.com/p/numexpr/可以帮助你?这[问题](http://stackoverflow.com/questions/2937669/linear-combinations-in-python-numpy)也看起来相关。 – gspr

+0

我认为你可以通过这样做来避免中间数组:'out [:] = A [1:]; out + = A [: - 1]'当然你的实际算法可能会变得更加难以精简。当然,不惜一切代价尽量避免循环。你可以用累积和ufuncs做些创造性的事情。 – Paul

-1

我跟奥利弗的解释一致。如果您想要在位执行操作,则必须手动循环访问阵列。这将会慢得多,但是如果你需要速度,你可以求助于Cython,它可以让你获得纯C实现的速度。