Python’un Performansı ve Cython 2

Enes Mesut Yıldız
5 min readJun 8, 2023

--

Merhabalar, bu yazıda Cython ile programlama yapabilmeniz için bilmeniz gerekenleri anlatacağım ve literatürde bulduğum bir performans analizini sizlerle paylaşıp sonuçları 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 “Python’un Performansı ve Cython 1” linkine tıklayarak okumanı 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ımak yeterli) sonra Cython dilini kullanacağımız hücrelerin başına “%%cython –a” yazarak kodlamaya başlayabilirsiniz. Cythonu 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 var;

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++ bytecode 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.

Örn:

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 Cpython’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 Cpython syntaxı ile mi yazıldı bu belirtilir. Bir diğer seçenek saf Python ve Cpython syntaxının ikisinin birlikte kullanıldığı fonksiyonlardır.

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

· cdef : Cython C fonksiyon tanımı. Cython ve C kod dosyalarında kullanılabilir. cdef ile tanımlanan fonksiyonlar “*args **kwargs” gibi C diline çevirmesi zor parametleri 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 fonksiyonlar. 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ıtlamalar 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 test sonuçları 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.

Yukarda 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 ; 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 fonksiyonunda 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 oluşan “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ğini 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’u 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’da veri işleme kütüphaneleri(Pandas, Numpy vb.) verilerin daha hızlı işlenebilmesi için birçok kritik kod parçasını 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. gibi 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. Cythonu 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ını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 Cythonu 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 iletebilirseniz çok sevinirim. Serinin ikinci yazısında görüşmek üzere kendinize iyi bakın ve Cython’u merak edin :)

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

--

--