Funkcje NumPys są zaprojektowane dla tablic nie dla pojedynczych wartości lub skalarów. Mają one dość wysokie koszty ogólne, ponieważ wykonują kilka testów i konwersji, które zapewnią dużą szybkość dla dużych macierzy, ale są one kosztowne dla skalarów.
Konwersja jest bardzo oczywiste, sprawdzając typ powrotu:
>>> import numpy as np
>>> import math
>>> type(np.log(2.))
numpy.float64
>>> type(math.log(2.))
float
Z drugiej strony math
-module jest zoptymalizowany dla skalarów. Więc nie potrzebują wielu kontroli (myślę, że są tylko dwa: Konwertuj na float
i sprawdź, czy jest to <= 0
). Dlatego też math.log
jest szybszy dla skalarów w porównaniu do numpy.log
.
Ale jeśli operujesz na tablicach i chcesz wziąć logarytm wszystkich elementów w tablicy NumPy może być znacznie szybszy. Na moim komputerze, jeśli limit czasu na wykonanie np.log
na tablicy porównaniu math.log
każdej pozycji na liście, a następnie czas wygląda inaczej:
arr = np.arange(1, 10000000)
%timeit np.log(arr)
201 ms ± 959 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
lst = arr.tolist()
%timeit [math.log(item) for item in lst]
8.77 s ± 63.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Więc np.log
będzie o wiele rzędów wielkości szybciej na macierzach (to więcej niż 40 razy szybciej w tym przypadku)! I nie musisz sam pisać żadnej pętli. Ponieważ ufunc np.log
będzie poprawnie działał na wielowymiarowych tablicach numpy, a także pozwala na wykonanie operacji w miejscu.
Zasada: jeśli macie tablicę z tysiącami przedmiotów, NumPy będzie szybsze, jeśli macie skalary lub tylko kilkadziesiąt pozycji: math
+ wyraźna pętla będzie szybsza.
Również nie używaj kodu time
dla kodu czasu. podczas taktowania Są dedykowane moduły, które dają bardziej dokładne wyniki, lepsze statystyki i wyłączyć zbieranie śmieci:
ja zazwyczaj używają %timeit
który jest wygodnym otokiem wokół funkcji timeit
, ale wymaga IPython. Już wygodnie wyświetlają średnią wyników i odchylenie oraz wykonują niektóre (w większości) użyteczne statystyki, takie jak wyświetlanie wyniku "najlepszego z 7" lub "najlepszego z 3".
Niedawno analizowano zachowanie w czasie wykonywania funkcji NumPy dla another question niektóre punkty zastosowanie również tutaj.
Jestem dość zainteresowany odpowiedzią. Specjalnie dlatego, że właśnie wszedłem w kod źródłowy, a funkcja jest trudna do prześledzenia. Po lewej stronie znajduje się kod źródłowy, napisany: '# prawdziwy podpis nieznany; przywrócono z __doc__'. Czy ktoś może również wyjaśnić, w jaki sposób działa kod źródłowy? –
Odpowiedź brzmi: http://stackoverflow.com/questions/3650194/are-numpys-math-functions-faster-than-pythons?rq=1 – Bathsheba
'np.log' jest zoptymalizowany do działania na tablicach wartości, a nie pojedyncze wartości. Na przykład 'np.log (np.arange (1 10000000))' (log tablicy liczb całkowitych w tym zakresie) zajmuje dla mnie około 120ms. –