İçeriğe geç
academia.sh

Ders 05 / 15

Çizelgeleme Algoritmaları

Dört çizelgeleyici, aynı iş yükü: önalımsız sıra 194, dilimli 197, öncelikli 195, adil paylaşımlı 192 zaman birimi veriyor; dilim 4'ten 1'e indiğinde süre 206'ya, bağlam değiştirme 36'ya çıkıyor, ikinci iş yükünde sıralama değişiyor ve iki iş yükünde de en iyi olan hiçbir yordam bulunmuyor.

İçindekiler

Önceki dört ders yürütme birimlerinin nasıl kurulduğunu ölçtü: kaç adres uzayı, kaç kopyalanan sayfa, kaç etkilenen birim. Kurulum bittiğinde geriye her zaman biriminde yeniden sorulan tek bir soru kalır — hazır birimlerden hangisi koşacak.

Bu kararı veren bileşen çizelgeleyicidir (scheduler) ve kararın nasıl verildiği ölçülebilir bir farktır. Bu ders aynı beş süreçlik iş yükünü dört ayrı yordamla koşturur, sonra aynı karşılaştırmayı ikinci bir iş yükünde yineler. Dersin sonucu tek bir yordamın seçilmesi değildir; hiçbir yordamın her iş yükünde en iyi olmadığının gösterilmesidir.

  • SR31. Çizelgeleyici her zaman biriminde hazır birimlerden birini seçer. Hazır olmayan birim, bekleme adımındadır ve seçilemez.
  • SR32. Önalımsız sıra, bir süreci bitene ya da bir bekleme adımına girene kadar bırakmaz; hazır olanlar arasında en erken hazır olanı seçer.
  • SR33. Dilimli yordam önalımlıdır: bir süreç en çok 4 zaman birimi koşar, sonra çekirdeği bırakır. Bu süreye zaman dilimi, kısaca dilim denir.
  • SR34. Öncelikli yordam en yüksek öncelikli hazır süreci seçer; öncelikler iş yükünün parçasıdır ve ikinci iş yükünde farklıdır.
  • SR35. Adil paylaşımlı yordam, o ana kadar en az çekirdek kullanmış hazır süreci seçer.
  • SR36. Ölçülen büyüklükler: süre (bütün işin bitmesine kadar geçen zaman birimi), bağlam değiştirme sayısı, boş çekirdek adımı, ortalama tamamlanma süresi (varıştan bitişe) ve ortalama bekleme (hazır ama koşamadığı zaman birimi).
  • SR37. İkinci iş yükü tohumu 20260219’dur. Aynı beş süreç yapısı, farklı adım bileşimi ve farklı öncelikler verir.
  • SR38. Çözünürlük 2 zaman birimidir. İki yordam arasındaki 1 birimlik fark ölçülmemiş sayılır ve sıralamaya girmez.

İki İş Yükü

İki tohum aynı yapıyı üretir ama farklı bir bileşim verir. Fark, hesap adımı ile bekleme adımı arasındaki dağılımdadır ve çizelgeleyicilerin davranışını belirleyen şey tam olarak budur.

# Bu makine bir BENZETICIDIR. Hicbir gercek cizelgeleyici cagrilmaz; butun
# sureler modeldeki zaman birimidir.
TOHUM = 20260218
IKINCI_TOHUM = 20260219
SUREC_SAYISI = 5
ADIM_SAYISI = 12
BEKLEME_SURESI = 30
BAGLAM_BEDELI = 2
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):
    """Bir adim ya ("HESAP", sanal_sayfa) ya da ("BEKLE", sure)."""
    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


ISLER = is_yuku()
print("is yuku  hesap adimi  bekleme adimi  oncelikler")
for tohum in (TOHUM, IKINCI_TOHUM):
    y = is_yuku(tohum)
    h = sum(1 for i in y for t, _ in i["adim"] if t == "HESAP")
    print(f"{tohum}  {h:10d}  {SUREC_SAYISI * ADIM_SAYISI - h:13d}"
          f"  {[i['oncelik'] for i in y]}")
is yuku  hesap adimi  bekleme adimi  oncelikler
20260218          39             21  [3, 2, 1, 3, 2]
20260219          46             14  [1, 2, 3, 1, 1]

İkinci iş yükü daha hesap ağırlıklıdır: 60 adımın 46’sı çekirdeği tutar, ilkinde bu sayı 39’du. Bu, çizelgeleyici için daha zor bir iştir, çünkü çekirdek için çekişen süreç sayısı artmıştır. Öncelikler de değişmiştir ve tek bir sürecin önceliği 3’tür.

Dört Yordam, Aynı İş Yükü

Aşağıdaki gerçeklenim dört yordamı tek gövdede toplar. Aralarındaki tek fark iki satırdır: hazır kümesinden hangisinin seçildiği ve bir sürecin dilimini doldurup doldurmadığına bakılıp bakılmadığı.

# Ilk blogun uzerine: ISLER ve BAGLAM_BEDELI oradan gelir.
SONSUZ = 10**9


def cizelgele(isler, yordam="sirayla", dilim=4, cekirdek=1,
              baglam_bedeli=BAGLAM_BEDELI):
    """yordam: sirayla (onalimsiz) | dilimli | oncelikli | adil
    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):                  # son adim beklemeyse is o zaman biter
                    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}}


YORDAM = ("sirayla", "dilimli", "oncelikli", "adil")
print("cizelgeleyici  sure  baglam  bos.cek  ort.tamamlanma  ort.bekleme")
for y in YORDAM:
    s = cizelgele(ISLER, y)
    print(f"  {y:12s} {s['sure']:4d}  {s['baglam']:5d}  {s['bos_cekirdek_adimi']:6d}"
          f"  {s['ortalama_tamamlanma']:13.2f}  {s['ortalama_bekleme']:10.2f}")
print()
print("dilim supurmesi (dilimli)")
print("dilim  sure  baglam  ort.bekleme")
for d in (1, 2, 4, 8, 16):
    s = cizelgele(ISLER, "dilimli", dilim=d)
    print(f"{d:5d}  {s['sure']:4d}  {s['baglam']:5d}  {s['ortalama_bekleme']:11.2f}")
cizelgeleyici  sure  baglam  bos.cek  ort.tamamlanma  ort.bekleme
  sirayla       194     22     111         148.40       14.60
  dilimli       197     25     108         153.80       20.00
  oncelikli     195     21     114         149.00       15.20
  adil          192     25     103         153.00       19.20

dilim supurmesi (dilimli)
dilim  sure  baglam  ort.bekleme
    1   206     36        33.00
    2   202     29        26.60
    4   197     25        20.00
    8   194     22        14.60
   16   194     22        14.60

Dört yordamın süreleri 192 ile 197 arasındadır; aralarındaki en büyük fark 5 zaman birimidir, yani toplam sürenin yüzde 2,6’sı. Bu, önemli bir okumadır: çizelgeleyici seçimi bu iş yükünde büyük bir kaldıraç değildir. Asıl belirleyici, iş yükünün kendi bekleme adımlarıdır ve onlar 630 zaman birimi tutar.

Önalımlı yordam, önalımsız sıradan 3 zaman birimi daha uzun sürer ve 3 bağlam değiştirme fazla yapar. Ortalama bekleme 14,60’tan 20,00’a çıkar. Dilimlemenin sağladığı şey — hiçbir sürecin çekirdeği uzun süre tutamaması — süreyle ödenir.

Dilim Küçüldükçe Kötüleşir

Süpürme bu ödemenin doğrudan ölçüsüdür. Dilim 4’ten 1’e indiğinde süre 197’den 206‘ya, bağlam değiştirme 25’ten 36‘ya, ortalama bekleme 20,00’dan 33,00‘a çıkar. Her adımda çekirdeği bırakmak, adımların kendisinden çok bağlam değiştirmeye zaman harcamak demektir: 36 geçiş 72 zaman birimi tutar ve iş yükünün toplam hesap adımı 39’dur.

Öteki uçta süpürme durur. Dilim 8 ile dilim 16 tıpatıp aynı sonucu verir: 194, 22, 14,60. Bunun nedeni açıktır — bu iş yükünde hiçbir süreç art arda sekizden fazla hesap adımı yürütmez, dolayısıyla dilim 8’in üstünde önalım hiç tetiklenmez. Bu iş yükünün çözünürlüğü dilim 8’de tükenir; daha büyük dilimlerle yapılan bir karşılaştırma yeni bilgi vermez. Dilim 8’deki 194 ve 22, önalımsız sıranın sayılarının tıpatıp aynısıdır ve olması gereken de budur: önalımın hiç tetiklenmediği bir dilimli yordam, önalımsız yordamdır.

Toplam Süre Neyi Gizler

Toplam süre tek başına bakıldığında dört yordam birbirine yakın durur. Yordamların birbirinden ayrıldığı yer toplam değil, dağılımdır: aynı 192 ile 197 arasındaki süre, süreçler arasında çok farklı biçimlerde bölüşülebilir.

# Onceki bloklarin uzerine: ISLER, cizelgele ve YORDAM.
print("cizelgeleyici  S1   S2   S3   S4   S5   en genis fark")
for y in YORDAM:
    s = cizelgele(ISLER, y)
    t = [s["bitis"][i["ad"]] - i["varis"] for i in ISLER]
    print(f"  {y:12s} " + " ".join(f"{x:4d}" for x in t) + f" {max(t) - min(t):13d}")
print()
print("oncelik 3 olan surecler:", [i["ad"] for i in ISLER if i["oncelik"] == 3])
print("oncelik 1 olan surecler:", [i["ad"] for i in ISLER if i["oncelik"] == 1])
for y in ("sirayla", "oncelikli"):
    s = cizelgele(ISLER, y)
    yuksek = [s["bitis"][i["ad"]] - i["varis"] for i in ISLER if i["oncelik"] == 3]
    dusuk = [s["bitis"][i["ad"]] - i["varis"] for i in ISLER if i["oncelik"] == 1]
    print(f"{y:10s} yuksek oncelik ort. {sum(yuksek) / len(yuksek):6.2f}"
          f" | dusuk oncelik ort. {sum(dusuk) / len(dusuk):6.2f}")
cizelgeleyici  S1   S2   S3   S4   S5   en genis fark
  sirayla       103  112  176  173  178            75
  dilimli       111  120  175  185  178            74
  oncelikli     103  112  187  169  174            84
  adil          127  115  170  180  173            65

oncelik 3 olan surecler: ['S1', 'S4']
oncelik 1 olan surecler: ['S3']
sirayla    yuksek oncelik ort. 138.00 | dusuk oncelik ort. 176.00
oncelikli  yuksek oncelik ort. 136.00 | dusuk oncelik ort. 187.00

Son sütun adil paylaşımlı yordamın ne yaptığını gösterir: en hızlı ve en yavaş sürecin tamamlanma süreleri arasındaki fark 65 zaman birimidir, dört yordamın en darı. Öncelikli yordamda aynı fark 84’tür, en genişi. Adaletin ölçüsü toplam süre değil bu farktır ve adil paylaşımlı yordam onu 19 birim daraltır.

Öncelikli yordamın kime ne kazandırdığı ayrıca sayılabilir. Önceliği 3 olan iki süreç, önalımsız sırada ortalama 138,00 zaman biriminde biterken öncelikli yordamda 136,00’da biter: 2 zaman birimi, yani çözünürlüğün tam sınırında bir kazanç. Önceliği 1 olan süreç ise 176,00’dan 187,00’a geriler — 11 zaman birimi kayıp. Öncelik vermek, kayırılanlara ölçülemeyecek kadar az kazandırıp kayırılmayana ölçülebilir bir bedel ödetir.

Sıralama İkinci İş Yükünde Ayakta Kalıyor mu

Tek bir iş yükünde ölçülmüş bir sıralama, o iş yüküne ait bir olgudur. Sonucun bir kural olabilmesi için ikinci bir iş yükünde de sınanması gerekir.

# Onceki bloklarin uzerine: is_yuku, cizelgele, YORDAM ve IKINCI_TOHUM.
SONUC = {y: [cizelgele(is_yuku(t), y)["sure"] for t in (TOHUM, IKINCI_TOHUM)]
         for y in YORDAM}
EN_IYI = [min(SONUC[y][k] for y in YORDAM) for k in (0, 1)]
print("cizelgeleyici  20260218  fark  20260219  fark")
for y in YORDAM:
    a, b = SONUC[y]
    print(f"  {y:12s} {a:8d} {a - EN_IYI[0]:5d} {b:9d} {b - EN_IYI[1]:5d}")
print()
for k, tohum in enumerate((TOHUM, IKINCI_TOHUM)):
    en_iyi = [y for y in YORDAM if SONUC[y][k] == EN_IYI[k]]
    en_kotu = [y for y in YORDAM if SONUC[y][k] == max(SONUC[z][k] for z in YORDAM)]
    print(f"{tohum}: en iyi {en_iyi} | en kotu {en_kotu}")
print("iki is yukunde de en iyi olan:",
      [y for y in YORDAM if SONUC[y][0] == EN_IYI[0] and SONUC[y][1] == EN_IYI[1]])
print("cozunurluk altinda kalan cift (fark < 2):",
      [(y, z, k) for k in (0, 1) for i, y in enumerate(YORDAM)
       for z in YORDAM[i + 1:] if abs(SONUC[y][k] - SONUC[z][k]) < 2])
cizelgeleyici  20260218  fark  20260219  fark
  sirayla           194     2       189     0
  dilimli           197     5       202    13
  oncelikli         195     3       196     7
  adil              192     0       195     6

20260218: en iyi ['adil'] | en kotu ['dilimli']
20260219: en iyi ['sirayla'] | en kotu ['dilimli']
iki is yukunde de en iyi olan: []
cozunurluk altinda kalan cift (fark < 2): [('sirayla', 'oncelikli', 0), ('oncelikli', 'adil', 1)]

Hangi Sonuç Ayakta Kalır

Çıktının son dört satırı bu dersin bütün iddialarını sınırlar.

Ayakta kalan sonuç: dilimleme adaleti süreyle ödetir. Dilimli yordam iki iş yükünde de en kötüdür — ilkinde en iyiden 5, ikincisinde 13 zaman birimi geride. İkinci iş yükünde fark üç katına çıkar, çünkü hesap ağırlıklı bir iş yükünde önalım daha sık tetiklenir. Bu sonuç iki ölçümde de aynı yönde durur ve yazılabilir.

Ayakta kalmayan sonuç: adil paylaşımın üstünlüğü. Adil paylaşımlı yordam ilk iş yükünde en iyidir, ikincisinde en iyiden 6 zaman birimi geridedir. Aynı yordam bir iş yükünde birinci, ötekinde değildir; dolayısıyla “adil paylaşım en iyisidir” cümlesi ölçülmemiş bir iddiadır ve kurulamaz.

İki iş yükünde de en iyi olan yordam listesi boştur. Bu, dersin ana sonucudur: bir çizelgeleyicinin üstünlüğü kendisinin değil, iş yükünün bileşiminin özelliğidir. Önalımsız sıra hesap ağırlıklı ikinci iş yükünde birinciye çıkar, çünkü orada süreçlerin bekleme adımı azdır ve bölmeden koşturmak toplamı kısaltır.

Son satır çözünürlüğün nasıl çalıştığını gösterir. İlk iş yükünde önalımsız sıra (194) ile öncelikli (195) arasındaki 1 birim, ikinci iş yükünde öncelikli (196) ile adil paylaşımlı (195) arasındaki 1 birim çözünürlüğün altındadır. Bu çiftler ayrılmaz; aralarında bir sıralama yazmak, ölçülmemiş bir farkı ölçülmüş gibi sunmak olur.

Özet

  • Çizelgeleyici, her zaman biriminde hazır birimlerden hangisinin koşacağına karar verir; dört yordam bu kararı önalım ve seçim ölçütü bakımından farklı verir.
  • Aynı iş yükünde dört yordamın süresi 192 ile 197 arasındadır; en büyük fark 5 zaman birimi, yani yüzde 2,6’dır. Çizelgeleyici seçimi bu iş yükünde büyük bir kaldıraç değildir.
  • Dilim küçüldükçe kötüleşir: dilim 1’de süre 206, bağlam değiştirme 36, ortalama bekleme 33,00 olur. Dilim 8 ile 16 aynı sonucu verir; bu iş yükünün çözünürlüğü dilim 8’de tükenir.
  • Dilimli yordam iki iş yükünde de en kötüdür (197 ve 202); dilimleme adaleti süreyle ödetir ve bu sonuç iki ölçümde de ayaktadır.
  • İki iş yükünde de en iyi olan yordam yoktur: adil paylaşımlı ilkinde birinci, önalımsız sıra ikincisinde birincidir. Üstünlük yordamın değil, iş yükünün bileşiminin özelliğidir.
  • Çözünürlük altındaki 1 birimlik farklar ölçülmemiş sayılır; iki çift bu nedenle ayrılmaz kalır ve aralarına sıralama yazılmaz.

Sonraki Adım

Bu konu boyunca birimler birbirinden ayrı sayıldı: her biri kendi adımlarını yürütüyor, çizelgeleyici aralarında gidip geliyordu. Bir varsayım hiç sınanmadı — bir birimin adımı bölündüğünde sonucun değişmeyeceği varsayımı. Kursun sonraki konusu bu varsayımı bozar ve tek bir cümleyi kanıtlar: aynı programın iki birimi aynı veriye dokunduğunda doğru çıktı doğru program demek değildir.

İ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