Šlo by dodělat i porovnání s pypy?
Zkusil jsem si totiž porovnat rychlost toho benchmarku u sebe na počítači mezi pythonem2/3 a pypy. Překvapuje mě, že poměr rychlosti vychází mezi pythonem a pypy u dvou mnou zkoušených příkladů více než 30× rychlejší (resp. více jak 15× rychlejší) oproti cca 8× rychlejšímu rpythonu v článku (oproti pythonu).
S takovým výsledkem mi přijde zbytečné piplat se s rpythonem, když to stačí spustit v pypy a výsledek je ještě lepší (testoval jsem jen 2 případy).
2048×2048:
Python: 1m9,365s
Python3: 1m13,470s
Pypy: 0m2,191s (31,66× rychlejší resp. 33,53×)
4096×4096:
Python: 4m50,124s
Python3: 4m50,474s
Pypy: 0m18,403s
Můj PC je zřetelně pomalejší než použitý v článku (zhruba poloviční výkon při porovnání běhu pythonu) a přesto je výsledek v běhu u 2048×2048 2× rychlejší než rpython běžící na PC v článku a u 4096×4096 stejně rychlý jako rpython běžící na PC v článku. Čím to?
Ahoj, přesně na to se chystám příště. PyPy sice používá RPython, ale má k dispozici plnohodnotný JIT a ten to může ještě víc zoptimalizovat. Měl bys vidět, že první běhy pro malé rozlišení budou pomalejší a potom - od nějaké hranice - už začne JIT vyhrávat.
Jen pro zajímavost - byly výsledky binárně shodné? Mě JIT optimalizoval výpočty tak, že výsledky byly vlastně přesnější (-ffast-math atd.).
Bez uvedení explicitní informace o typech (a to prakticky všude) byl rozdíl výkonu oproti interpretru dost malý, tuším mezi 30-40%. Přidání anotací o typech argumentů a funkcí to vylepšilo dost výrazně, ale přišlo mi, že je to víc práce, než upravit kód pro RPython nebo jen odladit pro PyPy - ale tady skutečně záleží na konkrétním algoritmu, protože velmi dynamický kód se upravuje strašně špatně (a typové anotace se přidávají taky špatně).
Zkusím se o tom víc rozepsat příště, protože to možná napsáno v jednom odstavci vyznívá, že Cython je špatný. Určitě má své místo, stejně jako Numba.
Vlastně Cython a RPython se snaží řešit podobný problém - rozlišit typy už v době překladu - a každý na to jde trošku jinak (typové anotace vs flow diagram). Oboje má svoje omezení.
Ano, Cython take vnímám jako velice záludný jazyk: jakmile někde nezná typ, zavolá se celá Pythoní mašinérie pro univerzální typ. Je nutné typ deklarovat. Ale nejde tam zapnout kontrolu, že by deklaraci typu vyžadoval.
Navíc občas je schopný si typ domyslet, záleží například na jedné ze dvou syntaxí for cyklu, kterou použijete.
V praxi to znamená že musím často kontrolovat generovaný C kód (zobrazený v pěkném html), abych objevil, kam mi cython nacpal spoustu kódu navíc, který jsem nechtěl, a pak vymyslel, jak mu to rozmluvit.
Cython je dobrý jako interface umožňující zapojení kompilovaných kousků kódu do pythonovského a numpy programu.
Ale kdyby měl dialekt vyžadující deklaraci typů, odstranilo by to mnoho pastí. A kdyby tento kompilovaný kód šlo psát rovnou v C, byla by to dokonce i příjemná práce. Takhle myslím v C, šifruji to do pseudo-pythonu, a třesu se strachy, kde zapomenu deklarovat proměnnou a pak to budu zdlouhavě hledat.
V Cythonu se dobře dostanu k underlying datům numpy array; bojím se, že pro numbu nebo jiné přístupy to není tak propracované a přenos velkých polí mezi C a numpy by vždy zdržoval.
Štěpán
Ahoj, přesně na to se chystám příště
Už se těším...
Měl bys vidět, že první běhy pro malé rozlišení budou pomalejší a potom - od nějaké hranice - už začne JIT vyhrávat.
To se dá předpokládat, že než se spustí s jit, že to trvá a projeví se krátkých běhů více...
Jen pro zajímavost - byly výsledky binárně shodné?
To jsem neřešil, prostě jsem spustil jeden a ten samý .py kód pod python2, python3 a pypy a porovnával délku běhu.
Jen pro zajímavost - byly výsledky binárně shodné?
To jsem neřešil, prostě jsem spustil jeden a ten samý .py kód pod python2, python3 a pypy a porovnával délku běhu.
Ono je to v tomto ohledu zajímavé a Pythoní specifikace to moc myslím vlastně ani neřeší - totiž některé optimalizace FPU operací vedou k tomu, že jsou výsledky přesnější na nějakém n-tém místě, protože se v závislosti na architektuře atd. může počítat s větší přesností, než je double. To vede k tomu, že pár pixelů v obrázku může mít nepatrně odlišnou hodnotu (třeba jen o jedničku). RPython dává naprosto shodné výsledky s CPythonem, ale protože nemáme obdobu strictfp z Javy, tak to vlastně jen znamená to, že se drží původní sémantiky co nejvíc to jde (a některé optimalizace buď neprovádí, nebo přepíná stav FPU). Takže jsem se jen ptal proto, že odlišné výsledky můžou znamenat, že si překladač dovolil optimalizovat ještě trošku drastičtějším způsobem.