Python ile uygulama geliştirirken karşımıza çıkan en büyük sorulardan biri şudur: “Kodumu nasıl daha hızlı çalıştırabilirim?” Paralel programlama, modern çok çekirdekli işlemcilerin gücünü kullanmak için harika bir yoldur. Ancak Python dünyasında işler, diğer dillerden biraz farklı yürür. Sahneye “Küresel Yorumlayıcı Kilidi” yani Global Interpreter Lock (GIL) girdiğinde, seçimlerimiz kritik hale gelir.
Program Ne Yapıyor?
Bu projemizde, Python’un iki temel paralel çalışma modeli olan Threading (Çoklu İş parçacığı) ve Multiprocessing (Çoklu İşlem) yapılarını karşılaştıran bir performans testi (benchmark) hazırladık.
Program, iki farklı senaryo üzerinde çalışıyor:
- CPU-Bound (İşlemci Tabanlı) Görevler: Ağır matematiksel hesaplamalar gibi işlemciyi yoğun şekilde kullanan işler.
- I/O-Bound (Giriş/Çıkış Tabanlı) Görevler: Web sitesinden veri çekmek veya dosya okumak gibi, programın çoğunlukla “beklediği” işler.
Sizlere, hangi durumda hangi yöntemin zafer kazandığını gerçek zamanlı sürelerle gösteriyoruz.
Kodun Anatomisi
Projenin kalbinde concurrent.futures modülü yer alıyor. Bu modül, düşük seviyeli thread veya process yönetimiyle uğraşmak yerine bize yüksek seviyeli “Executor”lar sunar.
1. CPU-Bound Görev ve GIL Engeli
CPU tabanlı görevlerde, Python’un meşhur GIL (Global Interpreter Lock) mekanizması devreye girer. GIL, aynı anda sadece bir thread’in Python bytecode’unu çalıştırmasına izin verir. Bu yüzden, matematiksel bir hesaplamayı Threading ile yapmaya çalıştığınızda, aslında işlemcinizin tüm çekirdeklerini kullanamazsınız; thread’ler sıraya girer.
def cpu_bound_task(number: int) -> int:
"""Sayıları bir döngüde sayarak ağır CPU yükü simüle eder."""
count = 0
for i in range(number):
count += 1
return count
Bu sorunu aşmanın yolu ProcessPoolExecutor kullanmaktır. Multiprocessing, her görev için ayrı bir Python yorumlayıcısı (interpreter) başlatır. Böylece her işlem kendi GIL’ine sahip olur ve gerçek anlamda paralel çalışarak tüm CPU çekirdeklerini sömürebilir.
2. I/O-Bound Görevler ve Verimlilik
Ağ istekleri gibi I/O tabanlı işlerde durum tam tersidir. Program, sunucudan yanıt beklerken işlemci boşta kalır. İşte burada Threading (iş parçacıkları) parlar. Bir thread yanıt beklerken, Python kontrolü hemen diğer thread’e devreder. Bu geçişler çok hızlıdır ve sistem kaynaklarını tüketmez.
def io_bound_task(url: str) -> int:
"""Bir web sayfasını açarak I/O tabanlı bir süreci simüle eder."""
try:
with urllib.request.urlopen(url, timeout=5) as response:
return response.status
except Exception:
return 404
Nasıl Çalıştırılır?
Projenin çalışması için herhangi bir dış kütüphane kurulumuna gerek yoktur; tamamen Python standart kütüphanesi kullanılmıştır.
- Terminalinizi açın.
- Proje klasörüne gidin:
cd ~/Desktop/python_projects/v312/26_multiprocessing_vs_threading
- Programı başlatın:
python main.py
Beklenen Çıktı:
- CPU-Bound aşamasında Multiprocessing çok daha hızlı olacaktır.
- I/O-Bound aşamasında Threading genellikle daha verimli veya benzer sonuçlar verecektir (Multiprocessing’in işlem başlatma maliyeti burada dezavantaj yaratabilir).
Ne Öğrendik?
Bu deney sonucunda şu altın kuralları cebimize koyabiliriz:
- CPU-Bound (Matematik, Görüntü İşleme, Veri Analizi) $\rightarrow$ Multiprocessing kullanın. Çünkü GIL’i aşmanın tek yolu budur.
- I/O-Bound (Web Scraping, API İstekleri, Veritabanı Sorguları) $\rightarrow$ Threading (veya
asyncio) kullanın. Çünkü beklemek, hesaplamaktan daha kolay yönetilir. - GIL Nedir? Python’un bellek yönetimini güvenli tutmak için kullandığı, ancak gerçek paralelliği (CPU bazlı) engelleyen bir kilittir.
Kaynaklar ve Sonraki Adımlar
Bu konuyla ilgili daha derinlemesine bilgi almak isterseniz Python’un resmi concurrent.futures dokümantasyonuna göz atmanızı öneririm. Bir sonraki adım olarak asyncio kütüphanesini araştırarak “asenkron programlama” dünyasına giriş yapabilirsiniz.
Ahmet Aksoy
Not: Bu yazıda incelediğimiz kodu ve benzer projelerin kaynak kodlarını https://github.com/ahmetax/practical-python-examples adresinde bulabilirsiniz.
python, python programlama, python öğren, yazılım, kod, concurrency, multiprocessing, threading, GIL, performans optimizasyonu, orta seviye, ubuntu