İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat