İçeriğe geç
academia.sh

Ders 02 / 10

İş Parçacıkları

Sekiz işçi ve tek yuva, seksen adımı girdi/çıktı ağırlıklı yükte 31 tikte bitirir (kazanç 49, oran 0,6125), işlemci ağırlıklı yükte ancak 73 tikte (kazanç 7); aynı düzenek, yedi kat fark ve kazanç her yükte örtüşebilen adım sayısıyla sınırlıdır.

İçindekiler

Önceki ders tikin içine baktı ve toplam tik sayısını hiç yazmadı. Tek yuvalı rejimin ilk on iki tikinde işlemci sütunu hep 1’di, girdi/çıktı sütunu ise dörde kadar çıkıyordu. Buradan bir alt sınır çıkmıştı: 26 işlemci adımı en az 26 ayrı tike dağılmak zorunda.

Bu ders sayının kendisini sorar. Sekiz görevi aynı anda sıraya sokmak — yani iş parçacığı (thread) açmak — seksen adımı kaç tikte bitirir? Yanıt tek bir sayı değil. Aynı düzenek, yükün bileşimine göre iki apayrı sayı verir ve bu dersin ölçtüğü şey aradaki farkın büyüklüğüdür.

İş Parçacığı İşçi Ekler, Yuva Eklemez

İş parçacığı, aynı süreç içinde ayrı bir yürütme akışıdır. Süreç, iş parçacığı, çizelgeleme ve bağlam değiştirme İşletim Sistemi Kavramları kursunda mekanizma olarak kuruldu; burada tekrarlanmaz. Bu dersin sorusu mekanizma değil, sayı: iş parçacığı açmak modelin hangi ayarını değiştirir?

Yanıt önceki dersin iki ayarında yazılı. Sekiz iş parçacığı, sekiz görevin aynı anda sıraya girebilmesi demektir; yani işçi sayısı sekize çıkar. Ama sekiz iş parçacığı da aynı yorumlayıcının içindedir ve o yorumlayıcının kilidi tektir. Yuva birde kalır.

Bunun doğrudan sonucu şudur: iş parçacığı eklemek, girdi/çıktı adımlarının örtüşmesine izin verir; işlemci adımlarının örtüşmesine izin vermez. Bir iş parçacığı ağdan yanıt beklerken kilidi bırakır ve başka bir iş parçacığı ilerler. İkisi de aynı anda bayt kodu yürütmek isterse biri bekler.

Bu ayrım, iş parçacığı hakkındaki iki yaygın cümlenin ikisini de düzeltiyor. “İş parçacığı işi paralel yapar” cümlesi yalnız girdi/çıktı adımları için doğrudur; işlemci adımlarında paralellik yoktur, sıra vardır. “Kilit yüzünden iş parçacığı işe yaramaz” cümlesi ise girdi/çıktı adımlarını görmez. İkisinin de eksiği aynı: hangi adımdan söz edildiğini söylememek. Aşağıdaki ölçüm tam olarak bu ayrımı sayıyor.

Rejim Modellenir, Çalıştırılmaz

Bu ders gerçek iş parçacığı başlatmaz ve bu bir kolaylık tercihi değil, ölçümün koşuludur. Gerçekten sekiz iş parçacığı açan bir program, hangi iş parçacığının hangi anda ilerlediğini işletim sisteminin çizelgeleyicisine bırakır. Aynı program iki kez koştuğunda iki ayrı sıra üretir; yazılan çıktı okuyanın makinesinde çıkmaz. Ölçülmek istenen şey — hangi adımın örtüştüğü — o gürültünün altında kalır.

Onun yerine çizelgeleme modellenir: sıra kuralı yazılıdır, tohum sabittir, koşum her yerde aynı sayıyı verir.

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

  • EM13 — Çekirdek önceki dersin aynısıdır: sekiz görev, görev başına on adım, toplam seksen adım; tohum sabit, kurgu belirlenimci.
  • EM14 — İş parçacığı rejiminin modeldeki karşılığı işçi 8, yuva 1’dir.
  • EM15 — Gerçek iş parçacığı başlatılmaz; başlatılsaydı çıktı çizelgeleyiciye bağlı olurdu ve yeniden üretilemezdi.
  • EM16 — Karşılaştırma tabanı tek akış rejimidir (işçi 1, yuva 1) ve üç yükte de 80 tik verir.
  • EM17 — Kazanç, tek akış tikinden rejimin tikinin çıkarılmasıdır; oran kazancın tek akış tikine bölümüdür. Bu bir hızlanma çarpanı değildir, iki tik sayısının farkıdır.
  • EM18 — Alt sınır, önceki derste kurulan kuraldır: tek yuvada tik sayısı işlemci adımı sayısının altına inemez.
  • EM19 — İşçi taraması aynı görev dizisiyle yapılır; yalnız işçi sayısı değişir.
  • EM20 — Bağlam değiştirme bedeli modelde sıfırdır. Gerçek bir sistemde bu bedel vardır ve modelin dışındadır; ölçülen şey bedelin büyüklüğü değil, örtüşmenin sınırıdır.
  • EM21 — Görevler birbirinden bağımsızdır; ortak durum, kilit ve yarış bu ölçümün dışındadır.
  • EM22 — Süre ölçülmez. Sayılan birim adım, tik ve örtüşen adımdır.
  • EM23 — Ölçüm tek koşumdur; üç yük aynı çekirdekten üretilir.

Ölçüm

"""Is parcaciklari: ayni duzenek, iki yuk, iki ayri kazanc."""

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


YUKLER = (("girdi/çıktı ağırlıklı", 7), ("dengeli", 5), ("işlemci ağırlıklı", 1))

print("iş parçacığı rejimi: sekiz işçi, tek yuva")
print(f"{'yük':<22s} {'adım':>5s} {'tek akış':>9s} {'iş parçacığı':>13s} "
      f"{'örtüşen':>8s} {'kazanç':>7s} {'oran':>7s}")
for ad, pay in YUKLER:
    g = gorevler(gc_payi=pay)
    tek = kosum(g, 1, 1)[0]
    tik, ortusen, _, _ = kosum(g, 8, 1)
    print(f"{ad:<22s} {sum(len(t) for t in g):5d} {tek:9d} {tik:13d} "
          f"{ortusen:8d} {tek - tik:7d} {(tek - tik) / tek:7.4f}")

print()
print("alt sınır ile ulaşılan tik")
print(f"{'yük':<22s} {'işlemci adım':>13s} {'alt sınır':>10s} {'ulaşılan':>9s} "
      f"{'fark':>5s}")
for ad, pay in YUKLER:
    g = gorevler(gc_payi=pay)
    tik, _, islemci_adim, _ = kosum(g, 8, 1)
    print(f"{ad:<22s} {islemci_adim:13d} {islemci_adim:10d} {tik:9d} "
          f"{tik - islemci_adim:5d}")

print()
print("işçi sayısı arttıkça (yuva hep bir)")
print(f"{'işçi':>5s} " + " ".join(f"{ad:>25s}" for ad, _ in YUKLER))
print(f"{'':5s} " + " ".join(f"{'tik / örtüşen':>25s}" for _ in YUKLER))
for isci in (1, 2, 4, 8):
    hucre = []
    for ad, pay in YUKLER:
        tik, ortusen, _, _ = kosum(gorevler(gc_payi=pay), isci, 1)
        hucre.append(f"{f'{tik} / {ortusen}':>25s}")
    print(f"{isci:5d} " + " ".join(hucre))

print()
g_gc, g_ic = gorevler(gc_payi=7), gorevler(gc_payi=1)
k_gc = kosum(g_gc, 1, 1)[0] - kosum(g_gc, 8, 1)[0]
k_ic = kosum(g_ic, 1, 1)[0] - kosum(g_ic, 8, 1)[0]
print(f"aynı düzenek, iki yük: kazanç {k_gc} tike karşı {k_ic} tik, "
      f"oran {k_gc / k_ic:.1f}")
print(f"işlemci ağırlıklı yükte g/ç adımı {kosum(g_ic, 8, 1)[3]}, "
      f"kazanç {k_ic}; girdi/çıktı ağırlıklı yükte g/ç adımı "
      f"{kosum(g_gc, 8, 1)[3]}, kazanç {k_gc}")
iş parçacığı rejimi: sekiz işçi, tek yuva
yük                     adım  tek akış  iş parçacığı  örtüşen  kazanç    oran
girdi/çıktı ağırlıklı     80        80            31       49      49  0.6125
dengeli                   80        80            42       38      38  0.4750
işlemci ağırlıklı         80        80            73        7       7  0.0875

alt sınır ile ulaşılan tik
yük                     işlemci adım  alt sınır  ulaşılan  fark
girdi/çıktı ağırlıklı             26         26        31     5
dengeli                           40         40        42     2
işlemci ağırlıklı                 73         73        73     0

işçi sayısı arttıkça (yuva hep bir)
 işçi     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

aynı düzenek, iki yük: kazanç 49 tike karşı 7 tik, oran 7.0
işlemci ağırlıklı yükte g/ç adımı 7, kazanç 7; girdi/çıktı ağırlıklı yükte g/ç adımı 54, kazanç 49

Aynı Düzenek, Yedi Kat Fark

Üst tablonun iki ucu bu dersin bütün iddiasını taşıyor.

Girdi/çıktı ağırlıklı yükte sekiz işçi ve tek yuva, seksen adımı 31 tikte bitiriyor. Kazanç 49 tik, oran 0,6125. Örtüşen adım da 49: tik sayısının toplam adımdan örtüşen adımın çıkarılmasıyla bulunduğu kimlik burada birebir görünüyor.

İşlemci ağırlıklı yükte aynı düzenek seksen adımı ancak 73 tikte bitiriyor. Kazanç 7 tik, oran 0,0875.

Değişen tek şey adımların türü. Görev sayısı aynı, adım sayısı aynı, işçi sayısı aynı, yuva aynı, çizelgeleyici aynı. Son satırın verdiği oran 7,0 — kazanç arasındaki fark tam yedi kat.

Arada duran dengeli yük iki ucun aynı eğrinin üstünde olduğunu gösteriyor: 80 tik 42‘ye iniyor, kazanç 38, oran 0,4750. Girdi/çıktı payı onda yediden onda beşe düştüğünde kazanç 49’dan 38’e iniyor; onda bire düştüğünde 7’ye. Kazanç, girdi/çıktı payının kesikli bir işlevi gibi davranıyor ve üç ölçüm noktası da aynı yönü veriyor.

Bunun okunuşu şudur: eşzamanlılık bir hızlandırma düzeneği değildir. Aynı rejim bir yükte işin yarıdan fazlasını örtüştürür, öbüründe onda birine bile yaklaşamaz. Bir programa iş parçacığı eklenip kazanç görülmediğinde eksik olan şey iş parçacığı sayısı değil, o programda örtüşebilen adım olabilir.

Kazancın Üst Sınırı Kodda Yazılı

Son satır kazancın nereden geldiğini de söylüyor ve iki sayıyı yan yana koyuyor.

İşlemci ağırlıklı yükte girdi/çıktı adımı 7, kazanç 7. İki sayı eşit. Girdi/çıktı ağırlıklı yükte girdi/çıktı adımı 54, kazanç 49 — kazanç, örtüşebilen adım sayısının biraz altında ama onu aşmıyor.

Kural şudur: kazanç, örtüşebilen adım sayısını geçemez. Tek yuvalı bir rejimde işlemci adımları sırayla atılmak zorunda olduğuna göre, tik sayısından düşülebilecek tek şey girdi/çıktı adımlarıdır. İşlemci ağırlıklı yükte örtüşebilecek yalnız yedi adım var; sekiz değil, seksen hiç değil.

Orta tablo aynı sınırı öbür uçtan gösteriyor. Alt sınır, önceki derste kurulan kuraldı: tek yuvada tik sayısı işlemci adımı sayısının altına inemez. Girdi/çıktı ağırlıklı yükte alt sınır 26, ulaşılan 31; fark 5. İşlemci ağırlıklı yükte alt sınır 73, ulaşılan 73; fark 0.

Son satır önemli: işlemci ağırlıklı yükte rejim alt sınıra tam olarak oturuyor. Daha iyisi mümkün değil, çünkü 73 işlemci adımının her biri kendi tikini istiyor. Bu yükte iyileştirme arayan biri iş parçacığı sayısıyla oynayarak hiçbir şey elde edemez; değiştirmesi gereken şey yuva sayısıdır ve o, iş parçacığının değiştirebileceği bir sayı değildir.

Girdi/çıktı ağırlıklı yükteki 5 tiklik fark de anlamlı: 31 tikin 26’sı bir işlemci adımı taşıyor, kalan 5’i yalnız girdi/çıktı adımı taşıyor. O beş tikte yuva boş duruyor, çünkü o anda sırasında işlemci adımı olan canlı görev yok. Yuvanın boş durması bir kayıp gibi görünse de düzeltilebilir bir şey değil: hangi görevin hangi tikte işlemci adımı isteyeceği adım dizisine yazılıdır, çizelgeleyicinin seçebileceği bir şey değildir.

İşçi Eklemenin Nerede Durduğu

Alt tablo işçi sayısını 1’den 8’e çıkarıyor ve üç yükte üç ayrı davranış veriyor.

İşlemci ağırlıklı yükte ikinci işçi 80 tiki 73’e indiriyor; dördüncü ve sekizinci işçi hiçbir şey eklemiyor. Tik 73’te, örtüşen adım 7’de donuyor. Yedi adım örtüşebiliyordu, yedisi de ikinci işçiyle örtüştü; üçüncüsüne iş kalmadı. Bu yükte iş parçacığı sayısını artırmanın sayılabilir bir karşılığı yok.

Girdi/çıktı ağırlıklı yükte eğri hiç düz değil ama azalan bir eğri: ikinci işçi 36 tik, üçüncü ve dördüncü birlikte 10 tik, beşinciden sekizinciye kadar dördü birlikte 3 tik kazandırıyor. Kazanç işçi sayısıyla doğrusal büyümüyor; ilk işçiler örtüşebilen adımların çoğunu zaten kapıyor.

Dengeli yükte aynı biçim daha erken duruyor: 80’den 52’ye, sonra 44’e, sonra 42’ye. Sekiz işçiye çıkmak dört işçiye göre yalnız iki tik kazandırıyor.

Tablonun ilk satırı da bilgi taşıyor: tek işçiyle üç yükün üçü de 80 tik / 0 örtüşen adım veriyor. Yani sekiz görevi tek işçiyle koşturmak, rejim adı ne olursa olsun tek akıştır. Bir programda iş parçacığı havuzunun genişliği bire indirildiğinde ölçülen şey eşzamanlılık değil, yalnız sıradır. Havuz genişliğini ölçüme yazmayan bir karşılaştırma bu yüzden okunamaz.

Üç sütunun ortak dersi şu: işçi eklemek, örtüşebilen adım tükenene kadar kazandırır; sonra durur. Nerede duracağını belirleyen sayı işçi sayısı değil, yükün bileşimidir. Ve bu tablonun hiçbir yerinde işlemci ağırlıklı sütun 73’ün altına inmiyor — o sınırı aşmanın yolu bu dersin rejiminde yok.

Modelin Dışında Bıraktıkları

Bir ölçüm neyi saydığını söylemedikçe okunamaz, bu yüzden bu modelin saymadığı iki şeyi adıyla yazmak gerekir.

Bağlam değiştirme bedeli sıfır sayılıyor. Gerçek bir sistemde bir iş parçacığından öbürüne geçmek boşuna değildir; kaydedilecek durum vardır. Model bu bedeli hiç saymıyor, yani yukarıdaki kazanç sayıları iyimser taraftan yazılıdır. Bu, sonuçları bozmuyor: bedel eklendiğinde kazanç yalnız küçülür, işaret değiştirmez. İşlemci ağırlıklı yükteki 7 tik zaten küçüktü; bedel eklenirse daha da küçülür ve o yükte iş parçacığının anlamsızlığı güçlenir.

Ortak durum yok sayılıyor. Sekiz görev birbirinden bağımsız; hiçbiri ötekinin yazdığını okumuyor. Gerçek bir programda paylaşılan bir sözlüğe iki iş parçacığından yazmak, araya kilit koymayı gerektirir ve kilit beklemesi yeni bir bekleme türü ekler. Bu, modelin ölçtüğü şeyin dışında kalır ama yönü bellidir: kilit beklemesi örtüşen adımı azaltır, çünkü bekleyen görev o tikte ilerlemez.

İkisinin ortak sonucu şu: ölçülen 49 ve 7, iş parçacığından beklenebilecek kazancın üst sınırıdır. Gerçek bir program bu sayılara ancak yaklaşabilir. Bir kazanç iddiası bu sınırın üstündeyse, ölçümde sayılmayan bir şey vardır.

Buradan ayrı bir uyarı da çıkıyor: iş parçacığı, bekleyen adımlar için bir düzenektir. Bir program bekleme yerine hesap yapıyorsa, kilit yüzünden değil, örtüşecek bir şey olmadığı için kazanamaz.

Özet

  • İş parçacığı açmak modelde işçi sayısını büyütür, yuva sayısını değil; sekiz iş parçacığı da aynı yorumlayıcının tek kilidini paylaşır.
  • Sekiz işçi ve tek yuva, girdi/çıktı ağırlıklı yükte 80 tiki 31‘e indirir — kazanç 49 tik, oran 0,6125. Aynı düzenek işlemci ağırlıklı yükte 80’i ancak 73’e indirir — kazanç 7 tik. Aradaki fark tam yedi kat.
  • Kazanç, örtüşebilen adım sayısını geçemez: işlemci ağırlıklı yükte girdi/çıktı adımı 7’dir ve kazanç da 7’dir.
  • İşlemci ağırlıklı yükte rejim alt sınıra tam oturur (73’e karşı 73); girdi/çıktı ağırlıklı yükte 5 tiklik boşluk kalır ve o beş tikte yuva boş durur.
  • İşçi eklemek örtüşebilen adım tükenene kadar kazandırır: işlemci ağırlıklı yükte kazanç ikinci işçide donar, girdi/çıktı ağırlıklı yükte sekizinci işçiye kadar azalarak sürer.

Sonraki Adım

Bu dersin son sayısı bir sınırı gösteriyor: işlemci ağırlıklı yükte kaç işçi eklenirse eklensin tik 73’ün altına inmiyor, çünkü değişmeyen ayar yuva. Sonraki ders o ayarı değiştirir. Ayrı bir süreç başlatmak ayrı bir yorumlayıcı demektir ve ayrı yorumlayıcı ayrı bir yuva demektir. Sorusu şu: dört yuva işlemci ağırlıklı yükte seksen adımı kaça indirir, ve yuva sayısı görev sayısına eşitlendiğinde yükün bileşimi hâlâ bir şey söyler mi?

İ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