2011-09-23 12 views
6

Próbuję napisać funkcję, która wykonuje operację matematyczną na tablicy i zwraca wynik. Uproszczony przykład mogą być:Zmiana macierzy funkcji numpy na miejscu

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

Aby przyspieszyć i uniknąć przydzielenie nowego układ wyjściowy dla każdego wywołania funkcji, ja jak do macierzy wyjściowej jako argumentu, i zmieniać go w miejscu:

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

jednak podczas wywoływania tych dwóch funkcji w następujący sposób

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

C = original_func(A) 

inplace_func(A, out) 

pierwotna funkcja wydaje się być dwukrotnie szybciej jako funkcja lokalna. Jak to wyjaśnić? Czy funkcja lokalna nie powinna być szybsza, ponieważ nie musi przydzielać pamięci?

Odpowiedz

5

myślę że odpowiedź jest następująca:

W obu przypadkach obliczyć A[1:] + A[:-1] iw obu przypadkach rzeczywiście stworzyć macierz pośrednią.

Co jednak dzieje się w drugim przypadku, oznacza to, że jawnie skopiuj całą dużą nowo przydzieloną tablicę do zarezerwowanej pamięci. Kopiowanie takiej tablicy zajmuje mniej więcej tyle samo, co oryginalna operacja, więc w rzeczywistości podwoisz czas.

Podsumowując-up, w pierwszym przypadku zrobić:

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

W drugim przypadku można zrobić

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

jak w przypadku rozwiązania: * I * myślę musisz zrobić pętelki się uniknąć tablic pośrednich opisane w odpowiedzi Oliviera. A może coś takiego jak http://code.google.com/p/numexpr/ może ci pomóc? To [pytanie] (http://stackoverflow.com/questions/2937669/linear-combinations-in-python-numpy) również wygląda na trafne. – gspr

+0

Myślę, że można uniknąć pośredniej tablicy, wykonując następujące czynności: 'out [:] = A [1:]; out + = A [: - 1] 'Oczywiście twoje aktualne algo prawdopodobnie będzie trudniejsze do usprawnienia. Oczywiście spróbuj uniknąć pętli za wszelką cenę. Często są kreatywne rzeczy, które możesz zrobić, gromadząc i ufając ... – Paul

-1

zgadzam się z Olivers wyjaśnienia. Jeśli chcesz wykonać operację inplace, musisz ręcznie przeprowadzić pętlę w swojej tablicy. Będzie to znacznie wolniejsze, ale jeśli potrzebujesz prędkości, możesz uciekać się do Cythona, który zapewnia szybkość czystej implementacji C.

Powiązane problemy