Wydajnosc Pythona

Transkrypt

Wydajnosc Pythona
Plan
1
Uwagi na temat wydajności CPython’a
2
Podstawowe techniki poprawiające wydajność obliczeniową
3
Podstawowe techniki poprawiające zużycie pamięci
krótkie opisy modułów
1
array - jak oszczędzić na pamięci
2
ctypes - prosta integracja z C
3
multiprocessing - zrównoleglanie programu
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
1 / 10
Ogólnie
Wydajność obliczeniowa
wydajność Pythona zależy od użytego intepretera
CPython nie jest zbyt szybki (wolniejszy niż Java)
Operacje oraz typy danych wbudowane w intepreter są zwykle szybsze.
Duża część modułów Pythona jest zaimplementowana w C/C++ co
przekłada się na odpowiednią wydajność
Typy wbudowane również zaimplementowane są w C
Zużycie pamięci - CPython
Niektóre obiekty czysto Pythonowe zajmują więcej miejsca w pamięci
niż można by się spodziewać
CPython rezerwuje sobie listy obiektów podręcznych które czasami
zajmują zbyt dużo miejsca
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
2 / 10
Wydajność obliczeniowa
czyli dlaczego nie lubimy kropek. . .
Redukcja ilości odwołań do słowników
Każde odwołanie się do obiektu który nie znajduje się w aktualnej
przestrzeni adresowej kosztuje dodatkowe sprawdzenie w słowniku
a ponieważ funkcje też są obiektami to. . .
tablica = []
for i in xrange(1000000):
tablica.append(i)
. . . to szybciej będzie w ten sposób
tablica = []
dodaj_element = tablica.append
for i in xrange(1000000):
dodaj_element(i)
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
3 / 10
Wydajność obliczeniowa
każda “kropka” więcej spowalnia program
class Obiekt(object):
def __init__(self):
self.tablica = []
o = Obiekt()
for i in xrange(1000000):
o.tablica.append(i)
jeśli można najlepiej jest użyć funkcji wbudowanej. . .
tablica = range(1000000)
. . . lub generator expression
tablica = [i for i in xrange(1000000)]
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
4 / 10
Wydajność obliczeniowa
importowanie
Z tego samego powodu co w poprzednich przykładach lepiej stosować
formę importu
from modul import funkcja
funkcja()
niż
import modul
modul.funkcja()
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
5 / 10
Zużycie pamięci
CPython tworzy bufory obiektów prostych (np. int) do ponownego
wykorzystania
>>> a = range(10000000)
>>> del a
oznacza to że po wykonaniu drugiego polecenia ilość pamięci zajmowanej
przez Python’a nie spadnie do poziomu początkowego
uwagi
tablica 10 000 000 liczb (int) zajmuje około 300 MB
W normalnej pracy efekt ten nie jest zauważalny i pojawia się jedynie
wtedy gdy chcemy przetwarzać duże ilości danych w jednym
momencie.
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
6 / 10
moduł array
array pozwala na wydajne przechowywanie wartości tego samego typu
dd id=/dev/zero of=100MB bs=1048576 count=100
array będzie zajmować w pamięci tyle ile się spodziewamy i po
skasowaniu pamięć zostanie zwolniona
from array import array
a = array("c")
with open("100MB") as f:
a.fromfile(f, 100*1024*1024)
raw_input()
del a
raw_input()
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
7 / 10
moduł multiprocessing
reklama
Zrównoleglanie programów w Pythonie jest bardzo proste.
program jednordzeniowy
from math import sqrt
pierwiastki = sum(map(sqrt, range(10000000)))
program wielordzeniowy
from math import sqrt
def przelicz(zakres):
return sum(map(range(*zakres)))
if __name__ == "__main__":
from multiprocessing import Pool
procesy = Pool()
pierwiastki_partial = procesy.map(przelicz, [(0, 5000000), (5000000, 10000000)])
pierwiastki = sum(pierwiastki_partial)
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
8 / 10
moduł ctypes
reklama
Z Pythona można załadować i używać dowolnych współdzielonych
bibliotek w C. Zarówno pod Windows jak i Linux.
program w czystym Pythonie
from math import sqrt
pierwiastki = sum(map(sqrt, range(10000000)))
funkcja w C
# include <math.h>
float pierwiastki(float* tablica, int rozmiar){
float wynik = 0;
for (int i = 0; i < rozmiar; i++){
wynik += sqrt(tablica[i]);
};
return wynik;
};
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
9 / 10
moduł ctypes
Kompilujemy kod w C:
gcc -O3 -fPIC funkcja.c --shared -o funkcja.o -std=c99 -ggdb
nowy program w Pythonie
from ctypes import cdll, c_float, c_void_p
from array import array
lib = cdll.LoadLibrary("funkcja.o")
tablica = array("f", xrange(10000000))
pierwiastki_funkcja = lib.pierwiastki
pierwiastki_funkcja.restype = c_float
pierwiastki_funkcja.argtypes = [c_void_p, c_int]
wskaznik, liczba_elementow = tablica.buffer_info()
pierwiastki = pierwiastki_funkcja(wskaznik, liczba_elementow)
Łukasz Ligowski, Sławomir Walkowiak (ICM UW)
Wydajność Pythona
19 stycznia 2010
10 / 10

Podobne dokumenty