Python’un Performansı ve Cython — Bölüm 2

Enes Mesut Yıldız
Akbank Teknoloji
Published in
5 min readJul 21, 2023

Merhaba, yazımızın ikinci bölümünde Cython ile programlama yapabilmeniz için bilmeniz gerekenleri anlatacağım ve literatürde bulduğum bir performans analizini sizlerle paylaşıp sonuçlarını yorumlayacağım. Cython’u ve teorik olarak Python dilinin ne gibi sorunlarını çözmeyi amaçladığını anlatan serinin ilk yazısını okumadıysanız “Python’un Performansı ve Cython 1” linkine tıklayarak okumanızı tavsiye ederim.

Jupyter Notebook’ta Cython Kullanımı

Jupyter Notebook, Cython eklentisi olan bir geliştirme aracı olduğu için Python dili ile yazılan hücrelerin arasına basit bir şekilde Cython fonksiyonları yazabilmenize olanak sağlıyor. Cython’u Jupyter Notebook içinde aktif etmek için herhangi bir boş hücrede “load_ext cython” komutunu çalıştırdıktan (bir kere çalıştırmak yeterli) sonra Cython dilini kullanacağınız hücrelerin başına “%%cython –a” yazarak kodlamaya başlayabilirsiniz. Cython’u Jupyter Notebook içinde kullanmak için başka bir adım yoktur. Cython’da tanımladığınız fonksiyonları Python kodlarının arasında Python fonksiyonları gibi kullanabilirsiniz.

Cython Gereksinimleri

Eğer Jupyter Notebook yerine standart bir kod geliştirme ortamı (ide) kullanıyorsanız Cython’u kullanmadan önce uygulamanız gereken birkaç adım bulunuyor;

1. Python dili gereksinimlerinin indirilmesi

2. Pip ile Cython ve Setuptools paketlerinin indirilmesi

Python Kodlarının Cython’a Dönüşümü

1. “.py” uzantılı dosyaya Python dilinde fonksiyon yazılır.

2. “.pyx” uzantılı dosyaya kodun Cython versiyonu yazılır.

3. Py uzantılı dosya ile pyx uzantılı dosyanın birbiriyle bağdaştırıldığı bir “setup file” yazılır.

4. “setup.py” dosyasında yazılan setup fonksiyonu çalıştırılır ve bunun sonucunda C/C++ byte code dönüşümü yapılmış dosya ve diğer üretilen dosyalar elde edilir.

5. Cython dönüşümü tamamlanmış dosyadaki fonksiyonlar Python ile yazılmış kodların içinde Python fonksiyonları gibi kullanılır.

“setup.py” örneği:

from setuptools import setup
from Cython.Build import cythonize

setup(
ext_modules=cythonize(
['primes.py', # Cython code file with primes() function
'primes_python_compiled.py'], # Python code file with primes() function
annotate=True) # enables generation of the html annotation file
)

Değişken Tanımları

Python dilinde yazılmış fonksiyonların C derleyicisinde derlenebilmesi için statik değişken tanımlarının yapılması gerekmektedir. Statik değişken tanımlarında Python dilinden farklı olarak “cdef” anahtar sözcüğü kullanılır ve veri tipi belirtilir.

Örneğin:

cdef int sayac_1, sayac_2 =0
cdef list stopWords
cdef dict http_response
#python dilinde yazılmış fonksiyon(py dosyası)
def test(x):
y = 0
for i in range(x):
y += i
return y
#cython dönüşümü yapılmış fonksiyon(pyx dosyası)
def test(int x):
cdef int y = 0
cdef int i
for i in range(x):
y += i
return y

Fonksiyon Tanımları

Python dilindeki fonksiyonların C diliyle derlenebilmesi için hangi fonksiyonların Cython’a uygun şekilde yazıldığının belirtilmesi gerekmektedir. Fonksiyon tanımlarında üç farklı tanım kullanılarak, derleyiciye ilgili fonksiyon saf Python dilinde mi yoksa Cython syntax’ı ile mi yazıldı bu bilgi belirtilir. Bir diğer seçenek, saf Python ve Cython syntax’ının ikisinin birlikte kullanıldığı fonksiyonlardır.

· def: Klasik Python fonksiyon tanımıdır. Python ve Cython kod dosyalarında kullanılabilir.

· cdef: Cython’un C fonksiyon tanımıdır. Cython ve C kod dosyalarında kullanılabilir. cdef ile tanımlanan fonksiyonlar “*args **kwargs” gibi C diline çevirmesi zor parametreleri kullanamazlar. cdef fonksiyonları başka fonksiyonlar içinde tanımlanamazlar.

· cpdef: Hem C hem Python dilinde yazılan programların erişebildiği, kullanabildiği fonksiyonlardır. C dili için bir fonksiyon oluşturulurken Python dili için de “wrapper” oluşturulur. cpdef ile tanımlanan fonksiyonlar cdef ve def ile tanımlanan fonksiyonlarla aynı kısıtlamalara sahiptir. Çoğu Cython uygulamasında cpdef, fonksiyon tanımı olarak kullanılır.

“Fonksiyon tanımlarından hangisi kullanılmalı?” sorusuna yanıt olabilecek bir algoritma (https://stackoverflow.com/questions/49172528/should-i-define-my-cython-function-using-def-cdef-or-cpdef-for-optimal-perform/49172529#49172529)

Fonksiyon Tanımlarının Benchmark Sonuçları

Aşağıda sonuçlarını paylaşacağım testlerde, Cython’da farklı fonksiyon tanımları ve iyileştirmeler ile yazılan fonksiyonların Fibonacci problemini çözme hızları karşılaştırılmıştır.

Yukarıdaki tabloda performans sonuçları paylaşılmıştır. Performans testleri için kullanılan kodlara bu linkten ulaşılabilir.

Benchmark performans testinde Python, saf Python ile yazılan fonksiyonu, def() naive, Cython dosyasında def ile tanımlanmış fonksiyonu, def() typed, Cython dosyasında def ile yazılmış ve veri tipi belirtilmiş fonksiyonu, cdef(), Cython dosyasında cdef ile yazılmış fonksiyonu, cpdef(), Cython dosyasında cpdef ile yazılmış fonksiyonu, C ise saf C dilinde yazılmış fonksiyonu temsil etmektedir.

Fonksiyonların çalışma hızlarını karşılaştırdığımızda en yavaş çalışan, işlemciyi arka planda en yoran fonksiyonun Python ile yazılmış fonksiyon olduğunu anlayabiliriz. En az işlemci komutu ile çalışan, işlemciyi en az yoran fonksiyonun da saf C ile yazılan fonksiyon olduğu sonucunu çıkarabiliriz.

Tabloda paylaşılan sonuçların görselleştirilmiş hali (https://notes-on-cython.readthedocs.io/en/latest/fibo_speed.html#code-example)

Cython Optimizasyonu

Cython dosyası, derlenirken “kod_dosyası_adı.html” adlı bir html dosyası üretir. Bu dosya bize kodların derlenme seviyelerini belirtir. Sarı ile renklendirilmiş satırların renk koyuluğu arttıkça derlenen Python kodlarının yavaşlığı da artmaktadır.

“kod_dosyası_adı.html” dosyası içeriği (https://medium.com/analytics-vidhya/speedup-your-existing-python-project-with-cython-30x-1dc1ffaf147a)

Bu dosya incelendiğinde sarı ile işaretli satırlarda yazan kodları mümkünse Cython kullanarak C dilinde yazmak programın çalışma hızını artırabilir. Bu html dosyası bize hangi satırlara odaklanmamız gerektiği konusunda yol gösterici olacaktır.

Cython’un Kullanım Alanları

Cython, veri bilimi projelerinde birçok farklı şekilde kullanılabilir. Birçok farklı şekilde kullanılabilmesi, Python konusunda deneyimli olmayanlar veya Cython konusunda yeterli bilgiye sahip olmayanlar için kafa karıştırıcı olabilir. Bu başlık altında, Cython’un hangi alanlarda daha mantıklı bir tercih olabileceğini, kişisel deneyimlerim ve bilgi birikimim doğrultusunda ele alacağım.

Farklı dillerde geliştirme yapan bazı programcılar, Python’un yavaş bir dil olduğunu düşünseler de veri işleme konusunda Python nispeten hızlı ve pratik bir dildir. Bu nedenle veri bilimi gibi veri odaklı alanlarda yaygın bir şekilde kullanılmaktadır. Python veri işleme kütüphanelerinde (Pandas, Numpy vb.) verilerin daha hızlı işlenebilmesi için birçok kritik kod parçası C++ dilinde yazılmıştır. Python’un veri işleme kütüphanelerinde kodların daha hızlı çalışması için Cython benzeri bir mantığın kullanıldığını düşünebiliriz.

Pandas, Numpy vb. kütüphanelerin kendi hazır fonksiyonları yerine Cython ile yazacağımız fonksiyonları tercih etmek bir önceki paragrafta üzerinde durduğum bilgiler ışığında mantıklı bir tercih olmayabilir. Cython’u kullanmanın –bence- en mantıklı yolu, veriyi iteratif olarak işlediğimiz herhangi bir hazır kütüphane veya fonksiyon kullanmadan, elle yazdığımız fonksiyonlar yerine Cython ile yazacağımız fonksiyonları kullanmaktır. Döngüler vasıtasıyla veri setine özel çeşitli veri işleme adımları uygulamak istiyorsak Cython, bu ve benzeri ihtiyaçlarımızda hızlı bir çözüm sunabilir. Özellikle NLP üzerinde çalışan geliştiriciler, modellerini eğitecekleri veri setlerinde (corpus) Cython fonksiyonlarını birer lamda fonksiyonuna dönüştürüp pratik bir şekilde kullanabilirler. NLP modelleri yapısı gereği veriye özgü veri işleme adımlarını gerektirecek bir alan olduğu için Cython için vereceğim örneği bu alandan seçmeye gayret ettim.

Bu yazıda Cython’un Python içinde Jupyter Notebook veya diğer ide ortamlarında nasıl kullanılabileceğinden bahsettim. Cython’un kendi dokümantasyonlarında paylaşılan performans testini yorumlamaya çalıştım. Serinin üçüncü ve son yazısında sizlere Cython ile yaptığımız performans testlerini paylaşıp Python’dan Cython’a dönüştürülen kodlarla ilgili farklı farklı örnekler vermeye çalışacağım.

Konuyla ilgili değerlendirmelerinizi, düzeltmelerinizi yorum yaparak bana iletebilirsiniz.

Cython’u merak etmeye devam edin :)
Serinin üçüncü ve son yazısında görüşmek üzere…

Kaynakça

https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html

https://pythonprogramming.net/introduction-and-basics-cython-tutorial/

https://stackoverflow.com/questions/49172528/should-i-define-my-cython-function-using-def-cdef-or-cpdef-for-optimal-perform/49172529#49172529

https://notes-on-cython.readthedocs.io/en/latest/fibo_speed.html#code-example

https://medium.com/analytics-vidhya/speedup-your-existing-python-project-with-cython-30x-1dc1ffaf147a

--

--