Ders 09 / 10
Yerel Uzantılar
Sıcak yolun alt seviyeye taşınması modelde üç etkiyle ölçülür; işlemci ağırlıklı yükte on iki dörtlü grup 80 adımı 44'e, 73 tiki 25'e indirir, sınır maliyeti kazancı 48'den 36'ya çeker ve aynı düzenek girdi/çıktı ağırlıklı yükte hiçbir şey kazandırmaz.
İçindekiler
Önceki iki ders sıcak yolu iki ayrı sayıyla çevreledi: işlemci ağırlıklı yükte
islemci_adimi_mi 322 kez çağrılıyor, ve 80 adımı taşıyan yapı biçimine göre 1 ile 172
nesne arasında yer tutuyor. İkisi de aynı yeri gösteriyor — işin ağırlığı işlemci
adımlarında.
Bu noktada sık başvurulan bir yol var: sıcak yolu dilin dışına, daha alt bir seviyeye taşımak. Kazancı çoğunlukla süreyle anlatılır ve o anlatım bu kursta kabul edilmez. Bu ders aynı soruyu tek bir biçimde sorar: sıcak yolun adım sayısı düştüğünde toplam tik ne oluyor?
Yerel Uzantı Nedir
Yerel uzantı (native extension), kodu yorumlayıcının adım adım yürütmesi yerine önceden makine yönergelerine çevrilmiş biçimde tutan ve dile bir modül gibi görünen bileşendir. Programın geri kalanı onu sıradan bir işlev çağrısıyla kullanır; çağrı bir sınırdan geçer, argümanlar alt seviyenin beklediği biçime çevrilir, iş orada yapılır ve sonuç geri çevrilir.
Bu ders bir uzantının nasıl yazılacağını değil, ne kazandırdığını ölçer. Araçtan, derleyiciden ve paketten söz edilmez; ölçülen şey yaklaşımın kendisidir, onu gerçekleştiren belirli bir düzenek değil. Yaklaşımın kendisini tanımlayan iki özellik yeter: iş dilin yürütme adımlarının dışında yapılır ve her giriş çıkış bir sınırdan geçer. Bu iki özellik hangi araçla sağlanırsa sağlansın ölçüm aynı kalır; bir sonraki tablo bu iki özelliğin doğrudan karşılığıdır.
Gerçek bir uzantı da derlenmiyor, ve bunun gerekçesi kursun ölçüsüyle aynı. Derlenmiş bir uzantının kazancı ortama, derleme seçeneklerine ve işin türüne bağlıdır; iki makinede iki ayrı sayı verir. Modelde ölçülen adım ise her koşumda aynı çıkar. Yeniden üretilemeyen bir sayı bir kazanç iddiasını taşıyamaz.
Modelde Üç Etki
Yerel uzantı modele üç ayrı etkiyle girer ve üçünü ayrı ayrı ölçmek dersin asıl işidir.
Birincisi adım sayısıdır. Sıcak yolda ardışık duran birkaç işlemci adımı, uzantıya tek bir çağrıyla devredilir; yorumlayıcının görmesi gereken adım sayısı düşer. Dört adımın tek çağrıya inmesi, o dört adımın yerine bir adım demektir.
İkincisi sınır maliyetidir. Çağrı bedavaya geçmez: argümanların çevrilmesi, verinin sınırın öbür tarafına aktarılması ve dönüş değerinin kurulması iş yapar. Modelde bu, çağrı başına sabit sayıda ek adımdır.
Üçüncüsü kilittir. Alt seviyede çalışan bir kod, işini yaparken genel yorumlayıcı kilidini bırakabilir. Bunun çizelgeleyicideki karşılığı doğrudandır: kilidi bırakan adım işlemci yuvası istemez, dolayısıyla başka görevlerin adımlarıyla örtüşebilir. Bu yeni bir davranış değil; ortak tanımın çizelgeleyicisi yuva istemeyen her adıma zaten böyle davranır.
Üç etki birbirinden bağımsız açılıp kapanabilir, ve tablo bunu yapıyor: kimi satırda yalnız adım düşüyor, kimisinde sınır maliyeti ekleniyor, kimisinde kilit bırakılıyor.
Modelin dışında kalanları da söylemek gerekir, çünkü bir model neyi kapsamadığını söylemeden okunamaz. Sınır maliyeti burada çağrı başına sabittir; gerçekte aktarılan verinin büyüklüğüne bağlı olabilir ve büyük veri kopyalanan bir çağrıda sabit sayı yanıltır. Belleğin sınırın hangi tarafında sahiplenildiği, alt seviyede oluşan bir hatanın dile nasıl taşındığı ve uzantının taşınabilirliği de modelde yoktur. Bunlar kazanç sorusunun değil, maliyet sorusunun parçalarıdır; tablo yalnız kazancı ölçüyor ve bu sınırı açık tutuyor.
Ölçümün varsayımları:
- BS13 — Yerel uzantı modelde yalnız bu üç etkiyle temsil edilir: adım birleştirme, sınır maliyeti, kilidin bırakılması. Başka hiçbir etki modellenmez.
- BS14 — Yalnız ardışık ve tam gruplar birleşir. Grubu dolduramayan adımlar yorumlanmaya devam eder; bir uzantı da ancak sıcak yolun tamamını devralabildiği yerde devralır.
- BS15 — Sınır maliyeti çağrı başına sabit ve tam sayıda adımdır. Argüman dönüşümü, veri aktarımı ve dönüş değerinin kurulması bu tek sayıda toplanır.
- BS16 — Kilidi bırakan adım çizelgeleyici için işlemci adımı değildir: yuva istemez ve
örtüşebilir.
gorevlervekosumişlevlerinin davranışı değiştirilmez; yalnız yeni bir adım türü eklenir. - BS17 — Gerçek bir uzantı derlenmez, süre ölçülmez. Kazanç yalnız adım ve tik olarak yazılır.
- BS18 — Karşılaştırma tabanı, aynı görev kümesinin yoğunlaştırılmamış koşumudur. İki yük ayrı ayrı ölçülür ve rejim dışında hiçbir şey değişmez; her iki koşum da sekiz işçili, tek yuvalı rejimdedir.
Ölçüm
"""Yerel uzanti modeli: sicak yol kisaldiginda toplam tik ne oluyor.""" TOHUM = 20260817 ISLEMCI, GC, YEREL = "islemci", "g_c", "yerel" 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): 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): 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 yogunlastir(gorev, kat, sinir=0, tur=ISLEMCI): """Ardisik kat adet islemci adimini tek adima indirir; sinir kadar adim ekler.""" yeni, biriken = [], 0 for adim in gorev: if adim == ISLEMCI: biriken += 1 if biriken == kat: yeni.append(tur) yeni.extend([ISLEMCI] * sinir) biriken = 0 else: yeni.extend([ISLEMCI] * biriken) biriken = 0 yeni.append(adim) yeni.extend([ISLEMCI] * biriken) return yeni REJIM = ( ("taban: her adım yorumlanıyor", 1, 0, ISLEMCI), ("dört adım tek çağrıda", 4, 0, ISLEMCI), ("dört adım, sınır 1 adım", 4, 1, ISLEMCI), ("dört adım, kilit bırakılıyor", 4, 0, YEREL), ("dört adım, kilit + sınır 1", 4, 1, YEREL), ("iki adım, kilit + sınır 1", 2, 1, YEREL), ("on adım, kilit bırakılıyor", 10, 0, YEREL), ) for yuk, pay in (("işlemci ağırlıklı", 1), ("girdi/çıktı ağırlıklı", 7)): G = gorevler(gc_payi=pay) taban = kosum(G, 8, 1)[0] print(f"{yuk:<30s} {'adım':>5s} {'tik':>4s} {'örtüşen':>8s} {'kazanç':>7s}") for ad, kat, sinir, tur in REJIM: Y = [yogunlastir(g, kat, sinir, tur) for g in G] tik, ortusen, _, _ = kosum(Y, 8, 1) print(f" {ad:<28s} {sum(len(g) for g in Y):5d} {tik:4d} {ortusen:8d}" f" {taban - tik:7d}") print() G = gorevler(gc_payi=1) D = [yogunlastir(g, 4, 0, YEREL) for g in G] print(f"işlemci ağırlıklı yükte yoğunlaştırma öncesi adım {sum(len(g) for g in G)}, " f"sonrası {sum(len(g) for g in D)}") print(f"tek çağrıya inen dörtlü grup {sum(g.count(YEREL) for g in D)}, " f"yorumlanmaya devam eden işlemci adımı {sum(g.count(ISLEMCI) for g in D)}") H = gorevler(gc_payi=7) E = [yogunlastir(g, 4, 0, YEREL) for g in H] print(f"girdi/çıktı ağırlıklı yükte dörtlü grup {sum(g.count(YEREL) for g in E)}, " f"adım {sum(len(g) for g in H)} -> {sum(len(g) for g in E)}")
işlemci ağırlıklı adım tik örtüşen kazanç taban: her adım yorumlanıyor 80 73 7 0 dört adım tek çağrıda 44 37 7 36 dört adım, sınır 1 adım 56 49 7 24 dört adım, kilit bırakılıyor 44 25 19 48 dört adım, kilit + sınır 1 56 37 19 36 iki adım, kilit + sınır 1 80 44 36 29 on adım, kilit bırakılıyor 53 44 9 29 girdi/çıktı ağırlıklı adım tik örtüşen kazanç taban: her adım yorumlanıyor 80 31 49 0 dört adım tek çağrıda 80 31 49 0 dört adım, sınır 1 adım 80 31 49 0 dört adım, kilit bırakılıyor 80 31 49 0 dört adım, kilit + sınır 1 80 31 49 0 iki adım, kilit + sınır 1 80 24 56 7 on adım, kilit bırakılıyor 80 31 49 0 işlemci ağırlıklı yükte yoğunlaştırma öncesi adım 80, sonrası 44 tek çağrıya inen dörtlü grup 12, yorumlanmaya devam eden işlemci adımı 25 girdi/çıktı ağırlıklı yükte dörtlü grup 0, adım 80 -> 80
Adımın Düşmesi
İşlemci ağırlıklı yükte taban 80 adım, 73 tik. Dörtlü grupları tek çağrıya indirmek adımı 44’e, tiki 37’ye çekiyor; kazanç 36 tik. Alt bloktaki döküm bunun nereden geldiğini söylüyor: 12 dörtlü grup birleşmiş, 48 adım 12 adıma inmiş, geriye 25 işlemci adımı yorumlanmak üzere kalmış.
Dikkat çeken şey örtüşen adım sütununun 7’de kalması. Adım sayısı düştü, tik düştü, ama örtüşme hiç artmadı. Bunun nedeni tek yuvadır: birleşmiş adım da bir işlemci adımıdır ve yine yuva ister. Daha az iş yapıldı, ama iş yine sırayla yapıldı.
Kilit bırakıldığında tablo değişiyor: aynı 44 adım 25 tikte bitiyor ve örtüşen adım 7’den 19’a çıkıyor. Kazanç 36’dan 48’e. Aradaki 12 tik, tümüyle 12 birleşik adımın yuva istemeyi bırakmasından geliyor. Aynı adım azaltması, kilit bırakılmadan üçte iki, bırakıldığında tam kazanç veriyor.
Sınırın Ödettiği
Sınır maliyeti tabloda iki satır olarak duruyor ve okuma kolay.
Kilitsiz durumda çağrı başına bir adımlık sınır, adımı 44’ten 56’ya çıkarıyor — 12 çağrı, 12 ek adım. Tik 37’den 49’a, kazanç 36’dan 24’e iniyor. Sınır, kazancın üçte birini geri aldı.
Kilitli durumda aynı sınır kazancı 48’den 36’ya indiriyor. Buradaki sayı ilginç: 36, kilidin hiç bırakılmadığı ama sınırın da hiç ödenmediği satırın kazancıyla birebir aynı. Yani sınır maliyeti, kilit bırakmanın getirdiği kazancı tam olarak yedi. İki farklı düzenek, aynı toplam. Bir ölçüm bu iki satırdan yalnız kazanç sayısını gösterse, aralarında hiçbir fark görünmezdi.
Bu, uzantı kararının en kırılgan yeridir: kazanç grup büyüklüğüyle artar, sınır maliyeti çağrı sayısıyla artar. Küçük gruplar çok çağrı demektir ve çok çağrı çok sınır demektir.
Adım Düşmeden Gelen Kazanç
Altıncı satır bunu uçta gösteriyor. İki adımı tek çağrıya indirip çağrı başına bir adım sınır ödeyince toplam adım 80’de kalıyor — iki adım gitti, bir çağrı ve bir sınır adımı geldi; hesap başa döndü. Buna karşın tik 73’ten 44’e iniyor ve örtüşen adım 7’den 36’ya çıkıyor.
Yapılan iş hiç azalmadı; kazanç 29 tik. Tümü kilidin bırakılmasından geliyor. Bu satır, kursun ölçü ekseninin bu derse düşen payıdır: bir eniyilemenin kazancı yaptığı işi azaltmasından gelmek zorunda değildir; o işin örtüşmesine izin vermesinden de gelebilir.
Grubu Büyütmenin Sınırı
Son satır sezginin ters yöne çalıştığı yerdir. Grup dört yerine on yapıldığında — daha çok adımı tek çağrıya devretmek, daha büyük kazanç beklenir — adım 44 yerine 53, tik 25 yerine 44 çıkıyor.
Neden ortak tanımın kurgusunda. On adımlık görevlerde art arda tam on işlemci adımının gelmesi ender; girdi/çıktı adımları araya girip grubu bölüyor. Grubu dolduramayan adımlar birleşmiyor, tek tek yorumlanıyor. Grup büyüklüğü sıcak yolun gerçek uzunluğunu aşarsa kazanç büyümez, küçülür.
Bu satırı bir üstündekiyle yan yana koymak ikinci bir şey öğretiyor. Onlu grup 53 adımda 44 tik veriyor; dörtlü grup, sınır maliyetiyle birlikte, 56 adımda 37 tik. Yani daha az adımlı rejim daha çok tik harcıyor. Toplam adım sayısı tek başına tiki belirlemiyor; belirleyen şey o adımların hangi türden olduğu. Onlu grupta yalnız birkaç adım kilidi bırakabildiği için örtüşen adım 9’da kalıyor, dörtlü grupta 19’a çıkıyor. Adım saymak yetmez; hangi adımın örtüşebildiğini de saymak gerekir.
Sıcak Yol Orada Değilse
İkinci tablo dersin en sert sonucudur. Girdi/çıktı ağırlıklı yükte yedi satırın beşi tabanla birebir aynı: 80 adım, 31 tik, 49 örtüşen adım, kazanç 0.
Alt blok nedenini tek sayıyla veriyor: bu yükte ardışık dört işlemci adımından oluşan grup sayısı 0. Birleştirilecek bir şey yok. Uzantı yazıldı, sınır kuruldu, kilit bırakıldı — ve tablo hiç kımıldamadı.
Tek kazançlı satır ikili grup: 31’den 24 tike, kazanç 7. Bu yükte ardışık iki işlemci adımı bulunabiliyor ve kazanç yine adımdan değil örtüşmeden geliyor; adım yine 80’de kalıyor.
Sonuç şudur: sıcak yolu alt seviyeye taşımanın kazancı, sıcak yolun gerçekten orada olmasına bağlıdır. İki tablo aynı düzeneği, aynı grup büyüklüğünü ve aynı sınır maliyetini ölçüyor; biri 48 tik kazandırıyor, öbürü hiç. Aradaki fark koddan değil, yükün bileşiminden geliyor — ve o bileşimi bilmenin yolu, önceki iki dersin yaptığı gibi ölçmektir.
İlk dersin çağrı dökümü bu ayrımı zaten göstermişti. islemci_adimi_mi girdi/çıktı ağırlıklı
yükte 136, işlemci ağırlıklı yükte 322 kez çağrılıyordu; ilkinde işlemci adımları
yuvada birikmiyor, ikincisinde birikiyordu. Uzantı kararı için gereken bilgi orada
duruyordu. Profil çıkarmadan uzantıya geçmek, ikinci tablodaki beş satırı yazmakla aynı
şeydir: yapılmış iş, ölçülmüş sıfır kazanç.
Özet
- Yerel uzantı modelde üç etkiyle temsil edilir: sıcak yolun adım sayısının düşmesi, çağrı başına sabit sınır maliyeti, ve kilidin bırakılmasıyla adımın yuva istemeyi bırakması.
- İşlemci ağırlıklı yükte 12 dörtlü grup 80 adımı 44’e, 73 tiki 37’ye indiriyor; kilit de bırakılırsa tik 25’e iniyor ve örtüşen adım 7’den 19’a çıkıyor.
- Çağrı başına bir adımlık sınır maliyeti kazancı 48’den 36’ya çekiyor — kilit bırakmanın getirdiği kazancın tamamını yiyor. Kazanç grup büyüklüğüyle, maliyet çağrı sayısıyla artar.
- Toplam adım hiç düşmeden de kazanç olabilir: ikili gruplarda adım 80’de kalırken tik 73’ten 44’e iniyor, kazancın tümü örtüşmeden geliyor.
- Grup büyüklüğü sıcak yolun gerçek uzunluğunu aşarsa kazanç küçülür: onlu grup 44 tik verirken dörtlü grup 25 veriyor.
- Aynı düzenek girdi/çıktı ağırlıklı yükte hiçbir şey kazandırmıyor, çünkü o yükte ardışık dörtlü grup sayısı 0.
Sonraki Adım
Bu ders bir tablo boyunca aynı şeyi yaptı: her satırda neyin sayıldığını satırın adında yazdı — kaç adım birleşti, sınır ödendi mi, kilit bırakıldı mı. Adlar kaldırılsaydı geriye yalnız sayılar kalırdı, ve 37 ile 37 yan yana durup aynı şeyi ölçtüklerini söylerdi; oysa biri sınır ödeyen kilitli rejim, öbürü sınır ödemeyen kilitsiz rejimdi. Kursun son dersi bu tehlikeyi kendi başına ölçer: aynı iş, aynı rejim, tek fark ölçüme neyin dahil edildiği — ve iki sayı arasında ne kadar fark çıkıyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.