Ders 21 / 22
Maliyet ve Gecikme Denetimi
Bir ajan döngüsünün harcamasının iki ayrı paydayla okunması: tek adımlı araçsız çağrı adım başına 90,00 maliyet birimiyle en ucuzudur ama başarımı 0,0000 olduğu için doğru yanıt başına maliyeti tanımsızdır. Büyük ve küçük model sınıfı üç adım bütçesiyle koşturulduğunda küçük sınıf adım başına 79,25 ile büyük sınıfın 118,30'unun altında kalırken doğru yanıt başına 488,0 ile onun 453,5'inin üstüne çıkıyor. İki sıralamanın ayrıştığı bant birim fiyat oranıyla verilir: adım başına eşitlenme 0,8957, doğru yanıt başına eşitlenme 0,5576, arada kalan her fiyat oranında iki ölçüt ters yanıt verir. Gecikme sınıf olarak yazılır ve en uzun koşumdan okunur; ham süre ölçülmez.
İçindekiler
Bir önceki ders izin bedelini belirteçle ödedi: tam gözlem düzeyi 13623 belirteç sakladı ve karşılığında başarısız görevlerin nedenini geri okuttu. O bedel, döngünün ödettiği harcamanın yalnız bir kalemidir. Asıl harcama döngünün kendisindedir: her adım bir istem taşır, taşınan istem önceki gözlemlerle büyür ve adım sayısı görevden göreve değişir.
Bu dersin sorusu şudur: bir düzeneğin pahalı olup olmadığını neye bölerek söylüyoruz. Model API’leri ile Uygulama Geliştirme kursundaki maliyet dersi belirteç muhasebesini istek başına kurmuş ve paydanın değişmesiyle sıralamanın değiştiğini orada da göstermişti; o yordam burada tekrarlanmaz. Burada payda adım ile doğru yanıttır, bölünen şey tek bir çağrının değil bütün döngünün harcamasıdır ve karşılaştırılan şeyler adım bütçesi ile model sınıfıdır.
- KL41. Ortam, araçlar, görev kümesi ve ajan döngüsü kurgudur; gerçek bir model uç noktası ya da araç sunucusu çağrılmaz. Tohum 20260218, ikinci koşum 20260219.
- KL42. Taban çizgisi tek adımlı, araçsız çağrıdır: ajan hiçbir araç çağırmaz, tek adımda yanıt verir. Belirteci döngünün ilk adımının belirtecidir (istem 60, yanıt 30). Hiçbir gözlem duruma girmediği için başarımı 0,0000’dır.
- KL43. Model sınıfı doğru araç seçme payını ölçekler. Büyük sınıfın çarpanı 1,00’dir, yani ortak tanımın kendisidir; küçük sınıfın çarpanı 0,60’tır ve pay 0,20 ile 0,95 arasına kırpılır. Sınıflar tür adıyla anılır; hiçbir model, sürüm ya da sağlayıcı adı geçmez.
- KL44. Maliyet birimi belirteç başına ödenen göreli bedeldir. Büyük sınıfta 1,00 alınır; küçük sınıfın birim fiyatı bir parametredir ve tabloda 0,60 ile basılır.
- KL45. Gecikme sınıf olarak yazılır ve en uzun koşumun adım sayısından okunur: 1 adım tek çağrı, 2 ile 4 adım kısa zincir, 5 ile 8 adım uzun zincir, dokuz ve üstü çok uzun zincir. Hiçbir yerde ham süre ölçülmez; sınıfı belirleyen şey en kötü durumdaki zincirin uzunluğudur.
- KL46. Eşitlenme oranı, küçük sınıfın birim fiyatının hangi değerinde iki sınıfın ilgili ölçütte eşitlendiğidir. Seçilen fiyattan bağımsız türetilir ve tablonun kendisinden okunur.
Altı Düzenek, Tek Görev Kümesi
Aşağıdaki blok kursun ortak tanımını kurar: ölçüm ağının kurgu abone kayıtları, kurgu belge dağarcığı, beş araç, yirmi dört görev ve ajan döngüsü.
# KURGUDUR. Olcum aginin abone kayitlari, belge dagarcigi, bes arac ve yirmi dort # gorev ders icinde tanimlanir; gercek bir uc nokta ya da arac sunucusu 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 def ayrik(u, w): t = 0.0 for i, x in enumerate(w): t += x if u < t: return i return len(w) - 1 def belirtecle(m): b = [] for s in str(m).lower().replace(",", " , ").split(): while len(s) > 5: b.append(s[:5]) s = s[5:] b.append(s) return b def izno(m): h = 2166136261 for c in str(m): h = ((h ^ ord(c)) * 16777619) & M32 return h BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"] TIP = ["mesken", "isyeri"] ABONE = {} for i in range(60): r = uretec(TOHUM + 31 * i) onceki = 10000 + int(r() * 80000) ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)], "onceki": onceki, "simdiki": onceki + int(r() * 70)} BASAMAK, USTU = ((10, 4), (25, 7), (40, 11)), 16 ISYERI_KAT = 2 BELGE = {"TR01": "tarife basamaklari 10 25 40 metrekup ve ustu", "TR02": "isyeri abonesinde birim ucret iki katidir", "SY01": "endeks farki tuketimi verir sayac donusu 100000 eklenir", "AR01": "ariza kaydi acildiginda saha ekibi iki gun icinde gider", "KS01": "planli kesinti duyurusu bir hafta once yayimlanir"} CAGRI = [0] # arac cagri sayaci def _bedel(m3, tip): kalan, alt, top = m3, 0, 0 for ust, birim in BASAMAK: dilim = min(kalan, ust - alt) if dilim <= 0: break top += dilim * birim kalan -= dilim alt = ust top += kalan * USTU return top * (ISYERI_KAT if tip == "isyeri" else 1) def t_sayac_oku(abone=None, **_): a = ABONE.get(abone) if a is None: return {"hata": "abone yok"} return {"onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"], "bolge": a["bolge"]} def t_tuketim(onceki=None, simdiki=None, **_): if onceki is None or simdiki is None: return {"hata": "eksik alan"} f = simdiki - onceki return {"m3": f + 100000 if f < 0 else f} def t_tarife(m3=None, tip="mesken", **_): if m3 is None: return {"hata": "eksik alan"} return {"tutar": _bedel(m3, tip)} def t_belge(anahtar=None, **_): if not anahtar: return {"hata": "eksik alan"} ab = set(belirtecle(anahtar)) en, kod = -1, None for k, m in BELGE.items(): o = len(ab & set(belirtecle(m))) if o > en: en, kod = o, k return {"kod": kod, "metin": BELGE[kod]} if en > 0 else {"hata": "bulunamadi"} def t_kayit(abone=None, sutun=None, deger=None, **_): if not (abone and sutun and deger is not None): return {"hata": "eksik alan"} return {"yazildi": True, "abone": abone, "sutun": sutun, "deger": deger} ARAC = { "sayac_oku": {"islev": t_sayac_oku, "alan": ("abone",), "yan_etki": False}, "tuketim": {"islev": t_tuketim, "alan": ("onceki", "simdiki"), "yan_etki": False}, "tarife": {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False}, "belge_ara": {"islev": t_belge, "alan": ("anahtar",), "yan_etki": False}, "kayit_yaz": {"islev": t_kayit, "alan": ("abone", "sutun", "deger"), "yan_etki": True}, } ARAC_ADI = list(ARAC) def cagir_arac(ad, durum): """Sema disindaki alanlar suzulur; eksik alan aracin kendi hatasidir.""" CAGRI[0] += 1 if ad not in ARAC: return {"hata": "arac yok"} kw = {a: durum[a] for a in ARAC[ad]["alan"] if a in durum} return ARAC[ad]["islev"](**kw) GOREV = [] for i in range(24): r = uretec(TOHUM + 9973 * i) ab = f"A{1 + int(r() * 60):03d}" t = ayrik(r(), [0.30, 0.22, 0.20, 0.28]) if t == 0: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "bedel", "abone": ab, "istek": f"{ab} abonesinin bu donem bedeli nedir", "dizi": ("sayac_oku", "tuketim", "tarife")}) elif t == 1: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "tuketim", "abone": ab, "istek": f"{ab} abonesinin bu donem tuketimi kac metrekup", "dizi": ("sayac_oku", "tuketim")}) elif t == 2: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "belge", "abone": ab, "istek": "sayac donusunde endeks farki nasil hesaplanir", "dizi": ("belge_ara",)}) else: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "kayit", "abone": ab, "istek": f"{ab} abonesinin bedelini hesapla ve kayda yaz", "dizi": ("sayac_oku", "tuketim", "tarife", "kayit_yaz")}) def dogru_yanit(g): a = ABONE[g["abone"]] f = a["simdiki"] - a["onceki"] m3 = f + 100000 if f < 0 else f if g["tur"] == "tuketim": return m3 if g["tur"] == "belge": return "SY01" return _bedel(m3, a["tip"]) def gorme(d): return max(0.34, 0.80 - 0.09 * (d - 1)) # dogru araci secme payi, derinlikle duser def ajan(g, en_cok_adim=8, tohum=TOHUM, oz_elestiri=False, onay=False): """KURGU ajan dongusu. Gercek bir model cagrilmaz; arac secimi gorevin dizisine ve derinlige bagli tek bir cekilisten gelir.""" r = uretec(tohum ^ izno(g["ad"])) alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} iz, adim, bel, hata = [], 0, 0, 0 dizi, k = g["dizi"], 0 while adim < en_cok_adim: adim += 1 bel += 60 + 22 * len(iz) hedef = dizi[k] if k < len(dizi) else None if hedef is None: # is bitti , ajan durmali if r() < 0.88: return {"bitti": True, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} sec = ARAC_ADI[int(r() * len(ARAC_ADI))] else: sec = hedef if r() < gorme(k + 1) else ARAC_ADI[int(r() * len(ARAC_ADI))] if ARAC[sec]["yan_etki"] and onay: alan["onay"] = alan.get("onay", 0) + 1 if sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") s = cagir_arac(sec, alan) iz.append((sec, "hata" in s)) bel += 30 if "hata" in s: hata += 1 if oz_elestiri: bel += 40 continue alan.update({kk: vv for kk, vv in s.items() if kk != "hata"}) if sec == "tuketim": alan["sonuc"] = s["m3"] if sec == "tarife": alan["sonuc"] = s["tutar"] if sec == "belge_ara": alan["sonuc"] = s["kod"] if sec == hedef: k += 1 return {"bitti": False, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)}
Model sınıfı ortak tanıma tek bir yerden dokunur: doğru araç seçme payını ölçekleyen bir çarpan. Çarpan 1,00 iken taban birebir korunur, yani büyük sınıf ortak tanımın kendisidir.
# Model sinifi dogru arac secme payini olcekler; buyuk sinif ortak tanimin kendisidir. CARPAN = [1.00] _taban_gorme = gorme def gorme(d): return max(0.20, min(0.95, _taban_gorme(d) * CARPAN[0])) SINIF = {"buyuk": 1.00, "kucuk": 0.60} # dogru arac secme payi carpani FIYAT = {"buyuk": 1.00, "kucuk": 0.60} # belirtec basina maliyet birimi ARACSIZ_BEL = 60 + 30 # tek adimli, aracsiz cagrinin belirteci def gecikme(u): if u <= 1: return "tek cagri" return "kisa zincir" if u <= 4 else ("uzun zincir" if u <= 8 else "cok uzun zincir") def kosum(sn, b, tohum): CARPAN[0] = SINIF[sn] dogru, adim, bel, uzun = 0, 0, 0, 0 for g in GOREV: s = ajan(g, en_cok_adim=b, tohum=tohum) adim += s["adim"] bel += s["belirtec"] uzun = max(uzun, s["adim"]) dogru += s["yanit"] == dogru_yanit(g) return dogru, adim, bel, uzun for tohum in (20260218, 20260219): n = len(GOREV) print(f"tohum {tohum}") print("duzenek basarim adim belirtec maliyet adim basina dogru basina gecikme") print(f"{'araci yok':<14} {0.0:>8.4f} {n:>5} {n * ARACSIZ_BEL:>9} {n * ARACSIZ_BEL:>8.1f}" f" {ARACSIZ_BEL:>12.2f} {'tanimsiz':>13} {gecikme(1)}") veri = {} for sn in ("buyuk", "kucuk"): for b in (4, 6, 12): dogru, adim, bel, uzun = kosum(sn, b, tohum) veri[(sn, b)] = (dogru, adim, bel) m = bel * FIYAT[sn] print(f"{sn + ' butce ' + str(b):<14} {dogru / n:>8.4f} {adim:>5} {bel:>9} {m:>8.1f}" f" {m / adim:>12.2f} {m / dogru:>13.1f} {gecikme(uzun)}") print("butce esitlenme orani adim basina dogru yanit basina") for b in (4, 6, 12): db, ab, bb = veri[("buyuk", b)] dk, ak, bk = veri[("kucuk", b)] print(f"{b:>5} {(bb / ab) / (bk / ak):>28.4f} {(bb / db) / (bk / dk):>20.4f}")
tohum 20260218
duzenek basarim adim belirtec maliyet adim basina dogru basina gecikme
araci yok 0.0000 24 2160 2160.0 90.00 tanimsiz tek cagri
buyuk butce 4 0.8750 84 9402 9402.0 111.93 447.7 kisa zincir
buyuk butce 6 1.0000 92 10884 10884.0 118.30 453.5 uzun zincir
buyuk butce 12 0.9583 98 12214 12214.0 124.63 531.0 cok uzun zincir
kucuk butce 4 0.5417 90 10624 6374.4 70.83 490.3 kisa zincir
kucuk butce 6 0.7917 117 15454 9272.4 79.25 488.0 uzun zincir
kucuk butce 12 1.0000 142 21762 13057.2 91.95 544.0 cok uzun zincir
butce esitlenme orani adim basina dogru yanit basina
4 0.9482 0.5478
6 0.8957 0.5576
12 0.8132 0.5857
tohum 20260219
duzenek basarim adim belirtec maliyet adim basina dogru basina gecikme
araci yok 0.0000 24 2160 2160.0 90.00 tanimsiz tek cagri
buyuk butce 4 0.8333 83 9366 9366.0 112.84 468.3 kisa zincir
buyuk butce 6 0.9583 96 11610 11610.0 120.94 504.8 uzun zincir
buyuk butce 12 0.9583 98 11994 11994.0 122.39 521.5 uzun zincir
kucuk butce 4 0.3750 89 10550 6330.0 71.12 703.3 kisa zincir
kucuk butce 6 0.7917 121 16396 9837.6 81.30 517.8 uzun zincir
kucuk butce 12 0.8750 140 20526 12315.6 87.97 586.5 cok uzun zincir
butce esitlenme orani adim basina dogru yanit basina
4 0.9519 0.3995
6 0.8925 0.5850
12 0.8348 0.5335
Ucuz Olan Neye Göre Ucuz
İlk satır soruyu tek başına kuruyor. Araçsız çağrı adım başına 90,00 ile büyük sınıfın bütün düzeneklerinden ucuzdur; 111,93, 118,30 ve 124,63’ün hepsinin altındadır. Doğru yanıt başına maliyeti ise tanımsızdır, çünkü payda sıfırdır. Adım başına maliyet sıralamasının en tepesinde hiçbir işi bitirmeyen düzenek durur. Bu, bir ölçüt hatası değil, paydanın ne saydığının sonucudur: adım başına maliyet adımın ucuzluğunu ölçer, işin bitip bitmediğini ölçmez.
Aynı sınıf içinde bütçeyi büyütmek adım başına maliyeti düzenli olarak yükseltiyor: büyük sınıfta 111,93, 118,30, 124,63. Sebep döngünün belirteç muhasebesindedir; her adım kendinden önceki gözlemleri de taşır, bu yüzden geç adımlar erken adımlardan pahalıdır. Doğru yanıt başına maliyet ise 447,7, 453,5 ve 531,0’dir. İlk iki değer arasındaki 5,8’lik fark, aynı satırın iki koşum arasındaki farkından (447,7’ye karşı 468,3, yani 20,6) küçüktür; bütçe 4 ile bütçe 6 arasındaki sıralama bu ölçütte ölçülmemiş sayılır. Bütçe 12’nin 531,0’i ise banda göre büyüktür ve gerçek bir kötüleşmedir.
İki Sıralamanın Ayrıştığı Bant
Asıl ayrışma sınıflar arasındadır. Birim fiyat 0,60 alındığında küçük sınıf bütçe 6’da adım başına 79,25 ile büyük sınıfın 118,30‘unun belirgin altındadır. Aynı iki satır doğru yanıt başına okunduğunda sıra ters döner: 488,0‘e karşı 453,5. Küçük sınıf ucuz adımlar üretir ama daha çok adım harcar (117’ye karşı 92) ve daha az görev bitirir (0,7917’ye karşı 1,0000). İkinci koşum aynı yönü verir: 81,30’a karşı 120,94 ve 517,8’e karşı 504,8.
Bu ayrışma seçilen fiyata bağlı görünebilir, ama bağlı olmadığı tablonun son bölümünden okunur. Bütçe 6’da adım başına eşitlenme oranı 0,8957, doğru yanıt başına eşitlenme oranı 0,5576‘dır. Küçük sınıfın birim fiyatı 0,5576’nın altındaysa iki ölçüt de küçük sınıfı ucuz sayar; 0,8957’nin üstündeyse iki ölçüt de büyük sınıfı ucuz sayar. Arada kalan her fiyat oranında iki ölçüt ters yanıt verir ve hangisinin ucuz olduğu sorusunun tek bir doğru cevabı yoktur. İkinci koşum bandı 0,5850 ile 0,8925 arasına koyuyor; iki koşumun üst kenarı 0,0032 ile örtüşüyor, alt kenarı 0,0274 oynuyor. Bant bu yüzden yaklaşık olarak 0,56 ile 0,89 arasıdır. Bütçe 4’ün alt kenarı ise 0,5478 ile 0,3995 arasında oynuyor; o satırın bandı ölçülmemiş sayılır.
Gecikme sütunu ayrı bir uyarı taşıyor. Sınıf en uzun koşumdan okunur ve büyük sınıf bütçe 12 bir koşumda çok uzun zincir, öbüründe uzun zincir çıkıyor. Ortalama adım sayısı iki koşumda neredeyse aynıdır; oynayan şey tek bir görevin en kötü durumudur. Bir gecikme bütçesi en kötü duruma göre konuyorsa, aynı düzeneğin sınıfı iki koşum arasında değişebilir ve bu değişim bir iyileşme ya da kötüleşme diye okunamaz.
Özet
- Tek adımlı araçsız çağrı adım başına 90,00 ile en ucuz düzenektir ve doğru yanıt başına maliyeti tanımsızdır; adım başına ölçüt işin bitip bitmediğini saymaz.
- Büyük sınıfta bütçe büyüdükçe adım başına maliyet 111,93’ten 124,63’e çıkar, çünkü geç adımlar önceki gözlemleri de taşır.
- Birim fiyat 0,60’ta küçük sınıf adım başına 79,25 ile ucuz, doğru yanıt başına 488,0 ile pahalıdır; büyük sınıfın karşılıkları 118,30 ve 453,5’tir.
- Eşitlenme oranları iki ölçütün ayrıştığı bandı verir: bütçe 6’da adım başına 0,8957, doğru yanıt başına 0,5576; arada kalan her fiyatta iki ölçüt ters yanıt verir.
- Gecikme en uzun koşumdan okunan bir sınıftır ve aynı düzenek iki koşumda iki ayrı sınıfa düşebilir; ham süre hiçbir yerde ölçülmez.
Sonraki Adım
Maliyet tablosunun bütün satırlarında bir sütun sessiz kaldı: araç hatası. Döngü bir araç hata döndürdüğünde ne yapacağını bu derste hiç sormadık; ortak tanımın döngüsü hatayı görüp aynı hedefe yeniden yöneliyordu ve bunu bir politika olarak yazmamıştık. Sonraki ders bu boşluğu ölçer: ilk hatada durmak, aynı aracı yeniden denemek ve başarısız aracı bir daha seçmemek üç ayrı politikadır ve üçü başarımı, adımı ve araç hatasını ayrı yönlere çeker. O ders aynı zamanda kursun kapanışıdır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.