Zastanawiam się nad tym od jakiegoś czasu. Jak mówi tytuł, która jest szybsza, rzeczywista funkcja lub po prostu podniesienie do połowy mocy?
AKTUALIZACJA
Nie jest to kwestia przedwczesnej optymalizacji. Jest to po prostu pytanie o to, jak faktycznie działa podstawowy kod. Jaka jest teoria działania kodu Python?
Wysłałem Guido van Rossumowi wiadomość e-mail, ponieważ naprawdę chciałem poznać różnice w tych metodach.
Mój e-mail:
Istnieją co najmniej 3 sposoby wykonania pierwiastka kwadratowego w Pythonie: math.sqrt, operator „**” i pow (x, .5). Jestem ciekawy różnic we wdrażaniu każdego z nich. Jeśli chodzi o wydajność, która jest lepsza?
Jego odpowiedź:
pow i ** są równoważne; math.sqrt nie działa dla liczb zespolonych i łączy z funkcją C sqrt (). Co do tego, który jest szybszy, nie mam pojęcia ...
źródło
math.sqrt
jest to bardziej zoptymalizowana rutyna (jak jest) i wyraźniej wyraża intencję, zawsze powinna być preferowanax**.5
. Nie jest przedwczesna optymalizacja, aby wiedzieć, co piszesz, i wybierz alternatywę, która jest szybsza i zapewnia większą przejrzystość kodu. Jeśli tak, musisz równie dobrze argumentować, dlaczego wybrałeś inne alternatywy.Odpowiedzi:
math.sqrt(x)
jest znacznie szybszy niżx**0.5
.Korzystanie z Python 3.6.9 ( notebook ).
źródło
Oto niektóre czasy (Python 2.5.2, Windows):
Ten test pokazuje, że
x**.5
jest nieco szybszy niżsqrt(x)
.W przypadku Python 3.0 wynik jest odwrotny:
math.sqrt(x)
jest zawsze szybszy niżx**.5
na innym komputerze (Ubuntu, Python 2.6 i 3.1):źródło
Ile pierwiastków kwadratowych faktycznie wykonujesz? Czy próbujesz napisać silnik graficzny 3D w Pythonie? Jeśli nie, to po co stosować kod, który jest tajemniczy, a nie łatwy do odczytania? Różnica czasu byłaby mniejsza niż ktokolwiek mógłby zauważyć w prawie każdej aplikacji, którą mogłem przewidzieć. Naprawdę nie zamierzam stawiać pytania, ale wydaje się, że posuwasz się trochę za daleko z przedwczesną optymalizacją.
źródło
W tych mikro-testach
math.sqrt
będzie wolniejszy, ze względu na krótki czas potrzebny na wyszukiwaniesqrt
w przestrzeni nazw matematyki. Możesz to nieco poprawić za pomocąNawet wtedy, uruchamiając kilka odmian w czasie, wykazują niewielką (4-5%) przewagę wydajności
x**.5
Co ciekawe, robi
przyspieszyłem to jeszcze bardziej, do różnicy prędkości w granicach 1%, z bardzo małym znaczeniem statystycznym.
Powtórzę Kibbee i powiem, że jest to prawdopodobnie przedwczesna optymalizacja.
źródło
W Pythonie 2.6
(float).__pow__()
funkcja używa funkcji C,pow()
amath.sqrt()
funkcje używająsqrt()
funkcji C.W kompilatorze glibc implementacja
pow(x,y)
jest dość złożona i jest dobrze zoptymalizowana dla różnych wyjątkowych przypadków. Na przykład wywołanie Cpow(x,0.5)
po prostu wywołujesqrt()
funkcję.Różnica w prędkości używania
.**
lubmath.sqrt
jest spowodowana przez owijarki używane wokół funkcji C, a prędkość silnie zależy od flag optymalizacji / kompilatora C używanych w systemie.Edytować:
Oto wyniki algorytmu Claudiu na mojej maszynie. Mam inne wyniki:
źródło
Za to, co jest warte (patrz odpowiedź Jima). Na moim komputerze działającym w Pythonie 2.5:
źródło
używając kodu Claudiu, na mojej maszynie nawet z „z matematyki import sqrt” x **. 5 jest szybszy, ale użycie psyco.full () sqrt (x) staje się znacznie szybszy, przynajmniej o 200%
źródło
Najprawdopodobniej math.sqrt (x), ponieważ jest zoptymalizowany pod kątem kwadratowego rootowania.
Benchmarki zapewnią odpowiedź, której szukasz.
źródło
Ktoś skomentował „szybki pierwiastek kwadratowy Newtona-Raphsona” z Quake 3 ... Zaimplementowałem go z ctypami, ale jest on bardzo wolny w porównaniu z wersjami natywnymi. Wypróbuję kilka optymalizacji i alternatywnych implementacji.
Oto inna metoda wykorzystująca struct, wychodzi około 3,6x szybciej niż wersja ctypes, ale nadal 1/10 prędkości C.
źródło
Wyniki Claudiu różnią się od moich. Używam Python 2.6 na Ubuntu na starej maszynie P4 2.4Ghz ... Oto moje wyniki:
sqrt jest dla mnie konsekwentnie szybszy ... Nawet Codepad.org NOW wydaje się zgadzać, że sqrt, w kontekście lokalnym, jest szybszy ( http://codepad.org/6trzcM3j ). Wygląda na to, że Codepad obecnie działa w Pythonie 2.5. Być może używali wersji 2.4 lub starszej, kiedy Claudiu po raz pierwszy odpowiedział?
W rzeczywistości, nawet używając math.sqrt (i) zamiast arg (i), wciąż mam lepsze czasy dla sqrt. W tym przypadku timeit2 () zajął na mojej maszynie od 0,53 do 0,55 sekundy, co wciąż jest lepsze niż 0,56-0,60 z timeit1.
Powiedziałbym, że we współczesnym Pythonie użyj math.sqrt i zdecydowanie przenieś go do lokalnego kontekstu, albo somevar = math.sqrt, albo z matematycznego importu sqrt.
źródło
Pythoniczną rzeczą, którą należy zoptymalizować, jest czytelność. W tym celu uważam, że
sqrt
najlepiej jest użyć tej funkcji. To powiedziawszy, i tak zbadajmy wydajność.Zaktualizowałem kod Claudiu dla Pythona 3, a także uniemożliwiłem optymalizację obliczeń (coś, co dobry kompilator Pythona może zrobić w przyszłości):
Wyniki są różne, ale przykładowy wynik to:
Spróbuj sam.
źródło
Problem , który ostatnio rozwiązałem SQRMINSUM , wymaga wielokrotnego obliczania pierwiastka kwadratowego w dużym zbiorze danych. Najstarsze 2 zgłoszenia w mojej historii , zanim dokonałem innych optymalizacji, różnią się jedynie zastąpieniem ** 0,5 sqrt (), zmniejszając w ten sposób czas działania z 3,74 s do 0,51 s w PyPy. Jest to prawie dwukrotność już i tak ogromnej 400% poprawy, którą zmierzył Claudiu.
źródło
Oczywiście, jeśli mamy do czynienia z literałami i potrzebujemy stałej wartości, środowisko wykonawcze Python może wstępnie obliczyć wartość w czasie kompilacji, jeśli jest napisana z operatorami - w tym przypadku nie trzeba profilować każdej wersji:
źródło
Byłoby jeszcze szybciej, gdybyś wszedł na math.py i skopiował funkcję „sqrt” do swojego programu. Twój program potrzebuje czasu na znalezienie pliku math.py, a następnie jego otwarcie, znalezienie funkcji, której szukasz, a następnie przywrócenie jej do programu. Jeśli ta funkcja jest szybsza nawet po wykonaniu kroków „wyszukiwania”, to sama funkcja musi być strasznie szybka. Prawdopodobnie skrócisz czas o połowę. W podsumowaniu:
źródło
from math import sqrt
?