Ders 01 / 11
Küme Hesaplama Temelleri
Bir işin birden çok makineye bölünmesinin sürücü, yürütücü ve görev soyutlamalarıyla kurulması ve bölmenin iki ayrı sayıyla ölçülmesi: hattan çıkan 2200 satır tek işçide süre 2250 ve toplam iş 2200 verirken dört işçiye abone anahtarıyla bölündüğünde süre 611'e iniyor, bölge anahtarıyla bölündüğünde dört işçinin ikisi boş kalıyor, çarpıklık 1,02 yerine 3,32 oluyor ve süre yalnızca 1876'ya inebiliyor; üç kurulumun toplam işi birebir aynı 2200 olduğu için hangisinin ölçüldüğü yazılmayan bir hızlanma iddiası eksik kalıyor.
İçindekiler
On altı derste hat tek bir makinede koşuyormuş gibi ele alındı. Görevler sıraya girdi, düştü, yeniden denendi ve kırk sekiz düğüm tek bir listeye dizildi; hattın aşamaları arasında veri bir değişkenden öbürüne geçti ve bu geçişin bir bedeli yokmuş gibi davranıldı. Varsayım tek makine için doğrudur: aynı bellekteki bir listeyi bir sonraki işleve vermek bedavaya yakındır.
Veri tek bir makineye sığmadığında varsayım düşer. İşin bölünmesi gerekir, bölünen parçalar farklı makinelerde koşar ve aralarındaki her geçiş ağdan geçer. Bu ders o bölünmeyi kurar ve tek bir şeyi gösterir: bölünmüş bir işin tek bir sayısı yoktur. En az iki sayı vardır ve ikisi aynı yöne gitmek zorunda değildir.
- DH1. Kaynak, hat ve küme kurgudur. Gerçek bir dağıtık işleme çatısı, kaynak yöneticisi, dağıtık dosya sistemi ya da bulut servisi çağrılmaz. Tohum 20260218, ölçü koşumdan bağımsızdır.
- DH2. Kursun kuralı: dağıtık bir işin sayısı tek bir sayı değildir. Süre (en yüklü işçinin işi) ile toplam iş ayrı ölçülür ve hangisinin ölçüldüğü yazılmayan hızlanma iddiası eksiktir.
- DH3. Taban çizgisi tek işçidir: karıştırma yok, çarpıklık 1,00, süre 2250, toplam iş 2200.
- DH4. Süre bu modelin kendi birimidir, ham milisaniye değildir. Bir satırı yerel olarak işlemek bir birim sayılır; başka bir makinede ölçülen saat süresine karşılık gelmez.
- DH5. Görev, bir işçiye verilen paydır: aynı işlemin satırların bir altkümesi üzerinde koşması. Veri Hatları ve Orkestrasyon kursundaki görev çizgedeki bir düğümdü, yani bir aşamanın belirli bir dönem için koşmasıydı; buradaki görev o düğümün içinde durur.
- DH6. Her işçiye iş vermenin sabit bir bedeli vardır:
GOREV_SABIT = 50. Bu bir seçimdir ve ona duyarlı her sonuç değeriyle birlikte yazılır. - DH7. Bir satırı ağdan taşımanın bedeli yerel işlemenin üç katıdır (
AG_BEDELI = 3). Bu da bir seçimdir; bu derste karıştırma olmadığı için hiçbir sonuca girmez. - DH8. Ölçülen birimler satır, işçi, görev, süre, toplam iş ve çarpıklıktır. Süre ile toplam iş tam sayıdır ve üzerlerine oran basılmaz.
Sürücü, Yürütücü ve Görev
Dağıtık bir koşumda üç rol vardır ve üçü de tek makineli hatta yoktu. Sürücü (driver) işin planını tutan tek noktadır: hangi işlemin yapılacağını, verinin hangi anahtara göre bölüneceğini ve sonuçların nerede toplanacağını o bilir. Sürücü veriyi kendisi işlemez; iş dağıtır ve sonucu toplar. Yürütücü (executor) bir makine üzerinde koşan ve kendisine verilen payı işleyen süreçtir. Bu modelde her yürütücü tek bir işçi olarak sayılır, yani işçi sayısı yürütücü sayısıdır.
Görev üçüncü ve en kolay karıştırılan kavramdır. Veri Hatları ve Orkestrasyon kursunda görev
çizgedeki bir düğümdü: ayikla@2026-07 bir görevdi ve kırk sekiz tanesi vardı. Burada görev
çizgeyle ilgili değildir; bir işçiye verilen paydır. Aynı ayikla@2026-07 düğümü dört işçiye
bölündüğünde dört görev doğar ve dördü de aynı işlemi farklı satır altkümeleri üzerinde koşar.
Orkestrasyon görevleri sıraya dizer, dağıtık koşum onları yan yana koyar.
Bu üç rol aşağıdaki kurgu küme üzerinde kurulur. İlk blok Veri Mühendisliğine Giriş kursunda tanımlanan kaynağı ve hattın ilk üç aşamasını aynen yeniden kurar, üzerine bölüşüm ve maliyet işlevlerini ekler.
# KURGUDUR. Sayac okumalari, hat ve kume ders icinde tanimlanir; gercek bir # dagitik isleme catisi, kaynak yoneticisi ya da dosya sistemi cagrilmaz. TOHUM, M32 = 20260218, 0xFFFFFFFF def uretec(t): x = ((t ^ (t >> 16)) * 2246822507) & M32 x = ((x ^ (x >> 13)) * 3266489909) & M32 s = [(x ^ (x >> 16)) & M32] def sonraki(): s[0] = (s[0] * 1664525 + 1013904223) & M32 return s[0] / 4294967296 return sonraki BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"] TIP = ["mesken", "isyeri"] DONEM = [f"2026-{a:02d}" for a in range(1, 13)] ABONE = {} for i in range(200): r = uretec(TOHUM + 37 * i) ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)], "baslangic": 10000 + int(r() * 60000)} def kaynak_uret(): kayit = [] for i, (ab, a) in enumerate(ABONE.items()): e = a["baslangic"] for d in DONEM: r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d)) e += 4 + int(r() * 46) kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"], "endeks": e, "birim": "m3"}) return kayit def a1_ayikla(kayit): ZOR = ("abone", "donem", "bolge", "endeks", "birim") tut = [k for k in kayit if all(a in k for a in ZOR)] return tut, len(kayit) - len(tut) def a2_tekille(kayit): gor, tut = set(), [] for k in kayit: ad = (k["abone"], k["donem"]) if ad in gor: continue gor.add(ad) tut.append(k) return tut, len(kayit) - len(tut) def a3_tuketim(kayit): tablo = {(k["abone"], k["donem"]): k for k in kayit} cikti, dusen = [], 0 for k in kayit: i = DONEM.index(k["donem"]) if i == 0: continue onceki = tablo.get((k["abone"], DONEM[i - 1])) if onceki is None: dusen += 1 continue try: f = int(k["endeks"]) - int(onceki["endeks"]) except (TypeError, ValueError): dusen += 1 continue cikti.append(dict(k, m3=f)) return cikti, dusen # ---- KURGU kume: isci sayisi ve iki secim ISCI = 4 AG_BEDELI = 3 # bir satiri agdan tasimanin bedeli , yerel islemin kaç katı GOREV_SABIT = 50 # her isciye is vermenin sabit bedeli def satirlar(): v, _ = a1_ayikla(kaynak_uret()) v, _ = a2_tekille(v) v, _ = a3_tuketim(v) return v def izno(m): h = 2166136261 for c in str(m): h = ((h ^ ord(c)) * 16777619) & 0xFFFFFFFF return h def dagit(kayitlar, anahtar, isci=ISCI): """Satirlari anahtara gore isciye atar. Ayni anahtar hep ayni isciye gider.""" kova = {i: [] for i in range(isci)} for k in kayitlar: kova[izno(k[anahtar]) % isci].append(k) return kova def yuk(kova): n = [len(v) for v in kova.values()] return {"toplam": sum(n), "en_yuklu": max(n), "en_az": min(n), "carpiklik": round(max(n) / (sum(n) / len(n)), 4)} def maliyet(kova, tasinan=0, isci=ISCI): """Sure = en yuklu iscinin isi (paralel). Toplam is ayrica sayilir.""" n = [len(v) for v in kova.values()] return {"sure": max(n) + tasinan * AG_BEDELI // isci + GOREV_SABIT, "toplam_is": sum(n) + tasinan * AG_BEDELI, "tasinan": tasinan}
Bölüşüm Anahtarı İşçiyi Seçer
Sürücünün verdiği ilk karar hangi anahtara göre bölüneceğidir. dagit bir satırın anahtar
değerinden bir sayı üretir ve işçi sayısına göre kalanını alır; aynı anahtar değeri her zaman aynı
işçiye gider. Bu özellik bir gereklilikten doğar: aynı abonenin iki dönemi farklı işçilere düşerse
tüketim farkı hiç hesaplanamaz. Karar bedava görünür, çünkü hangi anahtar seçilirse seçilsin toplam
satır aynı kalır. İlk ölçüm bunun neden yanıltıcı olduğunu gösterir.
S = satirlar() print("hattan cikan satir:", len(S), " isci:", ISCI) print() print(f"{'anahtar':<9}{'isci yuku':<26}{'en yuklu':>9}{'en az':>7}{'carpiklik':>11}") for a in ("abone", "donem", "bolge"): kova = dagit(S, a, ISCI) y = yuk(kova) print(f"{a:<9}{str([len(v) for v in kova.values()]):<26}" f"{y['en_yuklu']:>9}{y['en_az']:>7}{y['carpiklik']:>11.4f}")
hattan cikan satir: 2200 isci: 4 anahtar isci yuku en yuklu en az carpiklik abone [539, 550, 561, 550] 561 539 1.0200 donem [600, 600, 400, 600] 600 400 1.0909 bolge [374, 0, 0, 1826] 1826 0 3.3200
Üç satırın toplamı aynıdır: her kurulumda 2200 satır dağıtılmıştır ve hiçbir satır kaybolmamıştır.
Değişen şey satırların nasıl yığıldığıdır. abone anahtarında iki yüz farklı değer dört kovaya
düştüğü için yükler 539 ile 561 arasında sıkışır; çarpıklık 1,02, yani en yüklü işçi ortalamanın
yüzde iki üzerindedir. donem anahtarında on iki değer dörde bölünür ve üç kova üçer dönem, biri
iki dönem alır: 600, 600, 400, 600.
bolge satırı bölüşümün sessiz kusurudur. Beş bölge dört işçiye dağıldığında iki işçi hiç satır
almaz ve bir işçi 1826 satırla kalır. Çarpıklık 3,32‘dir. Küme dört makine tutuyor, dördünün
de faturası işliyor, ama ikisi boş duruyor. Hiçbir hata verilmez, hiçbir satır düşmez ve sonuç
doğrudur; yanlış olan tek şey bölüşümdür ve bu yalnızca sayılırsa görünür. Çarpıklığın çözünürlüğü
işçi sayısına bağlıdır: dört işçide en küçük adım 0,0018’dir.
Süre ile Toplam İş
Yükler bir sayıya çevrildiğinde asıl ayrım ortaya çıkar. İşçiler yan yana koştuğu için işin bitmesi
en yavaş işçiyi bekler; bu süredir ve maliyet onu en yüklü işçinin payı artı 50 birimlik sabit
görev bedeli olarak hesaplar. Buna karşılık kümenin harcadığı toplam iş bütün işçilerin payının
toplamıdır ve kim beklerse beklesin ödenir. Aşağıdaki blok tek işçilik tabanı üç dörtlü kurulumla
karşılaştırır.
print(f"{'kurulum':<20}{'gorev':>6}{'en yuklu pay':>14}{'sure':>7}{'toplam is':>11}") for ad, anahtar, n in (("tek isci", "abone", 1), ("dort isci / abone", "abone", 4), ("dort isci / donem", "donem", 4), ("dort isci / bolge", "bolge", 4)): kova = dagit(S, anahtar, n) m = maliyet(kova, 0, n) print(f"{ad:<20}{n:>6}{max(len(v) for v in kova.values()):>14}" f"{m['sure']:>7}{m['toplam_is']:>11}")
kurulum gorev en yuklu pay sure toplam is tek isci 1 2200 2250 2200 dort isci / abone 4 561 611 2200 dort isci / donem 4 600 650 2200 dort isci / bolge 4 1826 1876 2200
Son sütun dört satırda da 2200’dür. Kümenin yaptığı iş hiç değişmemiştir, çünkü karıştırma yoktur ve her satır tam bir kez işlenir. Buna rağmen süre 2250 ile 611 arasında değişir. Bir kurulumun “2200 birimlik iş yaptığı” doğrudur ve dört kurulumu birbirinden hiç ayırmaz. Kursun kuralı bu tablodan okunur: hangisinin ölçüldüğü yazılmayan bir hızlanma iddiası eksiktir.
Taban çizgisi tek işçidir: süre 2250, toplam iş 2200. Aradaki 50 birimlik fark sabit görev
bedelidir ve tek işçide bile ödenir. Dört işçi abone anahtarıyla süreyi 611’e indirir; bu
kursun boyunca görülecek en temiz kazançtır ve sebebi de o kadar dardır: veri hiç hareket etmiyor,
her işçi kendi payını okuyup kendi payını yazıyor. donem anahtarında süre 650’ye çıkar, çünkü
en yüklü işçi 561 yerine 600 satır tutar.
bolge satırı bir kez daha ayrı durur. Dört işçi çalıştırılmasına rağmen süre yalnız 1876’dır;
tek işçiye göre kazanç dörtte bir değil, altıda birden azdır. İkisi boş oturan işçiler süreye hiç
dokunmaz, çünkü süre en yüklü işçiyi ölçer. Aynı toplam iş, aynı doğru sonuç, üç kat farklı süre.
Bu sayıların birimi üzerine bir uyarı gerekir. Süre bu modelin kendi birimidir. Bir satırı yerel
işlemek bir birim, bir satırı ağdan taşımak üç birim, bir işçiye iş vermek elli birimdir; ikinci ve
üçüncü değerler AG_BEDELI ve GOREV_SABIT olarak yazılmış seçimlerdir. 2250 sayısı bir
saniyeyi, bir milisaniyeyi ya da herhangi bir saat okumasını göstermez. Modelin verdiği şey
kurulumlar arasındaki karşılaştırmadır; tek bir kurulumun süresi kendi başına bir anlam taşımaz.
Sonuç Değişmez, Bedel Değişir
Bölüşüm yanlış olduğunda ne olur sorusunun yanıtı, bu kursta öğrenmesi en zor olanıdır: hiçbir şey. Sonuç yanlış çıkmaz, satır kaybolmaz, hata verilmez. Sürücü işçilerden gelen ara özetleri birleştirir ve elindeki tablo dört kurulumda da birebir aynıdır. Son blok bunu her kurulum için bölge toplamlarını hesaplayarak gösterir.
def bolge_toplami(kova): """Her isci kendi payini ozetler , surucu ara ozetleri birlestirir.""" ara = [] for pay in kova.values(): t = {} for k in pay: t[k["bolge"]] = t.get(k["bolge"], 0) + k["m3"] ara.append(t) son = {} for t in ara: for b, v in t.items(): son[b] = son.get(b, 0) + v return son taban = bolge_toplami(dagit(S, "abone", 1)) print("taban sonuc:", taban) print() print(f"{'kurulum':<20}{'ara satir':>10}{'sure':>7}{'toplam is':>11}{'sonuc':>17}") for ad, a, n in (("tek isci", "abone", 1), ("dort isci / abone", "abone", 4), ("dort isci / donem", "donem", 4), ("dort isci / bolge", "bolge", 4)): kova = dagit(S, a, n) m = maliyet(kova, 0, n) ara = sum(len(set(k["bolge"] for k in pay)) for pay in kova.values()) esit = "taban ile ayni" if bolge_toplami(kova) == taban else "farkli" print(f"{ad:<20}{ara:>10}{m['sure']:>7}{m['toplam_is']:>11}{esit:>17}")
taban sonuc: {'merkez': 14536, 'kuzey': 13338, 'dogu': 9695, 'bati': 9164, 'guney': 11721}
kurulum ara satir sure toplam is sonuc
tek isci 5 2250 2200 taban ile ayni
dort isci / abone 20 611 2200 taban ile ayni
dort isci / donem 20 650 2200 taban ile ayni
dort isci / bolge 5 1876 2200 taban ile ayni
Son sütun dört kez aynı şeyi söyler. Beş bölge toplamı hangi bölüşümde hesaplanırsa hesaplansın değişmez, çünkü toplama işlemi satırların hangi sırayla ve hangi makinede toplandığına duyarsızdır. Bunun sonucu şudur: hattın çıktısına bakan bir denetim, iki işçinin boş oturduğu kurulumla en iyi kurulumu birbirinden ayıramaz. Veri Mühendisliğine Giriş kursunda kurulan denetimlerin hepsi yeşil kalır. Yanlış bölüşüm bir doğruluk kusuru değildir; yalnızca sayılırsa görünür.
Üçüncü sütundan önceki sayı sürücünün payını verir. abone ve donem bölüşümlerinde her işçinin
payında beş bölge de bulunur, bu yüzden sürücüye 20 ara satır gelir; bolge bölüşümünde her bölge
tek bir işçide durduğu için yalnız 5 ara satır gelir. Sürücünün birleştirme işi bu modelde toplam
işe eklenmez, ama gerçek bir kümede o da bir bedeldir ve en dengesiz bölüşüm burada en ucuz olanıdır.
Bir bölüşümü tek bir sayıya bakarak seçmenin neden yetmediğinin ikinci örneği budur.
Özet
- Dağıtık koşumun üç rolü vardır: sürücü planı tutar ve dağıtır, yürütücü kendisine verilen payı işler, görev o payın kendisidir. Bu modelde bir yürütücü bir işçi olarak sayılır.
- Buradaki görev orkestrasyondaki görevle aynı şey değildir: orada çizgedeki bir düğümdü, burada o düğümün içinde bir işçiye düşen paydır. Bir düğüm dört işçide dört görev doğurur.
- Bölüşüm anahtarı yükleri belirler:
aboneçarpıklığı 1,02,donem1,0909,bolge3,32 verir vebolgeanahtarında dört işçinin ikisi hiç satır almaz. - Süre ile toplam iş ayrı sayılardır. Dört kurulumda toplam iş 2200’de sabit kalırken süre 2250, 611, 650 ve 1876 olur; toplam iş kurulumları birbirinden ayırmaz.
- Tek işçilik taban süre 2250 ve toplam iş 2200’dür; 50 birimlik fark her işçiye iş vermenin sabit bedelidir.
- Süre bu modelin kendi birimidir.
AG_BEDELI = 3veGOREV_SABIT = 50seçimlerdir ve sayılar ancak birbirleriyle karşılaştırıldığında anlam taşır.
Sonraki Adım
Bu derste satırlar bir listede hazır duruyordu ve dagit onları işçilere dağıttı. Gerçekte bir
işçinin işlediği satırlar bir yerden okunur ve o yer başka bir makine olabilir. Bölüşüm ne kadar
dengeli olursa olsun, her işçi payını ağ üzerinden çekiyorsa dağıtmanın kazancı okuma bedelinin
altında kalır. Sonraki ders veriyi bloklara ayırıp kümeye yerleştirir ve tek bir soruyu ölçer:
bir bloğu işleyen işçi onu zaten tutuyorsa ne kazanılır, ve bloğun kaç kopyasının saklandığı bu
kazancı nasıl değiştirir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.