2014-09-12 10 views
8

Niedawno natrafiłem na great SO post, w którym użytkownik sugeruje, że numpy.sum jest szybszy niż Python sum, jeśli chodzi o obsługę tablic NumPy.Czy operacje numeryczne są szybsze dzięki funkcjom NumPy niż operatorom?

Pomyślałem, że operacje na elementach NumPy są szybsze dzięki funkcjom NumPy niż operatorzy? Jeśli tak, to dlaczego tak się dzieje?

Rozważmy następujący przykład.

import numpy as np 
a = np.random.random(1e10) 
b = np.random.random(1e10) 

Will np.subtract(a, b) być wiarygodnie szybciej niż a - b?

Odpowiedz

12

Nie, nie w znaczący sposób.

Powodem np.sum jest szybszy niż sum że sum jest realizowany na „naiwnie” iteracyjne nad iterable (w tym przypadku numpy tablicy), nazywając __add__ operatora Elements' (który nakłada znaczny narzut), podczas realizacji NumPy za z sum jest zoptymalizowany, np korzystając z tego, że zna typ (typ) elementów i że sąsiadują z pamięcią.

Nie dotyczy to np.subtract(arr1, arr2) i arr1-arr2. Ten drugi z grubsza tłumaczy ten pierwszy.

Różnica wynika z faktu, że można zastąpić operatora odejmowania w pythonie, więc tablice numpy zastępują go, aby użyć wersji zoptymalizowanej. Operacja sum nie jest jednak możliwa do zastąpienia, więc numpy udostępnia jej alternatywną zoptymalizowaną wersję.

7

Niezupełnie. Możesz jednak dość łatwo sprawdzić czasy.

a = np.random.normal(size=1000) 
b = np.random.normal(size=1000) 

%timeit np.subtract(a, b) 
# 1000000 loops, best of 3: 1.57 µs per loop 

%timeit a - b 
# 1000000 loops, best of 3: 1.47 µs per loop 

%timeit np.divide(a, b) 
# 100000 loops, best of 3: 3.51 µs per loop 

%timeit a/b 
# 100000 loops, best of 3: 3.38 µs per loop 

Funkcje numpy wydają się wolniejsze. Nie jestem pewien, czy jest to znaczące, ale podejrzewam, że może to być spowodowane dodatkowym obciążeniem wywołanym przez funkcję w związku z tą samą implementacją.

EDIT: Jak @unutbu zauważa, to prawdopodobnie dlatego, np.add i przyjaciele mają dodatkowy typ sprawdzania napowietrznych do konwertowania array-lubi tablic gdy jest to konieczne, tak rzeczy, jak np.add([1, 2], [3, 4]) prace.

+6

'np.subtract' ma dodatkowy kod do konwersji swoich argumentów na tablice. Tak więc działa 'np.subtract ([1,2,3], [4,5,6])). 'a-b' nie potrzebuje tego dodatkowego kodu, więc jest odrobinę szybszy. 'np.subtract' również obsługuje parametr słowa wyjściowego' out' ... – unutbu

+0

Dobrze, @unutbu. Obie te dodatkowe funkcje 'np.subtract 'są jednorazowymi problemami przy wejściu/wyjściu z funkcji. Są one "O (1)", jeśli ich nie używasz, więc będą coraz mniej znaczące narzuty z coraz większymi tablicami. –

3

Świetna odpowiedź @ shx2.

ja po prostu poszerzyć nieco na sum vs. np.sum:

  • wbudowaną sum będzie przejść przez tablicę, wziąć elementy jeden po drugim i konwertować je do każdego obiektu Pythona przed dodawanie ich razem jako obiektów Pythona.
  • np.sum sumuje tablicy przy użyciu zoptymalizowanego pętlę kodu macierzystego, bez konwersji z wartości (jak wskazuje shx2, to niezwykle wymaga jednorodności i przylegający zawartości tablicy)

Zamiana każde element tablicy na obiekt Pythona jest zdecydowanie głównym źródłem narzutu.

Nawiasem mówiąc, to wyjaśnia również, dlaczego jest głupi używać Pythona standard-library C array type do matematyki. sum(list) jest szybszy niż sum(array.array).

1

a-b tłumaczy się na wywołanie funkcji a.__rsub__(b). Dlatego używa metody, która należy do zmiennej (np. Skompilowany kod numpy, jeśli a jest tablicą).

In [20]: a.__rsub__?? 
Type:  method-wrapper 
String Form:<method-wrapper '__rsub__' of numpy.ndarray object at 0xad27a88> 
Docstring: x.__rsub__(y) <==> y-x 

Doc dla np.subtract(x1, x2[, out]) pokazuje, że jest to ufunc. ufunc często używają skompilowanych operacji, takich jak __rsub__, ale mogą dodać trochę narzutów, aby dopasować protokół ufunc.

W wielu innych przypadkach np.foo(x, args) oznacza: x.foo(args).

Ogólnie rzecz biorąc, jeśli funkcje i operatorzy w końcu wywołują skompilowany kod liczbowy w celu wykonania rzeczywistych obliczeń, czasy będą dość podobne, szczególnie w przypadku dużych tablic.

Powiązane problemy