2011-09-23 73 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實現的速度。