2013-06-27 19 views
7

(Jest to uzupełnienie Statistical profiler for PyPy)Optymalizacja dla pypy

biegnę kodu Pythona pod pypy i chciałbyś ją zoptymalizować.

W języku Python użyłbym statprof lub lineprofiler, aby wiedzieć, które dokładnie linie powodują spowolnienie i próbują je obejść. W PyPy oba narzędzia nie generują jednak sensownych wyników, ponieważ PyPy może zoptymalizować niektóre linie. Wolałbym również nie używać cProfile, ponieważ jest mi bardzo trudno destylować, która część zgłaszanej funkcji jest wąskim gardłem.

Czy ktoś ma wskazówki, jak postępować? Być może inny profiler, który działa ładnie w PyPy? Ogólnie rzecz biorąc, jak można zoptymalizować kod Pythona dla PyPy?

Odpowiedz

5

Jeśli zrozumiesz, w jaki sposób działa architektura PyPy, przekonasz się, że próba wskazania poszczególnych linii kodu nie jest tak naprawdę wydajna. Zaczynasz od interpretera Pythona napisanego w RPython, który następnie przechodzi przez JIT śledzący, który generuje wykresy przepływu, a następnie transformuje te wykresy w celu optymalizacji interpretera RPython. Oznacza to, że układ kodu Pythona uruchamianego przez interpreter języka RPython będącego JIT może mieć bardzo odmienną strukturę niż faktycznie zoptymalizowany asembler. Ponadto należy pamiętać, że JIT zawsze działa w pętli lub funkcji, więc uzyskiwanie statystyk liniowych nie ma takiego znaczenia. W związku z tym myślę, że cProfile może być dobrym rozwiązaniem dla Ciebie, ponieważ pozwoli Ci zorientować się, gdzie skoncentrować optymalizację. Kiedy już wiesz, które funkcje są wąskimi gardłami, możesz poświęcić wysiłki optymalizacyjne na te wolniejsze funkcje, zamiast próbować naprawić pojedynczą linię kodu Pythona.

Należy pamiętać, że PyPy ma bardzo różne właściwości wydajności niż cPython. Zawsze staraj się pisać kod w tak prosty sposób, jak to tylko możliwe (to nie znaczy tak mało jak to możliwe). Istnieje kilka innych heurystyk, które pomagają w takich sytuacjach, jak używanie wyspecjalizowanych list, używanie obiektów przez dyktowanie, gdy masz niewielką liczbę w większości stałych kluczy, unikanie rozszerzeń C przy użyciu API Python, itp.

Jeśli naprawdę, naprawdę nalegasz o próbach optymalizacji na poziomie linii. Istnieje kilka opcji. Jedna z nich nazywa się JitViewer (https://bitbucket.org/pypy/jitviewer), co pozwala uzyskać bardzo niski poziom tego, co robi JIT z twoim kodem. Na przykład możesz nawet zobaczyć instrukcje asemblera, które odpowiadają pętli Pythona. Korzystając z tego narzędzia, możesz naprawdę zrozumieć, jak szybko PyPy będzie się zachowywać z pewnymi częściami kodu, ponieważ teraz możesz robić głupie rzeczy, takie jak liczba instrukcji asemblera użytych w pętli lub coś takiego.

+0

Jaka jest Twoja sugestia? –

+1

Moja sugestia polegała na użyciu cProfile, biorąc pod uwagę, jak PyPy faktycznie działa. Moją drugą sugestią było użycie JitViewer, jeśli naprawdę potrzebujesz niskiego poziomu zrozumienia cech wydajności twojego kodu. – jlund3

+1

Transformacje wykresów przepływu są stosowane podczas kompilowania i optymalizacji kodu RPython implementującego samego interpretera, * nie * Twojego kodu Pythona. Transformacje te są odpowiednikiem transformacji, które kompilator C stosuje do kodu C interpretera CPython, i nie mają nic wspólnego z kodem Pythona użytkownika końcowego. JIT PyPy przedstawia jednak problem, o którym mówisz; gorące pętle będą prawdopodobnie kompilowane przez JIT do wielu różnych bloków kodu zespołu, co sprawia, że ​​mapowanie wydajności z powrotem do indywidualnych instrukcji Pythona jest trudne. – Ben