Python, veri bilimi, makine öğrenimi ve bilimsel hesaplamalar için uzun süredir de facto dil konumundadır. Ancak, yorumlanan doğası ve Küresel Yorumlayıcı Kilidi (GIL), ağır sayısal döngüler veya büyük veri setleriyle çalışırken önemli performans darboğazlarına yol açabilir. NumPy ve Pandas gibi kütüphaneler arka planda C ile yazılmış olsa da, özel Python mantığı genellikle gerçek zamanlı işleme veya devasa simülasyonlar için gereken hızın çok altında çalışır.
Orta ve ileri düzey geliştiriciler için çözüm, Python'un kullanım kolaylığı ile C'nin ham hızı arasındaki boşluğu doldurmaktır. Bu silahlanmada en güçlü iki araç Numba ve Cython'dur. Her ikisi de dili terk etmeden Python kodunu hızlandırmanızı sağlar, ancak soruna farklı yaklaşırlar. Bu yazı, bu teknolojileri önemli sayısal hızlanmalar elde etmek için nasıl kullanabileceğinizi incelemektedir.
Performans Boşluğunu Anlamak
Araçlara dalmadan önce, Python'un neden yavaş olduğunu anlamak esastır. CPython kodu satır satır yürütür ve her işlem için dinamik tür kontrolleri ve bellek tahsisi yapar. Matematiksel bir dizi hesaplayan basit bir döngüde, bayrak kodunu yorumlamanın getirdiği yük, asıl hesaplama süresini gölgede bırakabilir. Örneğin, kareleri toplamak için bir milyon kez döngüye giren bir döngü, saf Python'da birkaç saniye sürebilirken, C'deki derlenmiş bir eşdeğeri milisaniyeler içinde çalışır.
Optimizasyon için genellikle üç yol izlenir: C/C++ ile yeniden yazmak, vektörize NumPy işlemlerini kullanmak veya hızlandırma kütüphanelerinden yararlanmak. Karmaşık mantık nedeniyle vektörizasyonun imkansız olduğu durumlarda Numba ve Cython birincil seçenekler haline gelir.
Numba: Basitleştirilmiş Zamanında Derleme
Numba, Python ve NumPy kodunun bir alt kümesini hızlı makine koduna çeviren açık kaynaklı bir zamanında (JIT) derleyicidir. Öne çıkan özelliği, gerektirdiği minimum kod değişikliğidir: genellikle sadece bir dekoratör eklemeniz yeterlidir.
Numba, mantığı basit ancak tekrarlayan sayısal algoritmalar için mükemmeldir. İşlevleri anında derler ve sonraki çağrılar için derlenmiş sürümü önbelleğe alır. Bu onu, yalnızca NumPy ile vektörize etmenin zor olduğu bilimsel simülasyonlar, sinyal işleme ve özel matematiksel işlemler için ideal kılar.
Aşağıdaki saf Python işlevine bir örnek verelim:
import numpy as np
import time
def pure_python_sum(x):
total = 0.0
for i in range(len(x)):
total += x[i] * x[i]
return total
Bunu Numba ile hızlandırmak için @jit dekoratörünü uygulamak yeterlidir:
from numba import jit
@jit(nopython=True)
def numba_sum(x):
total = 0.0
for i in range(len(x)):
total += x[i] * x[i]
return total
nopython=True bayrağı ile Numba, Python yorumlayıcısına güvenmeyen makine koduna işlevi derler ve böylece dinamik yükü etkili bir şekilde ortadan kaldırır. Benchmark'larda, bu basit dönüşüm iş yüküne bağlı olarak 10x ile 100x arasında hızlanma sağlayabilir.
Cython: Python Sözdizimi ile Statik Derleme
Eğer Numba dinamik optimizasyon ile ilgileniyorsa, Cython statik derleme ile ilgilenir. Cython, Python benzeri sözdizimini korurken C uyumlu kod yazmanıza olanak tanıyan Python'un bir üst kümesidir. .pyx dosyalarınızı çalıştırmadan önce C uzantılarına (.so veya .pyd) derlersiniz.
Cython, Numba'ya göre daha ince taneli kontrol sunar. Değişkenler için statik türler tanımlayabilir, mevcut C kütüphaneleriyle entegre olabilir ve bellek kullanımını daha agresif bir şekilde optimize edebilirsiniz. Bu, Cython'u uzantı modülleri oluşturmak, C kütüphanelerini gömmek veya son derece optimize edilmiş, kendi kendine yeterli bir ikili dağıtmak için tercih edilen seçenek haline getirir.
Aşağıda, önceki örneğin statik türleme ile Cython'da nasıl göründüğü yer almaktadır:
def cython_sum(double[:] x):
cdef int i
cdef double total = 0.0
for i in range(x.shape[0]):
total += x[i] * x[i]
return total
double[:] notasyonu, Cython'a girdiyi çift sayıların bir bellek görünümü olarak işlemesini söyler ve cdef, yerel değişkenleri C türleri olarak bildirir. Bir setup.py betiği veya cythonize kullanılarak derlendiğinde, bu neredeyse yerel hızlarda çalışan son derece verimli C kodu üretir.
Bunlardan Hangisini Ne Zaman Kullanmalı?
Doğru aracı seçmek, projenizin belirli kısıtlamalarına bağlıdır. Hızlı yineleme gerekiyorsa, derleme adımı olmadan belirli işlevleri hızlandırmak istiyorsanız veya bir Jupyter notebook ortamında çalışıyorsanız Numba'yı seçin. En az sürtünme ile hızlanmaya ulaşmanın en hızlı yoludur.
Eğer bağımsız olması gereken bir kütüphane dağıtımı yapıyorsanız, C/C++ API'leri ile derin entegrasyon gerekiyorsa veya belleği açıkça yönetmeniz gerekiyorsa Cython'u seçin. Cython, anında derlenen kod yerine sabit bir ikili ürün aradığınız üretim dağıtımları için daha sağlamdır.
Sonuç
Python kodunu sayısal performans için optimize etmek, dilden ayrılmayı gerektirmez. Numba'yı JIT hızlandırma veya Cython'u statik derleme için stratejik olarak uygulayarak, geliştiriciler C ve Fortran ile karşılaştırılabilir performans seviyelerini açığa çıkarabilir. Büyük veri setlerini işliyor, karmaşık simülasyonlar çalıştırıyor veya yüksek performanslı API'ler oluşturuyor olun, bu araçların ne zaman ve nasıl kullanılacağını anlamak, modern Python geliştiricisi için kritik bir beceridir.
Kodunuzu darboğazları belirlemek için profillemeye başlayın ve ardından yavaş döngülerinizi yüksek hızlı motorlara dönüştürmek için Numba'nın dekoratörlerini veya Cython'un tür bildirimlerini deneyin.