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

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

Merhaba, yazımızın son bölümünde Cython’un Python’un performansını ne ölçüde artıracağını gözlemleyebilmek için yaptığım performans testi sonuçlarını sizinle paylaşıp sonuçları yorumlamaya çalışacağım. Serinin bu yazısını okumaya başlamadan önce birinci ve ikinci yazıyı sırasıyla okumanızı tavsiye ederim. Python’un yavaşlık problemini ve Cython’un teorik olarak bu sorunları nasıl çözmeye çalıştığına odaklanan serinin ilk yazısına “Python’un Performansı ve Cython 1” linkine tıklayarak erişebilirsiniz. Cython’da nasıl kodlama yapıldığını anlattığım ve Cython’un kendi dokümantasyonunda paylaştığı performans testini paylaşıp yorumladığım serinin ikinci yazısına ise “Python’un Performansı ve Cython 2” linkine tıklayarak erişebilirsiniz.

Veri

Performans testleri için Akbank bünyesindeki SAS CLA Python projesinde kullanılan veri kullanılmıştır. Kullanılan veri tek kolondan oluşmaktadır ve verinin içeriği tüzel veya şahıs şirketi isimleridir. Performans testleri için veriden yüz bin, bir milyon, beş milyon, on milyon, on beş milyon şeklinde 5 farklı alt veri kümesi oluşturulmuştur. Veri kümeleri performans testlerinden önce rastlantısal olarak ayrılmış olup tüm testlerde değiştirilmeden kullanılmıştır.

Fonksiyonlar

Test için yazılan fonksiyonlar temelde NLP alanında kullanılan text türü verileri manipüle eden kodları içermektedir. Text türünde verilerin manipülasyonu için Pandas kütüphanesinin “apply” fonksiyonu kullanılmıştır. Performans testleri için yazılan fonksiyonlar apply fonksiyonu vasıtasıyla veriye uygulanmıştır.

“check_stopwords” fonksiyonu içeriği

Yukarıda performans testlerinde kullanılacak fonksiyonlardan biri olan “check_stopwords” fonksiyonunun içeriği gösterilmiştir. “check_stopwords” fonksiyonu string bir ifadeyi girdi olarak alıp, birkaç özel karakteri sildikten sonra harfleri küçültüp verideki noktalama işaretlerini kaldırmaktadır.

“clean_text” fonksiyonu içeriği

Yukarıdaki iki görselde performans testleri için kullanılan diğer fonksiyonumuz olan “clean_text” fonksiyonu gösterilmiştir. “clean_text” fonksiyonunda “check_stopword” fonksiyonundaki işlemlere ek olarak string ifadelerdeki Türkçe karakterleri düzeltme ve NLP’de “stopwords” olarak geçen kelimeleri silme gibi ek işlemler yapılmıştır.

Performans Testi Sonuçları

Yapılan testler sonucunda Cython’un Python’a göre daha hızlı çalıştığı ve aradaki hız farkının veri seti büyüklüğü ile orantılı olarak büyüdüğü gözlemlendi.

Performans testi sonuçları

Yukarıda paylaşılan sonuçlar, veri setinin büyümesinin ilgili fonksiyonun çalışma hızı–saniye bazında-üzerindeki değişimini ortaya koymaktadır. Sonuçlara göre on milyonluk tek kolonlu veri için “check_stopwords” fonksiyonunda 34 saniyelik hız farkı oluşurken, bu fark “clean_text” fonksiyonunda 51 saniyeye çıkmaktadır.

Makine öğrenmesi modellerinin teoride veri boyutu arttıkça optimum sonuca (“unavoidable bias”) yakınsamasını bekleriz ve modelimizin başarısını artırmak için elimizden geldiğince –ve kaynaklarımız elverdiğince- eğitim veri setini büyütmeye çabalarız. Yapılan testi göz önünde bulundurduğumuzda on milyonluk tek kolonlu veride standart birkaç NLP veri işleme adımında 51 saniyelik bir farkın, 25 kolonlu on milyonluk bir veri setinde yaklaşık 21 dakikanın üzerinde bir süre farkı oluşturabileceğini öngörebiliriz.

Makine öğrenmesi modellerinde kullanılan veri setlerinin 80–100 ve hatta bazı durumlarda 500–600 gibi sayıları bulabildiği durumlarda Cython, sağladığı performans artışı ile veri işleme süreçlerini kısaltarak katkı sağlayabilir.

Python/Cython Kod Örnekleri

#Python ile yazılmış örnek I

def primes(nb_primes: cython.int):
i: cython.int
p: cython.int[1000]

if nb_primes > 1000:
nb_primes = 1000

if not cython.compiled: # Only if regular Python is running
p = [0] * 1000 # Make p work almost like a C array

len_p: cython.int = 0 # The current number of elements in p.
n: cython.int = 2
while len_p < nb_primes:
# Is n prime?
for i in p[:len_p]:
if n % i == 0:
break

# If no break occurred in the loop, we have a prime.
else:
p[len_p] = n
len_p += 1
n += 1

# Let's copy the result into a Python list:
result_as_list = [prime for prime in p[:len_p]]
return result_as_list
#Cython ile yazılmış örnek I


def primes(int nb_primes):
cdef int n, i, len_p
cdef int p[1000]

if nb_primes > 1000:
nb_primes = 1000


len_p = 0 # The current number of elements in p.
n = 2
while len_p < nb_primes:
# Is n prime?
for i in p[:len_p]:
if n % i == 0:
break

# If no break occurred in the loop, we have a prime.
else:
p[len_p] = n
len_p += 1
n += 1

# Let's copy the result into a Python list:
result_as_list = [prime for prime in p[:len_p]]
return result_as_list
# Python ile yazılmış örnek II

import cython
from cython.cimports.libcpp.vector import vector

def primes(nb_primes: cython.uint):
i: cython.int
p: vector[c4826ython.int]
p.reserve(nb_primes) # allocate memory for 'nb_primes' elements.

n: cython.int = 2
while p.size() < nb_primes: # size() for vectors is similar to len()
for i in p:
if n % i == 0:
break
else:
p.push_back(n) # push_back is similar to append()
n += 1

# If possible, C values and C++ objects are automatically
# converted to Python objects at need.
return p # so here, the vector will be copied into a Python list.
# Cython ile yazılmış örnek II


from libcpp.vector cimport vector

def primes(unsigned int nb_primes):
cdef int n, i
cdef vector[int] p
p.reserve(nb_primes) # allocate memory for 'nb_primes' elements.

n = 2
while p.size() < nb_primes: # size() for vectors is similar to len()
for i in p:
if n % i == 0:
break
else:
p.push_back(n) # push_back is similar to append()
n += 1

# If possible, C values and C++ objects are automatically
# converted to Python objects at need.
return p # so here, the vector will be copied into a Python list.

Bu yazı, “Python’un Performansı ve Cython” yazı dizisinin son bölümüydü. Umarım okuyanlar için bilgilendirici bir dizi olmuştur. Python’un eksiklerini ve Cython’un bu eksikleri nasıl giderdiği gibi konuları elimden geldiğince farklı pencerelerden ele almaya çalıştım. Son iki yazıda ise daha çok Cython’un kullanımı ve performans testleri ile ilgili kod örnekleri verip konuyu teknik olarak ele aldım. Umarım okuması keyifli bir yazı dizisi olmuştur.

Yazıyla ilgili değerlendirmelerinizi ve eksik veya yanlış olduğunu düşündüğünüz kısımları yorum olarak paylaşabilirsiniz.

Bir sonraki yazımızda görüşmek üzere…

--

--