Codon - brzo izvođenje koda u Pythonu

Codon - brzo izvođenje koda u Pythonu

Ubrzanje i preko 100 puta

Započnimo današnji tekst s nekoliko općepoznatih tvrdnji o programskom jeziku Python.

Python je jedan od najpopularnijih programskih jezika na svijetu i kao takav se koristi za razvoj aplikacija na najrazličitijim područjima – od rješavanja jednostavnih problema na desktop računalima pa sve do modeliranja najsloženijih problema na području umjetne inteligencije. Budući da je sam programski jezik relativno jednostavan za učenje u usporedbi s nekim drugim programskim jezicima, vrlo često ga koriste i IT neprofesionalci koji dobro poznaju svoje područje, to jest nisu i/ili ne žele biti ovisni o tome da im “pravi” programeri napišu sve potrebne programe. U budućnosti će uz pomoć najmodernijih AI sustava biti još manje potrebe za nečim takvim, ali to je već tema za neki drugi tekst.

Istovremeno, o Pythonu kruže (opravdane) priče da je u usporedbi s drugim programskim jezicima jako spor u izvođenju što je zapravo i sasvim očekivano kad se uzme u obzir da se Python programi kod izvođenja interpretiraju umjesto da se izvode prevedene verzije programskog koda kao u većini “brzih” programskih jezika.

Obje tvrdnje smo demonstrirali s dvije prateće slike uz tekst jer one to jasno pokazuju. Naravno, ovisno o načinu i metodologiji mjerenja, rezultati o popularnosti i brzini izvođenja programskih jezika se mogu razlikovati od ovih rezultata, ali je zapravo sve to “tu negdje”. Drugim riječima, Python je danas postao narodski rečeno “katica za sve”. Da je bar još samo malo brži.

Prije nego krenemo dalje s tekstom, napišimo još jedan komentar u vezi s brzinom Pythona, jer se to često ignorira u praksi. Brzina programskog jezika je izuzetno bitna ako u njemu sve pišete ispočetka ili ako koristite biblioteke napisane u tom istom programskom jeziku (koje se kod izvođenja također interpretiraju). Međutim, ako vam Python služi prvenstveno zato da bi u njemu pripremili početne podatke, a onda ih predali na izvođenje nekakvoj AI biblioteci ili nečem sličnom (već prevedenoj u izvršni oblik za konkretni operativni sustav), te da bi na kraju prikazali vraćene rezultate, onda osnovna brzina programskog jezika zapravo ni nije toliko važna. U takvim situacijama će se u Pythonu možda potrošiti nekoliko nepotrebnih postotaka više od ukupnog vremena izvođenja programa. Međutim, ako niste zadrti perfekcionista u svemu što radite, priznat ćete da se isključivo u Python dijelu ne mogu postići prevelika poboljšanja u ukupnoj brzini izvođenja.

 

1. Što je Codon?

Pretpostavimo sada suprotno – da uistinu jeste perfekcionista koji ne voli da se njegov program izvodi nepotrebno sporo ni u jednom svojem dijelu. Ili čak i da niste perfekcionista, ali vam je na raspolaganju samo izvorna Python biblioteka za rješavanje vašeg problema, što znači da će se izvoditi jednako sporo kao i ostatak programa. Postoji li nekakvo rješenje za ubrzavanje izvođenja Python koda? Srećom, odgovor je pozitivan, a ime mu je Codon.

Codon je program prevoditelj za prevođenje Python koda u izvršni oblik, baš kao što je to slučaj kod drugih “brzih” programskih jezika. Prema provedenim mjerenjima, često se može očekivati ubrzanje u izvođenju programa veće od 100 puta po jednoj niti izvođenja.

Evo primjera ubrzanja izvođenja interpretiranog Python koda pomoću Codona na temelju dokumentacije proizvođača.

from time import time

def fib(n):

return n if n < 2 else fib(n - 1) + fib(n - 2)

 

t0 = time()

ans = fib(40)

t1 = time()

print(f’Computed fib(40) = {ans} in {t1 - t0} seconds.’)

 

Vrijeme izvođenja u Pythonu i Codonu:

$ python3 fib.py

Computed fib(40) = 102334155 in 17.979357957839966 seconds.

 

$ codon run -release fib.py

Computed fib(40) = 102334155 in 0.275645 seconds.

 

Kad smo već spomenuli niti izvođenja, istaknimo odmah i to da Codon podržava paralelno višenitno izvođenje koda te da ima ugrađenu svu potrebnu podršku za upravljanje asinkronim operacijama. Na prvi pogled sve to izgleda super, zapravo fantastično, kad ne bi bilo jedne “sitnice”. Codon nije 100% kompatibilan s interpreterskim verzijama, odnosno sa standardnom implementacijom programskog jezika Python (CPython). Drugim riječima, ne možete prevesti baš svaki Python program. I za mnoge čitatelje je tu možda kraj priče u vezi s Codonom. Ali ipak nije sve tako crno, što ćemo probati objasniti u nastavku.

Za razliku od velike većine programskih jezika gdje se prvo isplanira i napravi programski jezik, koji se onda primjenjuje na različitim područjima uz eventualne nužne i malo manje nužne nadogradnje, Codon je nastao potpuno suprotno. To jest, nastao je kao alat za rješavanje konkretnog problema s područja genetike, odnosno rada s genomima. U stručnoj terminologiji, takvi programski jezici nastali s točno određenim ciljem rješavanja konkretnog problema nazivaju se DSL (Domain Specific Language). U ovom slučaju cilj je bio napraviti specijalizirani programski jezik kao podršku istraživačima genoma koji su poznavali i koristili Python. Tako da mogu sami pripremati svoje modele u Pythonu, ali da se oni izvode mnogo brže nego kod interpretirane verzije. Postojeća brzina izvođenja “običnog” Pythona jednostavno nije bila dovoljno dobra za primjenu u praksi.

Zato su u Codonu prije svega implementirane Python naredbe koje su bile potrebne za izradu takvih modela. Ako koristite nešto izvan toga, onda ste u problemu. Ali ponovo, nije sve tako crno, što ćete vidjeti u nastavku teksta.

Zbog dobrih rezultata na rješavanju spomenutih problema postignutih u praksi, tvorci Codona su zaključili da bi mogli krenuti korak dalje i napraviti posebnu tvrtku koja se bavi Codonom. Tako je nastao Exaloop. Stvaranje takve tvrtke trebalo bi značiti da se Codon pojavio kako bi se zadržao među programerima, te da će se s vremenom u nove verzije dodavati sve veći stupanj kompatibilnosti sa standardnim Pythonom.

Na stranicama proizvođača (https://docs.exaloop.io/codon/ ) možete pronaći sve detalje o korištenju Codona, kao i opis trenutnog stanja kompatibilnosti i slično. A na adresi https://docs.exaloop.io/codon/general/roadmap možete provjeriti kako izgledaju planovi oko budućih verzija i rješavanje problema oko kompatibilnosti. Spomenimo na ovom mjestu i sam repozitorij za preuzimanje Codona (https://github.com/exaloop/codon).

 

 Untitled-2-CROP.gif

Rezultati mjerenja: Poboljšanja u brzini izvođenja programskog koda koje nudi Codon

 

Untitled-2-CROP-2.gif

 Usporedba popularnosti Pythona prema drugim jezicima: Prema PLPY (PopularitY of Programming Language)

 

Slika02.jpg

Usporedba brzine Pythona prema drugim jezicima: Prema https://github.com/niklas-heer/speed-comparison/blob/master/README.md

 

2. Kako riješiti probleme s nekompatibilnosti?

Autori alata svjesni su da trenutna nekompatibilnost s Pythonom realno predstavlja veliki problem u širenju Codona. Zato su se potrudili da program za prevođenje što detaljnije opiše svaki uočeni problem u postojećem Python kodu, kako bi se Codon što lakše zamijenio ekvivalentom.

U slučaju da je takvih mjesta previše, to jest da bi postojeći Python kod zahtijevao previše prerada, onda možete krenuti drugim putem. Umjesto prevođenja cijelog Python projekta u izvršni oblik pomoću Codona, možete prevesti samo neke njegove dijelove. Ako su to kritični dijelovi koji jako usporavaju cijeli projekt, evo prilike da jako ubrzate izvođenje projekta, a pri tome se ne morate mučiti s uklanjanjem svih uočenih problema s kompatibilnosti.

Za prevođenje dijelova Python projekta koristi se poseban Codon modul pod nazivom @codon.jit decorator. Kako izgleda takvo “djelomično” prevođenje početnog Python projekta proizvođač je demonstrirao na sljedećem primjeru.

import codon

from time import time

 

def is_prime_python(n):

if n <= 1:

return False

for i in range(2, n):

if n % i == 0:

return False

return True

@codon.jit

def is_prime_codon(n):

if n <= 1:

return False

for i in range(2, n):

if n % i == 0:

return False

return True

 

t0 = time()

ans = sum(1 for i in range(100000, 200000) if is_prime_python(i))

t1 = time()

print(f’[python] {ans} | took {t1 - t0} seconds’)

 

t0 = time()

ans = sum(1 for i in range(100000, 200000) if is_prime_codon(i))

t1 = time()

print(f’[codon] {ans} | took {t1 - t0} seconds’)

 

U prethodnom primjeru ista stvar je napravljena u interpretiranom Pythonu i u Codonu uz pomoć spomenutog “dekoratora”. A razlike u brzini izvođenja su ponovo drastične:

[python] 8392 | took 39.6610209941864 seconds

[codon] 8392 | took 0.998633861541748 seconds

 

Slika05.jpg

 Arhitektura Codona: Od izvornog do pravog izvršnog koda dolazi se u nekoliko koraka

 

Postoji još jedna zanimljiva mogućnost u korištenju Codona. Pretpostavimo da na raspolaganju imate programere koji dobro poznaju C/C++ i mogli bi bez problema napraviti nekakav „framework“ projekta (korisničko sučelje, pristup podacima na “nekakvim čudnim uređajima” ili različitim izvorima podataka i slično), ali nisu baš neki eksperti za glavno područje problema. Istovremeno u timu imate top stručnjake za to isto područje koji bar ponešto znaju i Python. U tom slučaju možete organizirati projekt tako da iz glavnog C/C++ projekta pozivate Codon dijelove, a njih su sami razvili spomenuti stručnjaci za glavno područje. Slijedi primjer pripreme takvog projekta prema dokumentaciji proizvođača.

Dio Codon koda koji se želi “izložiti” programskom jeziku C/C++ treba dodatno označiti “export” dijelom.

@export

def foo(n: int):

for i in range(n):

print(i * i)

return n * n

 

I onda ga treba prevesti u izvršni oblik kao posebnu podijeljenu biblioteku.

codon build --relocation-model=pic --lib -o libfoo.so foo.codon

 

Nakon toga se takva biblioteka može uključiti u C/C++ projekt na sljedeći način:

#include <stdint.h>

#include <stdio.h>

 

int64_t foo(int64_t);

// In C++, it would be:

// extern “C” int64_t foo(int64_t);

 

int main() {

printf(“%llu\n”, foo(10));

}

 

I sve skupa može se prevesti u izvršni oblik s gcc ili g++:

gcc -o foo -L. -lfoo foo.c

 

Ako vam se prethodni oblik prevođenja čini malo čudnim za Windows okruženje, potpuno ste u pravu. Codon u ovom trenutku još uvijek nije u potpunosti prilagođen Windowsima, nego prije svega Linux platformama. Ali prema tvorcima alata ne bi trebalo postojati bitnijih zapreka da se uskoro pojavi i Windows verzija (ponovo razlog zašto je osnovan Exaloop).

 

3. Podrška za višenitno izvođenje i GPU

 Već smo spomenuli da Codon nudi mogućnost višenitnog izvođenja Python koda, a ona se temelji na ugrađenoj podršci za OpenMP (Open Multi-Processing). Pisanje takvog koda je maksimalno pojednostavljeno, iako postoje i sve potrebne funkcije za detaljno upravljanje nitima kad se za tim ukaže potreba. Na primjer, sljedeći dio programskog koda omogućava njegovo izvođenje u zadanih pet niti.

 @par(num_threads=5)

for i in range(10):

import threading as thr

print(‘hello from thread’, thr.get_ident())

 

Codon nudi još jednu zanimljivu mogućnost za ubrzavanje izvođenja programskog koda. To je izravna podrška za GPU procesore. U ovom trenutku samo za NVIDIA procesore, ali sasvim dovoljno za početak.

Kako se određuje da će se neki dio koda izvoditi uz pomoć GPU i dodatnih NumPy i Matplotlib biblioteka prikazano je na sljedećem primjeru (dio označen s @gpu.kernel).

from python import numpy as np

from python import matplotlib.pyplot as plt

import gpu

 

MAX = 1000 # maximum Mandelbrot iterations

N = 4096 # width and height of image

pixels = [0 for _ in range(N * N)]

 

def scale(x, a, b):

return a + (x/N)*(b - a)

 

@gpu.kernel

def mandelbrot(pixels):

idx = (gpu.block.x * gpu.block.dim.x) + gpu.thread.x

i, j = divmod(idx, N)

c = complex(scale(j, -2.00, 0.47), scale(i, -1.12, 1.12))

z = 0j

iteration = 0

 

while abs(z) <= 2 and iteration < MAX:

z = z**2 + c

iteration += 1

 

pixels[idx] = int(255 * iteration/MAX)

 

mandelbrot(pixels, grid=(N*N)//1024, block=1024)

plt.imshow(np.array(pixels).reshape(N, N))

plt.show()

 

Prema mjerenjima provedenim od strane samog proizvođača Codona, takav programski kod za pripremu i iscrtavanje fraktala se uz pomoć GPU izvodi čak 450 puta brže!!!

 

Zaključak

Prema svemu navedenom, Codon je sjajan alat, ali nije za svakoga. Zapravo, prije bi rekli da je namijenjen ograničenom broju pojedinaca/timova koji u svojim projektima zbilja ozbiljno koriste Python, a do sada su njihova rješenja radila jednostavno presporo za ozbiljnije korištenje.

Prevođenjem Python koda uz pomoć Codona (cijelog projekta ili samo kritično sporih dijelova), mogućnosti istovremenog korištenja više niti u programu, kao i podrške za GPU hardver, složeni projekti mogu postati cijele redove veličine brži u praksi. U svakom slučaju, Codon je vrlo ozbiljan alat koji bi mogao imati priličan utjecaj na Python svijet, a posredno i na različite AI projekte i slično.

A postojanje tvrtke Exaloop trebalo bi biti garancija da će u budućnosti biti i sve manje problema s kompatibilnošću.

 

Ocijeni sadržaj
(0 glasova)

// možda će vas zanimati

Newsletter prijava


Kako izgleda naš posljednji newsletter pogledajte na ovom linku.


Copyright © by: VIDI-TO d.o.o. Sva prava pridržana.