Paano I-optimize ang Iyong Python Code gamit ang Profiling Tools

Paano I Optimize Ang Iyong Python Code Gamit Ang Profiling Tools



Ang pagpapahusay sa pagganap ng code ng Python ay isang mahalagang kasanayan para sa mga developer. Ang mga tool sa pag-profile ay mahalaga sa kasong ito at pinapadali ang pagtuklas ng mga paghihigpit sa code at kawalan ng kahusayan. Sinusuri ng artikulong ito ang mga paraan ng paggamit ng mga tool sa pag-profile upang mapabuti ang mga programang Python. Sa pamamagitan ng pag-master ng pagsukat ng mga oras ng pagpapatupad, pagkonsumo ng memorya, at function na tawag ng mga frequency, maaari nating tiyak na mapabuti.

Pag-optimize ng Python Code gamit ang Profiling Tools

Ang pag-set up ng Google Colab upang gumana para sa pag-optimize ng Python code gamit ang mga tool sa pag-profile, magsisimula kami sa pamamagitan ng pag-set up ng Google Colab environment. Kung tayo ay bago sa Colab, ito ay isang mahalaga, makapangyarihang cloud-based na platform na nagbibigay ng access sa mga Jupyter notebook at isang hanay ng mga Python library. Ina-access namin ang Colab sa pamamagitan ng pagbisita sa (https://colab.research.google.com/) at paggawa ng bagong Python notebook.

I-import ang Profiling Libraries

Ang aming pag-optimize ay umaasa sa mahusay na paggamit ng mga profile ng library. Dalawang mahalagang aklatan sa kontekstong ito ay cProfile at line_profiler.







angkat cProfile

angkat line_profiler

Ang 'cProfile' library ay isang built-in na Python tool para sa profiling code, habang ang 'line_profiler' ay isang external na package na nagbibigay-daan sa amin na mas malalim pa, na sinusuri ang code sa bawat linya.



Sa hakbang na ito, gumawa kami ng sample na script ng Python para kalkulahin ang Fibonacci sequence gamit ang recursive function. Suriin natin ang prosesong ito nang mas malalim. Ang Fibonacci sequence ay isang set ng mga numero kung saan ang bawat sunud-sunod na numero ay ang kabuuan ng dalawang bago nito. Karaniwan itong nagsisimula sa 0 at 1, kaya ang pagkakasunod-sunod ay mukhang 0, 1, 1, 2, 3, 5, 8, 13, 21, at iba pa. Isa itong mathematical sequence na karaniwang ginagamit bilang isang halimbawa sa programming dahil sa recursive na katangian nito.



Tinutukoy namin ang isang Python function na tinatawag na 'Fibonacci' sa recursive Fibonacci function. Ang function na ito ay tumatagal ng 'n' integer bilang argument nito, na kumakatawan sa posisyon sa Fibonacci sequence na gusto naming kalkulahin. Gusto naming hanapin ang ikalimang numero sa Fibonacci sequence, halimbawa, kung ang 'n' ay katumbas ng 5.





def fibonacci ( n ) :

Susunod, nagtatatag kami ng base case. Ang base case sa recursion ay isang senaryo na nagtatapos sa mga tawag at nagbabalik ng paunang natukoy na halaga. Sa Fibonacci sequence, kapag ang 'n' ay 0 o 1, alam na natin ang resulta. Ang 0th at 1st Fibonacci na numero ay 0 at 1, ayon sa pagkakabanggit.

kung n <= 1 :

bumalik n

Tinutukoy ng pahayag na 'kung' na ito kung ang 'n' ay mas mababa o katumbas ng 1. Kung oo, ibinabalik namin ang 'n' mismo, dahil hindi na kailangan ng karagdagang pag-uulit.



Recursive na Pagkalkula

Kung ang 'n' ay lumampas sa 1, magpapatuloy kami sa recursive na pagkalkula. Sa kasong ito, kailangan nating hanapin ang “n”-th Fibonacci number sa pamamagitan ng pagsusuma ng “(n-1)”th at “(n-2)”th Fibonacci number. Nakamit namin ito sa pamamagitan ng paggawa ng dalawang recursive na tawag sa loob ng function.

iba pa :

bumalik fibonacci ( n - 1 ) + fibonacci ( n - 2 )

Dito, kinakalkula ng “fibonacci(n – 1)” ang “(n-1)”th Fibonacci number, at ang “fibonacci(n – 2)” ay kinakalkula ang “(n-2)”th Fibonacci number. Idinaragdag namin ang dalawang value na ito upang makuha ang nais na numero ng Fibonacci sa posisyong “n”.

Sa buod, ang function na 'fibonacci' na ito ay recursively na kinakalkula ang mga numero ng Fibonacci sa pamamagitan ng paghahati sa problema sa mas maliliit na sub-problema. Gumagawa ito ng mga recursive na tawag hanggang sa maabot nito ang mga base case (0 o 1), na nagbabalik ng mga kilalang halaga. Para sa anumang iba pang 'n', kinakalkula nito ang numero ng Fibonacci sa pamamagitan ng pagbubuod ng mga resulta ng dalawang recursive na tawag para sa '(n-1)' at '(n-2)'.

Bagama't diretso ang pagpapatupad na ito upang kalkulahin ang mga numero ng Fibonacci, hindi ito ang pinakamabisa. Sa mga susunod na hakbang, gagamitin namin ang mga tool sa pag-profile upang matukoy at ma-optimize ang mga paghihigpit sa pagganap nito para sa mas mahusay na mga oras ng pagpapatupad.

Pag-profile sa Code gamit ang CProfile

Ngayon, i-profile namin ang aming function na 'fibonacci' sa pamamagitan ng paggamit ng 'cProfile'. Ang pagsasanay sa profile na ito ay nagbibigay ng mga insight sa oras na ginagamit ng bawat function call.

cprofiler = cProfile. Profile ( )

cprofiler. paganahin ( )

resulta = fibonacci ( 30 )

cprofiler. huwag paganahin ( )

cprofiler. print_stats ( uri = 'cumulative' )

Sa segment na ito, sinisimulan namin ang isang object na 'cProfile', i-activate ang profiling, hinihiling ang function na 'fibonacci' na may 'n=30', i-deactivate ang profiling, at ipinapakita ang mga istatistika na pinagsunod-sunod ayon sa pinagsama-samang oras. Ang paunang pag-profile na ito ay nagbibigay sa amin ng mataas na antas na pangkalahatang-ideya kung aling mga function ang kumukonsumo ng pinakamaraming oras.

! pip install line_profiler

angkat cProfile

angkat line_profiler

def fibonacci ( n ) :

kung n <= 1 :

bumalik n

iba pa :

bumalik fibonacci ( n - 1 ) + fibonacci ( n - 2 )

cprofiler = cProfile. Profile ( )

cprofiler. paganahin ( )

resulta = fibonacci ( 30 )

cprofiler. huwag paganahin ( )

cprofiler. print_stats ( uri = 'cumulative' )

Upang i-profile ang linya ng code sa bawat linya sa line_profiler para sa isang mas detalyadong pagsusuri, ginagamit namin ang 'line_profiler' upang i-segment ang aming linya ng code sa bawat linya. Bago gamitin ang 'line_profiler', kailangan naming i-install ang package sa Colab repository.

! pip install line_profiler

Ngayong handa na namin ang 'line_profiler', maaari na naming ilapat ito sa aming function na 'fibonacci':

%load_ext line_profiler

def fibonacci ( n ) :

kung n <= 1 :

bumalik n

iba pa :

bumalik fibonacci ( n - 1 ) + fibonacci ( n - 2 )

%lprun -f fibonacci ( 30 )

Nagsisimula ang snippet na ito sa pamamagitan ng paglo-load ng extension na 'line_profiler', tinutukoy ang aming function na 'fibonacci', at sa wakas ay ginagamit ang '%lprun' upang i-profile ang function na 'fibonacci' na may 'n=30'. Nag-aalok ito ng line-by-line na pagse-segment ng mga oras ng pagpapatupad, na tumpak na nililinaw kung saan ginagamit ng aming code ang mga mapagkukunan nito.

Pagkatapos patakbuhin ang mga tool sa pag-profile upang pag-aralan ang mga resulta, ipapakita ito ng isang hanay ng mga istatistika na nagpapakita ng mga katangian ng pagganap ng aming code. Kasama sa mga istatistikang ito ang kabuuang oras na ginugol sa loob ng bawat function at ang tagal ng bawat linya ng code. Halimbawa, maaari naming makilala na ang Fibonacci function ay namumuhunan ng kaunti pang tagal ng oras sa muling pagkalkula ng magkaparehong mga halaga nang maraming beses. Ito ang kalabisan na pag-compute at ito ay isang malinaw na lugar kung saan maaaring ilapat ang pag-optimize, alinman sa pamamagitan ng memoization o sa pamamagitan ng paggamit ng mga umuulit na algorithm.

Ngayon, gumagawa kami ng mga pag-optimize kung saan natukoy namin ang isang potensyal na pag-optimize sa aming Fibonacci function. Napansin namin na muling kinakalkula ng function ang parehong mga numero ng Fibonacci nang maraming beses, na nagreresulta sa hindi kinakailangang redundancy at mas mabagal na oras ng pagpapatupad.

Para ma-optimize ito, ipinapatupad namin ang memoization. Ang memoization ay isang diskarte sa pag-optimize na kinabibilangan ng pag-iimbak ng mga naunang kinakalkula na mga resulta (sa kasong ito, mga numero ng Fibonacci) at muling paggamit sa mga ito kapag kinakailangan sa halip na muling kalkulahin ang mga ito. Binabawasan nito ang mga paulit-ulit na pag-compute at pinapabuti ang pagganap, lalo na para sa mga recursive function tulad ng Fibonacci sequence.

Upang ipatupad ang memoization sa aming Fibonacci function, isinusulat namin ang sumusunod na code:

# Diksyunaryo upang mag-imbak ng mga nakalkulang numero ng Fibonacci
fib_cache = { }
def fibonacci ( n ) :
kung n <= 1 :
bumalik n
# Suriin kung ang resulta ay naka-cache na
kung n sa fib_cache:
bumalik fib_cache [ n ]
iba pa :
# Kalkulahin at i-cache ang resulta
fib_cache [ n ] = fibonacci ( n - 1 ) + fibonacci ( n - 2 )
bumalik fib_cache [ n ] ,

Sa binagong bersyong ito ng function na 'fibonacci', ipinakilala namin ang isang diksyunaryo ng 'fib_cache' upang iimbak ang mga dating nakalkulang numero ng Fibonacci. Bago kalkulahin ang isang numero ng Fibonacci, tinitingnan namin kung nasa cache na ito. Kung oo, ibinabalik namin ang naka-cache na resulta. Sa anumang iba pang kaso, kino-compute namin ito, itago ito sa cache, at pagkatapos ay ibabalik ito.

Inuulit ang Profiling at Optimization

Pagkatapos ipatupad ang optimization (memoization sa aming kaso), mahalagang ulitin ang proseso ng pag-profile para malaman ang epekto ng aming mga pagbabago at matiyak na napabuti namin ang performance ng code.

Pag-profile Pagkatapos ng Pag-optimize

Maaari naming gamitin ang parehong mga tool sa pag-profile, 'cProfile' at 'line_profiler', upang i-profile ang na-optimize na Fibonacci function. Sa pamamagitan ng paghahambing ng mga bagong resulta ng pag-profile sa mga nauna, masusukat namin ang pagiging epektibo ng aming pag-optimize.

Narito kung paano namin mai-profile ang na-optimize na function na 'fibonacci' gamit ang 'cProfile':

cprofiler = cProfile. Profile ( )

cprofiler. paganahin ( )

resulta = fibonacci ( 30 )

cprofiler. huwag paganahin ( )

cprofiler. print_stats ( uri = 'cumulative' )

Gamit ang 'line_profiler', i-profile namin ito nang linya sa linya:

%lprun -f fibonacci ( 30 )

Code:

# Diksyunaryo upang mag-imbak ng mga nakalkulang numero ng Fibonacci
fib_cache = { }

def fibonacci ( n ) :
kung n <= 1 :
bumalik n
# Suriin kung ang resulta ay naka-cache na
kung n sa fib_cache:
bumalik fib_cache [ n ]
iba pa :
# Kalkulahin at i-cache ang resulta
fib_cache [ n ] = fibonacci ( n - 1 ) + fibonacci ( n - 2 )
bumalik fib_cache [ n ]
cprofiler = cProfile. Profile ( )
cprofiler. paganahin ( )

resulta = fibonacci ( 30 )

cprofiler. huwag paganahin ( )
cprofiler. print_stats ( uri = 'cumulative' )
%lprun -f fibonacci ( 30 )

Upang suriin ang mga resulta ng pag-profile pagkatapos ng pag-optimize, magkakaroon ng makabuluhang bawasan ang mga oras ng pagpapatupad, lalo na para sa malalaking halaga ng 'n'. Dahil sa memoization, napagmasdan namin na ang function na ngayon ay gumugugol ng mas kaunting oras sa muling pagkalkula ng mga numero ng Fibonacci.

Ang mga hakbang na ito ay mahalaga sa proseso ng pag-optimize. Kasama sa pag-optimize ang paggawa ng matalinong mga pagbabago sa aming code batay sa mga obserbasyon na nakuha mula sa pag-profile, habang tinitiyak ng paulit-ulit na pag-profile na ang aming mga pag-optimize ay nagbubunga ng inaasahang mga pagpapabuti sa pagganap. Sa pamamagitan ng umuulit na pag-profile, pag-optimize, at pag-validate, maaari naming i-fine-tune ang aming Python code para makapaghatid ng mas mahusay na performance at mapahusay ang karanasan ng user ng aming mga application.

Konklusyon

Sa artikulong ito, tinalakay namin ang halimbawa kung saan na-optimize namin ang Python code gamit ang mga tool sa pag-profile sa loob ng Google Colab environment. Sinimulan namin ang halimbawa sa pag-setup, nag-import ng mahahalagang profile ng mga library, nagsulat ng mga sample na code, nag-profile nito gamit ang parehong 'cProfile' at 'line_profiler', kinakalkula ang mga resulta, inilapat ang mga pag-optimize, at paulit-ulit na pinino ang pagganap ng code.