---
title: 'Yürütücü Havuzları'
source: 'https://academia.sh/tr/kurslar/python-eszamanlilik/yurutucu-havuzlari'
course: 'Eşzamanlılık ve Başarım'
language: tr
updated: '2026-08-17T18:10:24+00:00'
license: 'CC BY-SA 4.0'
---

# Yürütücü Havuzları

Aynı arayüz iki arka uçta aynı görevi ayrı sayılarla bitirir: sekiz genişlikte iş parçacığı havuzu üç yükte 31, 42 ve 73 tik verirken süreç havuzu üçünde de 10 tik ve 70 örtüşen adım verir; arayüzün aynı olması seçimin de aynı olduğu anlamına gelmez.

Önceki ders engelleyen bir çağrıyı bir yürütücü havuzuna devretti ve havuzun genişliğini hiç
sormadı; ölçümde havuz sınırsız sayılmıştı. Gerçek bir havuzun genişliği vardır ve arkasında
ne olduğu — iş parçacığı mı, süreç mi — ölçümü değiştirir.

Bu ders o soruyu sorar. **Yürütücü havuzu (executor pool)** iş dağıtmanın ortak arayüzüdür:
aynı çağrı biçimi, arkasında iş parçacığı da olsa süreç de olsa aynı yazılır. Bu dersin ölçtüğü
şey arayüzün altındaki fark: aynı görev, aynı genişlik, iki arka uç — hangi sayılar çıkar?

## Ortak Arayüz

Yürütücü havuzu üç şey verir. Bir iş gönderilir ve karşılığında **sonuç nesnesi** alınır; bir
işlev bir dizi girdi üzerinde eşlenir ve sonuçlar **girdi sırasıyla** döner; havuz kapatılır ve
gönderilmiş işler tamamlanır. Bu üç işlem iki arka uçta da aynı adla, aynı imzayla çağrılır.

Arayüzün taşıdığı bir güvence bu dersin ölçüm koşulunu da veriyor: eşleme işleminin çıktısı
girdinin sırasına bağlıdır, çizelgelemeye değil. Hangi işin hangi işçide ne zaman koştuğu
belirsiz olsa da sonuç listesi belirlenimcidir. Aşağıdaki ilk blok bunu gösteriyor.

Kuyruk, arka plan işçisi ve geri basınç **Önbellekleme, Kuyruklar ve Eşzamansız İşleme**
kursunda servis tarafında kuruldu; burada tekrarlanmaz. Buradaki havuz bir servis bileşeni
değil, tek bir programın içindeki bir iş dağıtım arayüzüdür.

## Arayüz Aynı, Arka Uç İki Sayı

Modelin diliyle iki arka uç arasındaki fark tek bir yerde toplanıyor.

**İş parçacığı arka ucu** genişlik kadar **işçi** verir ama tek bir yorumlayıcının içindedir;
**yuva birde kalır**. **Süreç arka ucu** genişlik kadar işçi verir ve her biri ayrı bir
yorumlayıcı olduğu için **yuva da genişlik kadardır**.

İkinci dersin ve üçüncü dersin sonuçları bu tanımın içinde duruyor. Yeni olan şey, ikisinin
**aynı arayüzün** arkasında olması: çağıran taraf tek bir satır değiştirerek birinden öbürüne
geçer ve sayılar değişir.

Ölçümün varsayımları:

- **EM59** — Görev kurgusu önceki derslerin aynısıdır: sekiz görev, görev başına on adım,
  toplam seksen adım; üç yük yalnız girdi/çıktı payıyla ayrılır.
- **EM60** — İş parçacığı havuzunun modeldeki karşılığı **işçi = genişlik, yuva = 1**'dir.
- **EM61** — Süreç havuzunun modeldeki karşılığı **işçi = genişlik, yuva = genişlik**'tir.
- **EM62** — Gerçek süreç başlatılmaz. Gerçek iş parçacığı yalnız arayüzü göstermek için
  kullanılır ve verilen iş **saf**tır: aynı girdiye aynı sonucu verir, yan etkisi yoktur ve
  çıktının sırası eşleme işleminin sözleşmesinden gelir, çizelgeden değil.
- **EM63** — Ölçüm hiçbir yerde süre saymaz; havuzun karşılaştırıldığı birim tik ve örtüşen
  adımdır.
- **EM64** — Görevler bağımsızdır; havuza gönderilen işler birbirini beklemez.
- **EM65** — Havuza iş göndermenin kendisi bu ölçümde bedelsizdir.
- **EM66** — Süreç arka ucunun veri devri bedeli bu ölçüme **dahil değildir**; o bedel üçüncü
  derste ayrıca ölçüldü. Buradaki süreç sütunu bu yüzden bir **üst sınırdır**.
- **EM67** — Genişlik taraması aynı görev dizisiyle yapılır; yalnız genişlik değişir.
- **EM68** — Genişlik hiçbir koşumda görev sayısını aşmaz.
- **EM69** — Son satırdaki sayım, üç yükün verdiği **ayrı** tik sayısıdır; kaç ayrı sonuç
  çıktığını sayar, sonuçların büyüklüğünü değil.
- **EM70** — Ölçüm tek koşumdur ve tohum sabittir.

## Ölçüm

```python
"""Yurutucu havuzlari: ayni arayuz, iki arka uc, ayni gorevde ayri ortusme."""

from concurrent.futures import ThreadPoolExecutor

TOHUM = 20260817
ISLEMCI, GC = "islemci", "g_c"


def uretec(tohum):
    d = tohum % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def gorevler(sayi=8, adim=10, gc_payi=7, tohum=TOHUM):
    """Her gorev bir adim dizisi; gc_payi/10 orani girdi/cikti adimi."""
    r, liste = uretec(tohum), []
    for i in range(sayi):
        liste.append([GC if r(10) < gc_payi else ISLEMCI for _ in range(adim)])
    return liste


def kosum(gorevler, isci, islemci_yuvasi):
    """Donen: tik, ortusen adim, islemci adimi, g/c adimi."""
    kalan = [list(g) for g in gorevler]
    tik = ortusen = islemci_adim = gc_adim = 0
    while any(kalan):
        etkin = [i for i, g in enumerate(kalan) if g][:isci]
        if not etkin:
            break
        yuva, ilerleyen = islemci_yuvasi, 0
        for i in etkin:
            adim = kalan[i][0]
            if adim == ISLEMCI:
                if yuva <= 0:
                    continue
                yuva -= 1
                islemci_adim += 1
            else:
                gc_adim += 1
            kalan[i].pop(0)
            ilerleyen += 1
        tik += 1
        ortusen += max(0, ilerleyen - 1)
    return tik, ortusen, islemci_adim, gc_adim


def havuz(arka_uc, genislik):
    """Arayuz ayni, arka uc iki ayarla anlatilir: isci ve yuva.

    is parcacigi : genislik kadar isci, tek yuva  (tek yorumlayici)
    surec        : genislik kadar isci, genislik kadar yuva (ayri yorumlayici)
    """
    return (genislik, 1) if arka_uc == "iş parçacığı" else (genislik, genislik)


def kare(n):
    """Havuza verilen is: saf, yan etkisiz, sirasi onemsiz."""
    return n * n


YUKLER = (("girdi/çıktı ağırlıklı", 7), ("dengeli", 5), ("işlemci ağırlıklı", 1))
ARKA = ("iş parçacığı", "süreç")

with ThreadPoolExecutor(max_workers=4) as havuz_nesnesi:
    print("aynı arayüz:", list(havuz_nesnesi.map(kare, range(6))))
print("map çıktısının sırası girişten gelir, çizelgeden değil")

print()
print("genişlik sekiz — aynı görev, iki arka uç")
print(f"{'yük':<22s} " + " ".join(f"{ad:>22s}" for ad in ARKA))
print(f"{'':22s} " + " ".join(f"{'tik / örtüşen':>22s}" for _ in ARKA))
for ad, pay in YUKLER:
    g = gorevler(gc_payi=pay)
    hucre = []
    for arka in ARKA:
        isci, yuva = havuz(arka, 8)
        tik, ortusen, _, _ = kosum(g, isci, yuva)
        hucre.append(f"{f'{tik} / {ortusen}':>22s}")
    print(f"{ad:<22s} " + " ".join(hucre))

for arka in ARKA:
    print()
    print(f"{arka} havuzu, genişlik arttıkça")
    print(f"{'genişlik':>9s} " + " ".join(f"{ad:>22s}" for ad, _ in YUKLER))
    print(f"{'':9s} " + " ".join(f"{'tik / örtüşen':>22s}" for _ in YUKLER))
    for genislik in (1, 2, 4, 8):
        hucre = []
        for ad, pay in YUKLER:
            isci, yuva = havuz(arka, genislik)
            tik, ortusen, _, _ = kosum(gorevler(gc_payi=pay), isci, yuva)
            hucre.append(f"{f'{tik} / {ortusen}':>22s}")
        print(f"{genislik:9d} " + " ".join(hucre))

print()
for arka in ARKA:
    sayi = {kosum(gorevler(gc_payi=pay), *havuz(arka, 8))[0] for _, pay in YUKLER}
    print(f"{arka} havuzu, üç yükün verdiği ayrı tik sayısı: {len(sayi)} "
          f"({sorted(sayi)})")
```

```
aynı arayüz: [0, 1, 4, 9, 16, 25]
map çıktısının sırası girişten gelir, çizelgeden değil

genişlik sekiz — aynı görev, iki arka uç
yük                              iş parçacığı                  süreç
                                tik / örtüşen          tik / örtüşen
girdi/çıktı ağırlıklı                 31 / 49                10 / 70
dengeli                               42 / 38                10 / 70
işlemci ağırlıklı                      73 / 7                10 / 70

iş parçacığı havuzu, genişlik arttıkça
 genişlik  girdi/çıktı ağırlıklı                dengeli      işlemci ağırlıklı
                   tik / örtüşen          tik / örtüşen          tik / örtüşen
        1                 80 / 0                 80 / 0                 80 / 0
        2                44 / 36                52 / 28                 73 / 7
        4                34 / 46                44 / 36                 73 / 7
        8                31 / 49                42 / 38                 73 / 7

süreç havuzu, genişlik arttıkça
 genişlik  girdi/çıktı ağırlıklı                dengeli      işlemci ağırlıklı
                   tik / örtüşen          tik / örtüşen          tik / örtüşen
        1                 80 / 0                 80 / 0                 80 / 0
        2                40 / 40                40 / 40                40 / 40
        4                20 / 60                20 / 60                20 / 60
        8                10 / 70                10 / 70                10 / 70

iş parçacığı havuzu, üç yükün verdiği ayrı tik sayısı: 3 ([31, 42, 73])
süreç havuzu, üç yükün verdiği ayrı tik sayısı: 1 ([10])
```

## Aynı Görev, İki Sonuç

İlk tablo dersin iddiasını üç satırda veriyor. Sol sütun ile sağ sütun arasındaki tek fark
arka uç; görevler aynı nesne, genişlik aynı sayı, çizelgeleyici aynı işlev.

Girdi/çıktı ağırlıklı yükte iş parçacığı havuzu **31 / 49**, süreç havuzu **10 / 70** veriyor.
Dengeli yükte **42 / 38** ile **10 / 70**. İşlemci ağırlıklı yükte **73 / 7** ile **10 / 70**.

Sol sütun aşağı indikçe kötüleşiyor, sağ sütun hiç değişmiyor. Bunun kaynağı iki ayarın
tanımında: iş parçacığı havuzu yükün işlemci payını **görüyor**, çünkü tek yuvada işlemci
adımları sıraya giriyor. Süreç havuzunda yuva görev sayısına eşit olduğu için işlemci adımı
kısıt olmaktan çıkıyor ve yükün bileşimi görünmez oluyor.

Buradan bu dersin cümlesi çıkıyor: **aynı arayüzün arkasında aynı seçim yoktur.** Bir kod
tabanında havuz nesnesini değiştirmek bir satırlık iştir; ölçümde karşılığı ise yüke göre
hiçbir şeyden yedi kat farka kadar değişir.

## Genişlik İki Arka Uçta İki Ayrı Biçimde Kazandırır

Alt iki tablo genişliği birden sekize çıkarıyor ve iki apayrı biçim veriyor.

**İş parçacığı havuzunda** her sütun kendi eğrisini izliyor. Girdi/çıktı ağırlıklı sütun
80'den 44'e, 34'e, 31'e iniyor — azalarak kazanıyor. İşlemci ağırlıklı sütun ikinci genişlikte
**73**'e iniyor ve orada duruyor; dört ve sekiz genişlik hiçbir şey eklemiyor. Bu havuzda
genişliği artırmanın karşılığı **yükün girdi/çıktı payı kadardır**.

**Süreç havuzunda** üç sütun da aynı: 80, 40, 20, 10. Genişlik iki katına çıktığında tik yarıya
iniyor ve bu üç yükte de aynı. Sebebi işçi ile yuvanın birlikte büyümesi: her genişlikte canlı
görevlerin hepsi ilerleyebiliyor ve kısıt yalnız görev başına düşen on adım.

İki tablonun ilk satırı da aynı: genişlik bir olduğunda iki arka uç da **80 / 0** veriyor.
Havuzun arkasında ne olursa olsun, tek işçili havuz tek akıştır. Bir karşılaştırma havuz
genişliğini yazmıyorsa okunamaz — ilk satır bunu gösteriyor.

Genişliği seçerken bakılacak sayı da bu tablolarda: iki ardışık satır arasındaki fark. İş
parçacığı havuzunda işlemci ağırlıklı sütun için ikinci satırdan sonra fark **0**; genişliği
dörde ya da sekize çıkarmak ölçülebilir bir şey eklemiyor. Girdi/çıktı ağırlıklı sütunda aynı
fark dörtten sekize **3** tik. Süreç havuzunda ise fark her adımda büyük ve üç sütunda da
aynı. Genişlik için tek bir doğru sayı yok; olan şey, iki ölçüm arasındaki farkın küçüldüğü
yerde durmak.

Bir uyarı bu tabloların dışında duruyor ve varsayımlarda yazılı: süreç sütunu **veri devrini
saymıyor**. Üçüncü ders o bedeli ayrıca ölçmüştü; her göreve iki uçta on beşer aktarım adımı
eklendiğinde dört yuvanın kazancı sıfırlanıyordu. Buradaki süreç sütunu bu yüzden ulaşılabilir
en iyi sayıyı, yani bir **üst sınırı** veriyor. İş parçacığı sütununda böyle bir dış bedel yok,
çünkü aynı adres alanında taşınacak bir şey de yok.

## Havuza Verilen İşin Biçimi

Arayüzün aynı olması, verilebilecek işin de aynı olduğu anlamına gelmiyor ve seçim çoğu zaman
sayılardan önce burada belirleniyor.

**Süreç arka ucu, işin taşınabilir olmasını ister.** Gönderilen işlev ve girdisi öbür uca
aktarılabilir bir gösterime çevrilir, sonuç geri taşınır. Taşınamayan bir değer havuza
giremez. Üstelik bu taşıma, üçüncü derste ölçülen aktarım adımlarının kendisidir: iş küçük ve
veri büyük olduğunda kazanç orada erir.

**İş parçacığı arka ucu taşıma istemez** ama başka bir şey ister: işin **kilidi bırakması**.
Bırakmayan bir iş, tabloların işlemci ağırlıklı sütununa düşer ve genişliği artırmak onu
kurtarmaz — ikinci genişlikten sonra sütun kımıldamıyordu.

**İkisi de işlerin bağımsız olmasını ister.** Ölçümdeki sekiz görev birbirini beklemiyor; bir
görevin sonucunu öbürü kullansaydı bekleyen görev o tikte ilerlemez ve örtüşen adım düşerdi.
Havuz arayüzü bu bağımlılığı görmez, çünkü gönderilen her iş kendi başına gönderilir.

Ölçümdeki sayılar bu üç koşul sağlandığı için çıkıyor. Koşullardan biri bozulduğunda tablo
aşağı doğru kayar; hiçbiri bozulmadığında yukarıdaki sayılar ulaşılabilir en iyi durumdur.
Havuz seçerken sorulacak ilk soru bu yüzden genişlik değil: **işin kendisi hangi arka ucun
istediği biçimde mi?**

## Arayüzün Söylemediği

Son iki satır bu konunun kapanış sayısı: **iş parçacığı havuzu üç yükte 3 ayrı tik sayısı
veriyor ([31, 42, 73]); süreç havuzu 1 ([10]).**

Bu iki sayı, arka uç seçiminin ne olduğunu tanımlıyor. İş parçacığı havuzuna geçmek, ölçümü
**yüke duyarlı** kılmak demektir: hangi yükü verdiğinizi bilmeden sonucu kestiremezsiniz.
Süreç havuzuna geçmek — devir bedeli sayılmadığı sürece — ölçümü yükten **bağımsız** kılar.

Arayüz ikisini de aynı biçimde çağırıyor ve bu bir kolaylık. Ama aynı çağrı biçimi, aynı
davranışı vaat etmiyor. Ortak arayüzün gizlediği tam olarak bu dersin ölçtüğü şey: hangi adımın
örtüşebildiği. Bir kod tabanında havuz nesnesini iki satırla değiştirip sonucun aynı kalmasını
beklemek, bu iki sayıyı — **3** ile **1**'i — aynı saymak demektir.

Bu bölümün bütün rejimleri şu ana kadar aynı soruyu yanıtladı: **hangi rejim ne kazandırır?**
Beş ders boyunca yanıt hep aynı biçimde çıktı — kazanç, örtüşebilen adım sayısına ve o adımları
kaç yuvaya dağıtabildiğinize bağlı. Yanıtın her seferinde bir girdisi vardı ve o girdi
sorulmadı: **hangi adımın hangi tür olduğu.** Kurgu bunu bize verdi; gerçek bir programda
kimse vermez.

## Özet

- Yürütücü havuzu iş dağıtmanın ortak arayüzüdür; aynı çağrı biçimi iki arka uçla da
  kullanılır ve eşleme işleminin çıktı sırası girdiden gelir, çizelgeden değil.
- Modelde iş parçacığı arka ucu **işçi = genişlik, yuva = 1**; süreç arka ucu **işçi =
  genişlik, yuva = genişlik** demektir. Bütün fark bu iki ayardadır.
- Sekiz genişlikte aynı görev, iş parçacığı havuzunda üç yükte **31 / 49**, **42 / 38** ve
  **73 / 7** verir; süreç havuzunda üçünde de **10 / 70**.
- Genişliği artırmak iş parçacığı havuzunda yükün girdi/çıktı payı kadar kazandırır ve işlemci
  ağırlıklı yükte ikinci genişlikte durur; süreç havuzunda üç yükte de tik'i yarıya indirir.
- İş parçacığı havuzu üç yükte **3** ayrı tik sayısı verir, süreç havuzu **1**. Aynı arayüzün
  arkasında aynı seçim yoktur; süreç sütunu ayrıca veri devrini saymayan bir üst sınırdır.

## Sonraki Adım

Buraya kadar sayılan şey hep rejimdi: hangi rejim, hangi yükte, ne kazandırır. Her ölçümde
görevlerin adım dizisi elimizin altındaydı — hangi adımın işlemci adımı, hangisinin girdi/çıktı
adımı olduğunu kurgu söylüyordu. Gerçek bir programda o dizi yazılı değildir. Elde bir kod
tabanı vardır ve hangi çağrının ağır olduğu, hangi satırın sıcak yolda durduğu görünmez.
Sonraki ders bu boşluğu kapatır: bir programın hangi adımının ağır olduğu, süre ölçmeden,
**çağrı sayarak** nasıl bulunur?
