İçeriğe geç
academia.sh

Ders 10 / 15

Eşzamanlılık Modelleri

İş parçacığı, olay döngüsü ve ileti geçişi modellerinin aynı iş yükünde süre, boş çekirdek adımı ve doğruluk güvencesi bakımından karşılaştırılması.

İçindekiler

Dört ders boyunca tek bir eşzamanlılık modeli kullanıldı: paylaşılan belleğe erişen iş parçacıkları ve onları koruyan kilitler. Bu modelin bedeli artık sayılı — çekişme sekiz iş parçacığında 252 bekleme adımı, dört kilitli üç iş parçacığında 0,4074 kilitlenme oranı, iki çekirdekte 18 yanlış serpiştirme.

Bu bedellerin hepsinin tek bir ortak kaynağı var: paylaşılan değiştirilebilir durum. Kaldırılırsa hepsi birden kalkar. Bu ders paylaşılan durumu kaldıran ya da erişimini yapısal olarak sıralayan iki modeli ekler ve üçünü aynı iş yükünde sayar.

Üç Model

İş parçacığı modeli. Paylaşılan adres uzayı, önalımlı çizelgeleme, kilitle korunan kritik bölgeler. Buraya kadar ölçülen model budur.

Olay döngüsü modeli. Tek iş parçacığı, önalımsız yürütme, sonuna kadar çalışma. Bekleme işi engellemez; iş bittiğinde sıradaki alınır. Bu model Eşzamansız JavaScript ve Çalışma Zamanı kursunda ayrıntısıyla kuruldu ve ölçüldü; olay döngüsünün kuyruk kuralı, mikro görev ayrımı ve engelleyen işin sonuçları burada tekrarlanmaz. Bu ders onu yalnız üç modelden biri olarak alır.

İleti geçişi modeli. Yalıtılmış durum, paylaşım yok, iletişim yalnız kopyalanan iletilerle. Durum paylaşılmadığı için kilit de gerekmez.

Üç model aynı çizelgeleyicinin üç ayarıdır ve bu, karşılaştırmayı anlamlı kılan şeydir.

EZ26. İş parçacığı modeli: önalımlı, dilim 4, tek çekirdek, bağlam bedeli 2. EZ27. Olay döngüsü modeli: önalımsız, tek çekirdek, bağlam bedeli 0 — geçiş bir adres uzayı değişimi değil, bir sıradaki işe geçiştir. EZ28. İleti geçişi modeli: yalıtılmış durum, dört çekirdek, bağlam bedeli 2. EZ29. İleti kopyalama bedeli bu tanımda modellenmemiştir ve ölçülmemiş sayılır. EZ30. Üç model aynı iş listesini yürütür; iş yükü özdeştir.

TOHUM = 20260218
SUREC_SAYISI = 5
ADIM_SAYISI = 12
BEKLEME_SURESI = 30      # bir girdi/cikti adimi kac zaman birimi surer
BAGLAM_BEDELI = 2        # bir baglam degistirmenin bedeli (zaman birimi)
SANAL_SAYFA = 16


def uretec(tohum):
    """Belirlenimci sozde-rastgele uretec. Ayni tohum ayni diziyi verir."""
    d = tohum

    def sonraki(n):
        nonlocal d
        d = (d * 1103515245 + 12345) % 2147483648
        return d % n
    return sonraki


def is_yuku(tohum=TOHUM):
    r = uretec(tohum)
    isler = []
    for i in range(SUREC_SAYISI):
        adimlar = []
        for _ in range(ADIM_SAYISI):
            if r(10) < 3:
                adimlar.append(("BEKLE", BEKLEME_SURESI))
            else:
                taban = (i * 3) % SANAL_SAYFA
                adimlar.append(("HESAP", (taban + r(4)) % SANAL_SAYFA))
        isler.append({"ad": f"S{i+1}", "adim": adimlar,
                      "oncelik": 1 + r(3), "varis": i * 4})
    return isler


SONSUZ = 10**9


def cizelgele(isler, yordam="sirayla", dilim=4, cekirdek=1,
              baglam_bedeli=BAGLAM_BEDELI):
    """Her zaman biriminde her cekirdek en cok bir adim yurutur."""
    durum = [{"ad": i["ad"], "adim": list(i["adim"]), "yer": 0, "varis": i["varis"],
              "hazir": i["varis"], "kullanim": 0, "bitis": None,
              "oncelik": i["oncelik"]} for i in isler]
    pay_siniri = SONSUZ if yordam == "sirayla" else dilim
    cekirdekler = [{"surec": None, "onceki": None, "pay": 0, "engel": 0}
                   for _ in range(cekirdek)]
    t, baglam, bos_adim = 0, 0, 0

    def bitmedi(d):
        return d["yer"] < len(d["adim"])

    while any(bitmedi(d) for d in durum) or any(d["bitis"] is None or d["bitis"] > t
                                               for d in durum):
        for c in cekirdekler:                       # birakma
            d = c["surec"]
            if d is not None and (not bitmedi(d) or d["hazir"] > t or c["pay"] >= pay_siniri):
                c["surec"] = None
        for c in cekirdekler:                       # atama
            if c["engel"] or c["surec"] is not None:
                continue
            tutulan = [x["surec"] for x in cekirdekler if x["surec"] is not None]
            hazir = [d for d in durum if bitmedi(d) and d["hazir"] <= t and d not in tutulan]
            if not hazir:
                continue
            if yordam == "oncelikli":
                sec = min(hazir, key=lambda d: (-d["oncelik"], d["hazir"], d["ad"]))
            elif yordam == "adil":
                sec = min(hazir, key=lambda d: (d["kullanim"], d["hazir"], d["ad"]))
            else:
                sec = min(hazir, key=lambda d: (d["hazir"], d["ad"]))
            if c["onceki"] is not None and c["onceki"] is not sec:
                baglam += 1
                c["engel"] = baglam_bedeli
            c["surec"] = sec
            c["onceki"] = sec
            c["pay"] = 0
        for c in cekirdekler:                       # yurutme
            if c["engel"]:
                c["engel"] -= 1
                continue
            d = c["surec"]
            if d is None:
                bos_adim += 1
                continue
            tur, deger = d["adim"][d["yer"]]
            if tur == "BEKLE":
                d["yer"] += 1
                d["hazir"] = t + deger
                c["surec"] = None
                bos_adim += 1
                if not bitmedi(d):
                    d["bitis"] = t + deger
            else:
                d["yer"] += 1
                d["kullanim"] += 1
                d["hazir"] = t + 1
                c["pay"] += 1
                if not bitmedi(d):
                    d["bitis"] = t + 1
                    c["surec"] = None
        t += 1
    for d, i in zip(durum, isler):
        gc = sum(v for tur, v in i["adim"] if tur == "BEKLE")
        d["bekleme"] = d["bitis"] - d["varis"] - d["kullanim"] - gc
    return {"sure": t, "baglam": baglam, "bos_cekirdek_adimi": bos_adim,
            "toplam_is": sum(d["kullanim"] for d in durum),
            "ortalama_tamamlanma": round(sum(d["bitis"] - d["varis"] for d in durum) / len(durum), 2),
            "ortalama_bekleme": round(sum(d["bekleme"] for d in durum) / len(durum), 2),
            "bitis": {d["ad"]: d["bitis"] for d in durum}}


MODELLER = (("is parcacigi", dict(yordam="dilimli", dilim=4, cekirdek=1, baglam_bedeli=2)),
            ("olay dongusu", dict(yordam="sirayla", cekirdek=1, baglam_bedeli=0)),
            ("ileti gecisi", dict(yordam="dilimli", dilim=4, cekirdek=4, baglam_bedeli=2)))

for k, tohum in enumerate((20260218, 20260219)):
    if k:
        print()
    ISLER = is_yuku(tohum)
    hesap = sum(1 for i in ISLER for t, _ in i["adim"] if t == "HESAP")
    print(f"is yuku {tohum}: {hesap} hesap adimi , "
          f"{SUREC_SAYISI * ADIM_SAYISI - hesap} bekleme adimi")
    print("  model         sure  baglam  bos cekirdek  ort.tamamlanma  ort.bekleme")
    for ad, ayar in MODELLER:
        s = cizelgele(ISLER, **ayar)
        print(f"  {ad:12s}  {s['sure']:4d}  {s['baglam']:6d}  {s['bos_cekirdek_adimi']:12d}"
              f"  {s['ortalama_tamamlanma']:14.2f}  {s['ortalama_bekleme']:11.2f}")
is yuku 20260218: 39 hesap adimi , 21 bekleme adimi
  model         sure  baglam  bos cekirdek  ort.tamamlanma  ort.bekleme
  is parcacigi   197      25           108          153.80        20.00
  olay dongusu   178      22           139          137.20         3.40
  ileti gecisi   179      19           639          141.40         7.60

is yuku 20260219: 46 hesap adimi , 14 bekleme adimi
  model         sure  baglam  bos cekirdek  ort.tamamlanma  ort.bekleme
  is parcacigi   202      22           112          122.20        29.00
  olay dongusu   177      14           131           98.00         4.80
  ileti gecisi   175      12           630           98.00         4.80

Tabloda Ne Duruyor

En net sonuç, iş parçacığı modelinin iki iş yükünde de en kötü süreyi vermesidir: birincide 197, ikincide 202. Bu, ortak tanımın birinci okumasının bu derse düşen yüzüdür — önalımlı dilimleme adaleti süreyle ödetir ve bedel her iki iş bileşiminde de ayakta kalır.

Olay döngüsü ile ileti geçişi arasındaki fark ise ölçülemiyor. Birinci iş yükünde 178’e karşı 179, yani 1 zaman birimi; ikincisinde 177’ye karşı 175, yani 2 zaman birimi. Bu iş yükünde ölçüm bandının alt sınırı bağlam bedeli kadardır, yani 2 zaman birimi. İlk fark bandın altında ve yorumlanamaz; ikincisi tam sınırında ve tek başına bir sıralama kurmaya yetmez.

Bu iki modelin farkı süre sütununda değil, boş çekirdek adımı sütununda duruyor. Olay döngüsü birinci iş yükünde 139, ileti geçişi 639 boş çekirdek adımı harcıyor. Aynı süreyi almak için ileti geçişi dört çekirdek kullanıyor; olay döngüsü bir. Süre eşit, kaynak dört buçuk katı.

Sıralama iddiası kurulamaz, ama bedel karşılaştırması kurulabilir: bu iş yükünde ileti geçişinin dört çekirdeği bir süre kazancı üretmiyor.

İş Yükü Bileşimi Neyi Değiştiriyor

İki iş yükü aynı beş süreci farklı bileşimde taşıyor: birincisinde 39 hesap, 21 bekleme; ikincisinde 46 hesap, 14 bekleme. İkincisi daha hesap ağırlıklı.

Hesap payı arttıkça ileti geçişi göreli olarak iyileşiyor: birinci iş yükünde olay döngüsünün 1 zaman birimi gerisindeyken, ikincisinde 2 zaman birimi önüne geçiyor. Yön beklenen yöndür — çekirdek eklemek hesabı paralelleştirir, beklemeyi paralelleştirmez. Ama büyüklük ölçüm bandının sınırındadır ve bu kursta böyle bir fark üstünlük iddiasına çevrilmez.

Bağlam değiştirme sütunu daha net konuşuyor. İkinci iş yükünde iş parçacığı modeli 22, olay döngüsü 14, ileti geçişi 12 bağlam değiştirme üretiyor. Önalımın bedeli burada doğrudan görünür.

Ortalama tamamlanma süresi de ayrışıyor: ikinci iş yükünde iş parçacığı modeli 122,20, diğer ikisi 98,00. Süre farkı ölçülemezken tekil işlerin bitiş süresi ölçülebilir biçimde ayrılıyor — hangi ölçütün sorulduğu, hangi modelin kazandığını değiştirir.

Doğruluk Ekseni

Süre tek eksen değil. Üç model, aynı paylaşılan sayaç sorusuna üç ayrı güvence verir.

def sayac_kosumu(desen: list[int]) -> int:
    sayac, yerel = 0, {0: None, 1: None}
    asama = {0: 0, 1: 0}
    for kim in desen:
        a = asama[kim]
        if a == 0:
            yerel[kim] = sayac
        elif a == 1:
            yerel[kim] = yerel[kim] + 1
        else:
            sayac = yerel[kim]
        asama[kim] = a + 1
    return sayac


def serpistirmeler(a: int, b: int) -> list[list[int]]:
    if a == 0:
        return [[1] * b]
    if b == 0:
        return [[0] * a]
    return ([[0] + s for s in serpistirmeler(a - 1, b)]
            + [[1] + s for s in serpistirmeler(a, b - 1)])


def dilimli_serpistirmeler(adim: int, dilim: int) -> list[list[int]]:
    sonuc = []

    def gez(kalan_a, kalan_b, kim, dizi):
        if not kalan_a and not kalan_b:
            sonuc.append(list(dizi))
            return
        for yeni in (0, 1):
            kalan = kalan_a if yeni == 0 else kalan_b
            if not kalan:
                continue
            n = min(dilim, kalan)
            dizi.extend([yeni] * n)
            gez(kalan_a - n if yeni == 0 else kalan_a,
                kalan_b - n if yeni == 1 else kalan_b, yeni, dizi)
            del dizi[len(dizi) - n:]
    gez(adim, adim, None, [])
    ayri = []
    for d in sonuc:
        if d not in ayri:
            ayri.append(d)
    return ayri


print("model         paylasilan durum  kritik bolge bolunur  erisilebilen  yanlis")
for ad, paylasim, bolunur in (("is parcacigi", "var", True),
                              ("olay dongusu", "var", False),
                              ("ileti gecisi", "yok", None)):
    if paylasim == "yok":                 # sayaci tek sahip degistirir , serpisme yoktur
        print(f"  {ad:12s}  {paylasim:16s}  {'-':>20s}  {'-':>12s}  {'-':>6s}")
        continue
    kume = serpistirmeler(3, 3) if bolunur else dilimli_serpistirmeler(3, 3)
    yanlis = sum(1 for d in kume if sayac_kosumu(d) != 2)
    print(f"  {ad:12s}  {paylasim:16s}  {str(bolunur):>20s}  {len(kume):12d}  {yanlis:6d}")
model         paylasilan durum  kritik bolge bolunur  erisilebilen  yanlis
  is parcacigi  var                               True            20      18
  olay dongusu  var                              False             2       0
  ileti gecisi  yok                                  -             -       -

İş parçacığı modelinde kritik bölge bölünebilir; korunmazsa 20 serpiştirmenin 18’i yanlış sonuç verir. Korunursa doğruluk gelir ve bedeli önceki derslerde sayıldı: dört iş parçacığında süre 29’dan 47’ye, bekleme 18’den 54’e çıkar.

Olay döngüsü modelinde kritik bölge bölünemez: sonuna kadar çalışma kuralı, bir işin ortasında başka bir işin çalışmasını yapısal olarak yasaklar. Erişilebilen serpiştirme 2, yanlış 0 ve bu, birinci dersteki dilim ayarından türce başkadır — orada koruma bir ayardı, burada modelin tanımıdır. Buna karşılık aynı kural bir sınır getirir: uzun bir hesap adımı bütün kuyruğu bekletir ve model tek çekirdeği aşamaz.

İleti geçişi modelinde soru sorulamaz: sayacı tek bir sahip değiştirir, öbür taraf ileti gönderir. Paylaşılan değiştirilebilir durum olmadığı için kritik bölge de, kilit de, kilitlenme de, bellek görünürlüğü de yoktur. Bedeli, ölçülmeyen bir yerde durur — her iletide durumun kopyalanması (EZ29).

Modeller Birbirini Dışlamaz

Üç modelin aynı çizelgeleyicinin üç ayarı olması yalnız ölçüm kolaylığı değil, yapısal bir gözlemdir. Ayarlar birbirinden bağımsızdır ve karıştırılabilir.

Bunun en görünür örneği tablodadır. Olay döngüsü ayarı tek çekirdeklidir; ileti geçişi ayarı dört çekirdeklidir ve durumu yalıtır. İkisini birleştirmek, her çekirdekte bir olay döngüsü çalıştırmak ve aralarında yalnız ileti göndermek demektir. Bu bileşim yeni bir model değildir; iki ayarın aynı anda seçilmesidir.

Aynı biçimde, iş parçacığı modeli de yalıtımla birleştirilebilir: paylaşılan durum yalnız gerçekten paylaşılması gereken yerde bırakılır, geri kalanı iş parçacığına özel tutulur. Kritik bölge kısaldıkça çekişme düşer ve bu düşüşün ölçüsü ikinci derste alınmıştı — sekiz iş parçacığında kritik pay 0,50’den 0,05’e indiğinde süre 83’ten 20’ye iniyordu.

Buradan çıkan kural şudur: model bir bayrak değil, bir ayar kümesidir. Sorulacak soru “hangi model” değil, “hangi durum paylaşılacak, önalım olacak mı, kaç çekirdek kullanılacak” sorularıdır. Her birinin bedeli bu konuda ayrı ayrı sayıldı.

Model Seçimi Neyi Seçmektir

Model Süre (39/21) Süre (46/14) Boş çekirdek Doğruluk güvencesi
İş parçacığı 197 202 108 / 112 yok, kilitle kurulur
Olay döngüsü 178 177 139 / 131 sonuna kadar çalışma
İleti geçişi 179 175 639 / 630 paylaşım yok

Tablodan çıkarılabilecek tek genel sonuç, iş parçacığı modelinin iki iş yükünde de en kötü süreyi verdiğidir. Diğer iki model arasındaki fark, iki iş yükünde de ölçüm bandının içinde ya da sınırındadır; bu kursta böyle bir fark ölçülmemiş sayılır.

Seçim bu yüzden süreyle yapılmaz. Seçilen şey hangi bedelin ödeneceğidir: iş parçacığı modelinde çekişme ve kilitlenme riski, olay döngüsünde tek çekirdek sınırı, ileti geçişinde kopyalama ve dört buçuk kat boş çekirdek adımı.

Özet

  • Üç model aynı iş yükünde ölçüldüğünde iş parçacığı modeli iki iş yükünde de en kötü süreyi verir: 197 ve 202.
  • Olay döngüsü ile ileti geçişi arasındaki süre farkı 1 ve 2 zaman birimidir; ölçüm bandının altında ya da sınırındadır ve bir sıralama kurmaya yetmez.
  • Fark boş çekirdek adımında görünür: aynı süre için olay döngüsü 139, ileti geçişi 639 boş çekirdek adımı harcar.
  • Doğruluk güvenceleri türce farklıdır: iş parçacığı modelinde güvence yoktur ve kilitle kurulur; olay döngüsünde sonuna kadar çalışmadan gelir; ileti geçişinde paylaşım olmadığı için soru sorulamaz.
  • Hangi ölçütün sorulduğu kazananı değiştirir: ikinci iş yükünde süre farkı ölçülemezken ortalama tamamlanma 122,20’ye karşı 98,00 ile ayrışır.

Sonraki Adım

Bu konu, eşzamanlılığın bedelini üç eksende saydı: bekleme adımı, kilitlenme oranı ve erişilebilen serpiştirme kümesi. Hepsinde ortak varsayım, belleğin sınırsız ve erişimin bedelsiz olmasıydı — bir hesap adımı her zaman bir zaman birimi sürdü. Sonraki konu bu varsayımı kaldırır. Bellek sonludur, adres uzayı fizikselden büyüktür ve bir erişim diskten gelen bir sayfayı beklemek zorunda kalabilir. İlk ders bu iş yükünün ürettiği 39 erişimlik diziyi alıp 15 ayrı sanal sayfa üzerinde üç sayfa değiştirme yordamını süpürecek ve daha akıllı yordamın her zaman kazandırmadığını gösterecek.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat