---
title: 'Vektörleştirilmiş İşlemler'
source: 'https://academia.sh/tr/kurslar/python-ile-analiz/vektorlestirilmis-islemler'
course: 'Python ile Veri Analizi'
language: tr
updated: '2026-08-17T18:08:44+00:00'
license: 'CC BY-SA 4.0'
---

# Vektörleştirilmiş İşlemler

Aynı türetme işi tek döngüyle ve vektörleştirilmiş çağrı zinciriyle yapılır: satır sayısı 10'dan 2'ye düşerken geçiş sayısı 1'den 3'e, ayrılan bayt 30.320'den 90.960'a çıkar; zincirdeki her halka bir geçiş ve bir ara dizi ekler. Çağrının sessizce verdiği üç karar sayılır: tek bir kesirli sabit zinciri 64 bite taşır ve ayrılan baytı 30.400'den 60.720'ye çıkarır, 16 bit öğe tipi 3.780 öğenin 1.538'ini kaydırarak 102.034,22 m³ toplamı 1.239,85 m³ gösterir, nöbetçi değerle işaretlenmiş 581 boş hücrenin ilk işlemden sonra 0'ı ayırt edilebilir kalır ve aşımı sıfır görünen hücre sayısı 1.783'e çıkar.

Önceki ders üç ölçüden birinin beklenenin dışında çıktığını gösterdi: satır sayısı on birde bire
indi, ayrılan bayt altıda bire indi, ama geçiş sayısı hiç düşmedi. Bu ders o sayıyı ele alır ve
daha kötü bir haberle başlar — vektörleştirilmiş bir zincirde geçiş sayısı düşmez, **artar**.

İşin kendisi önceki kursun türetilmiş değişken adımından geliyor: her hücrenin ikinci tarife
basamağının üstünde kalan payı hesaplanacak. Okumadan 25 m³ çıkarılır, negatif sonuçlar sıfırda
kırpılır, kalan litreye çevrilir. Üç işlem, tek bir sonuç. İki yolla yazılır: tek bir döngüde
kaynaşmış olarak ve üç vektörleştirilmiş çağrının zinciri olarak.

- **SH5.** Vektörleştirilmiş bir çağrı döngüyü **yazmaktan** kurtarır, **geçişten** kurtarmaz.
  Zincirdeki her halka veriyi bir kez tarar ve sonucu yeni bir dizide tutar; kazanç satırda,
  bedel geçişte ve ayrılan bayttadır.
- **SH6.** Vektörleştirilmiş bir işlem öğe tipini kendi seçer. Bu seçim üç biçimde sayıyı oynatır:
  tipi yükselterek baytı büyütür, dar bir tipte taşarak sonucu küçültür, nöbetçi değeri sıradan
  bir sayıya çevirerek eksik hücreyi ayırt edilemez kılar.

## Bir İş, İki Yol

```python
# vektor.py — MODELDIR: vektorlestirilmis islem, ogeyi tek tek gezmeyen bir cagri
# olarak yaziliyor. Her cagri veriyi bir kez tarar (bir gecis) ve sonucu yeni bir
# dizide tutar (bir ara dizi). Kume K03'un hazirladigi kurgu kumedir.
import inspect
import sys
from array import array

def uretec(tohum):
    s = tohum & 0xFFFFFFFF
    def sonraki():
        nonlocal s
        s = (1664525 * s + 1013904223) & 0xFFFFFFFF
        return s / 4294967296
    return sonraki

ABONE, DONEM = 1260, 3
r = uretec(20260218)
HAM = [round(4 + r() * 56, 2) for _ in range(ABONE * DONEM)]
r2 = uretec(9110723)
p = [r2() for _ in range(ABONE * DONEM)]
BOS = set(sorted(range(len(p)), key=lambda j: p[j])[:581])
OKUMA = [0.0 if j in BOS else HAM[j] for j in range(ABONE * DONEM)]

GECIS = 0   # veri uzerinden bastan sona bir tam tarama
ARA = 0     # sonuc ve ara dizilerin ayirdigi bayt

class Dizi:
    def __init__(self, veri, tip="d"):
        self.d, self.tip = array(tip, veri), tip

def islem(a, f, tip=None):
    global GECIS, ARA
    GECIS += 1
    c = Dizi([f(x) for x in a.d], tip or a.tip)
    ARA += sys.getsizeof(c.d)
    return c

UST = 25.0        # ikinci tarife basamaginin ust siniri, m3
LITRE = 1000      # m3 -> litre

def elle(veri):
    global GECIS, ARA
    cikti = []
    for x in veri:
        f = x - UST
        cikti.append((f if f > 0.0 else 0.0) * LITRE)
    GECIS += 1
    c = Dizi(cikti)
    ARA += sys.getsizeof(c.d)
    return c

cikar = lambda a, s: islem(a, lambda x: x - s)
kirp = lambda a, alt: islem(a, lambda x: x if x > alt else alt)
carp = lambda a, s: islem(a, lambda x: x * s)

def zincirle(a):
    return carp(kirp(cikar(a, UST), 0.0), LITRE)

A = Dizi(OKUMA)
GECIS, ARA = 0, 0
E = elle(A.d); ge, ae = GECIS, ARA
GECIS, ARA = 0, 0
V = zincirle(A); gv, av = GECIS, ARA
satir = lambda f: len(inspect.getsource(f).strip().splitlines())
gen = lambda w: lambda h: "".join(str(v).ljust(w[0]) if j == 0 else str(v).rjust(w[j])
                                  for j, v in enumerate(h))
y = gen([22, 18, 20, 10])
print(f"is: (okuma - {UST} m3) degeri sifirda kirpilir ve litreye cevrilir; {len(OKUMA)} oge\n")
print(y(["olcu", "elle tek dongu", "vektorlestirilmis", "oran"]))
print(y(["satir sayisi", satir(elle), satir(zincirle), f"{satir(elle)/satir(zincirle):.1f}x"]))
print(y(["gecis sayisi", ge, gv, f"{gv/ge:.1f}x"]))
print(y(["ayrilan bayt", ae, av, f"{av/ae:.1f}x"]))
esit = sum(1 for x, z in zip(E.d, V.d) if abs(x - z) < 1e-9)
print(f"\nsonuc ayni: {esit}/{len(OKUMA)} oge 1e-9 litre esiginin altinda ayni "
      f"(kayan noktali karsilastirma == ile yapilmaz; esik litre cozunurlugunun altindadir)")
print(f"asim toplami {sum(V.d)/LITRE:.2f} m3")
```

```
is: (okuma - 25.0 m3) degeri sifirda kirpilir ve litreye cevrilir; 3780 oge

olcu                      elle tek dongu   vektorlestirilmis      oran
satir sayisi                          10                   2      5.0x
gecis sayisi                           1                   3      3.0x
ayrilan bayt                       30320               90960      3.0x

sonuc ayni: 3780/3780 oge 1e-9 litre esiginin altinda ayni (kayan noktali karsilastirma == ile yapilmaz; esik litre cozunurlugunun altindadir)
asim toplami 34707.55 m3
```

İki yol da aynı 3.780 sayıyı üretiyor. Karşılaştırma litre çözünürlüğünün çok altında bir eşikle,
1e-9 litre ile yapıldı; kayan noktalı iki değer `==` ile karşılaştırılmaz, çünkü aynı matematiksel
sonuca farklı sırada varan iki hesap son basamakta ayrışabilir. Eşik burada anlamlı bir farkı
gizlemez: 1e-9 litre bir sayacın okuyabileceği en küçük değerin milyarda biridir.

Kazanç satırdadır ve gerçektir. Elle yazılan sürüm 10 satır tutuyor, zincir 2 satır. Fark yalnız
uzunluk değil: elle yazılan sürümde döngü sınırı, biriktirme listesi ve kırpma koşulu aynı yerde
iç içedir; üç işlemden birini değiştirmek döngünün gövdesine dokunmayı gerektirir. Zincirde üç
halka birbirinden bağımsızdır ve `cikar`, `kirp`, `carp` bir kez yazılıp her yerde kullanılır.

Bedel sonraki iki satırdadır ve çoğu zaman hesaba katılmaz. Zincir üç halkadan oluştuğu için veri
**üç kez** taranır; elle yazılan döngü bir kez tarar. Her halka sonucunu yeni bir dizide tuttuğu
için 3.780 öğelik üç dizi ayrılır: 90.960 bayt. Bunun 60.640 baytı **ara diziler**, yani
kullanıldıktan sonra atılan iki geçici sonuçtur. Elle yazılan sürüm yalnız çıktı dizisini ayırır:
30.320 bayt. Küçük kümelerde bu fark görünmez; ölçek büyüdüğünde zincirin uzunluğu doğrudan bellek
tepesine yazılır, çünkü ara dizilerin her biri girdi kadar yer tutar.

Buradan kursun sürekli kuralına bağlanan bir okuma çıkıyor: zincirdeki halka sayısı, çağrıyı yazan
kişinin verdiği ama çoğu zaman farkında olmadığı bir karardır. Üç halkalık bir zincir üç geçiş,
beş halkalık bir zincir beş geçiş demektir ve kod satırı ikisinde de aynı kalır. **Zincirin
uzunluğu kodda görünür, bedeli görünmez.**

## Zinciri Kaynaştırmak

```python
# kaynasik.py — MODELDIR: ucuncu yol. Zincirin uc halkasi tek bir vektorlestirilmis
# cagriya kaynastiriliyor; dongu yine yazilmiyor ama veri bir kez taraniyor.
def kaynasik(a):
    return islem(a, lambda x: (x - UST if x > UST else 0.0) * LITRE)

GECIS, ARA = 0, 0
K = kaynasik(A); gk, ak = GECIS, ARA
w = gen([20, 10, 12, 12, 18])
print(w(["olcu", "elle", "zincir", "kaynasik", "en dusugu"]))
print(w(["satir sayisi", satir(elle), satir(zincirle), satir(kaynasik), "zincir / kaynasik"]))
print(w(["gecis sayisi", ge, gv, gk, "elle / kaynasik"]))
print(w(["ayrilan bayt", ae, av, ak, "elle / kaynasik"]))
print(w(["yeniden kullanilir", 0, 3, 0, "zincir"]))
sapan = sum(1 for x, z in zip(V.d, K.d) if abs(x - z) > 1e-9)
print(f"\nuc yol da ayni sonucu veriyor: {sapan} oge 1e-9 litre esiginin ustunde sapiyor")
print(f"kaynasik yol zincirle ayni satirda, elle ile ayni gecis ve bayttadir; bedeli "
      f"uc kararin tek ifadeye girmesi ve yeniden kullanilabilir parca sayisinin 3'ten 0'a inmesi")
```

```
olcu                      elle      zincir    kaynasik         en dusugu
satir sayisi                10           2           2 zincir / kaynasik
gecis sayisi                 1           3           1   elle / kaynasik
ayrilan bayt             30320       90960       30320   elle / kaynasik
yeniden kullanilir           0           3           0            zincir

uc yol da ayni sonucu veriyor: 0 oge 1e-9 litre esiginin ustunde sapiyor
kaynasik yol zincirle ayni satirda, elle ile ayni gecis ve bayttadir; bedeli uc kararin tek ifadeye girmesi ve yeniden kullanilabilir parca sayisinin 3'ten 0'a inmesi
```

Üçüncü yol zincirin bedelinin kaçınılmaz olmadığını gösteriyor. Üç halkanın işi tek bir
vektörleştirilmiş çağrının içine kaynaştırıldığında satır sayısı zincirdekiyle aynı kalıyor, geçiş
sayısı elle yazılan döngüdeki gibi 1'e, ayrılan bayt 30.320'ye iniyor. Üç ölçünün de en düşüğü
burada.

Bedelin nerede olduğu son satırda duruyor. Zincirde `cikar`, `kirp` ve `carp` bağımsız üç parçadır
ve başka bir hesapta başka sırayla yeniden kullanılır. Kaynaştırılmış ifadede aynı üç karar tek bir
gövdeye girer ve dışarıdan alınamaz; yeniden kullanılabilir parça sayısı 3'ten 0'a iner. Tarife
eşiği bir basamak kayarsa zincirde yalnız çağrının bir parametresi değişir, kaynaştırılmış ifadede
gövde yeniden yazılır.

Ölçünün kursa taşınan biçimi budur: soyutlamanın kazancı üç sayının hepsinde birden görünmez ve
"vektörleştirilmiş yazmak" tek bir şey değildir. **Kaç halka yazıldığı bir karardır** ve o karar
geçiş sayısıyla bellek tepesini birlikte belirler.

## Çağrının Verdiği Üç Karar

```python
# gizli.py — MODELDIR: vektorlestirilmis cagrinin senin yerine verdigi uc karar.
LITRELIK = [int(round(x * LITRE)) for x in OKUMA]

# 1. Tip yukseltme. Zincirin ilk halkasi tamsayi, ikincisi kesirli bir sabitle carpiyor.
TAM = Dizi(LITRELIK, "i")
GECIS, ARA = 0, 0
kalan = islem(TAM, lambda x: x - 25000, "i")
tam_bayt = ARA + sys.getsizeof(TAM.d)
GECIS, ARA = 0, 0
ucret = islem(islem(TAM, lambda x: x - 25000, "i"), lambda x: x * 0.0042, "d")
kesirli_bayt = ARA + sys.getsizeof(TAM.d)

# 2. Tasma. Bellek kazanmak icin oge tipi 16 bit tamsayi secilirse litre degerleri
# sinira sigmaz. Kaydirma acikca yaziliyor; oge tipinin davranisinin modelidir.
SINIR = 2 ** 15
kaydir = lambda v: ((v + SINIR) % (2 * SINIR)) - SINIR
tasan = [v for v in LITRELIK if v > SINIR - 1]
kayan = [kaydir(v) for v in LITRELIK]

# 3. Nobetci degerin kaybolmasi. 581 bos hucre -1 ile isaretlenmisti.
NOB = Dizi([-1.0 if j in BOS else HAM[j] for j in range(ABONE * DONEM)])
son = carp(kirp(cikar(NOB, UST), 0.0), LITRE)
ayirt = sum(1 for j in BOS if abs(son.d[j]) > 1e-9)
sifir = sum(1 for x in son.d if abs(x) < 1e-9)

z = gen([26, 22, 26])
print(z(["gizlenen karar", "yazilan varsayim", "olculen sonuc"]))
print(z(["tip yukseltme", "tamsayi kalir", f"{tam_bayt} -> {kesirli_bayt} bayt"]))
print(z(["16 bit tasma", "tasma olmaz", f"{len(tasan)}/{len(LITRELIK)} oge kaydi"]))
print(z(["nobetci hucre", "581 hucre isaretli", f"{ayirt}/581 ayirt edilebilir"]))
print(f"\ntip yukseltme: tek bir kesirli sabit zincirin geri kalanini 64 bite tasir, "
      f"ayrilan bayt {kesirli_bayt - tam_bayt} artar; ucret toplami {sum(ucret.d):.2f}")
print(f"tasma: {len(tasan)} oge 32.767 litre sinirini asiyor; toplam "
      f"{sum(LITRELIK)/LITRE:.2f} m3 yerine {sum(kayan)/LITRE:.2f} m3 cikar")
print(f"nobetci: zincirden sonra asimi sifir gorunen hucre {sifir}; bunun 581'i "
      f"gercek sifir degil, isaretlenmis bos hucre")
```

```
gizlenen karar                  yazilan varsayim             olculen sonuc
tip yukseltme                      tamsayi kalir       30400 -> 60720 bayt
16 bit tasma                         tasma olmaz       1538/3780 oge kaydi
nobetci hucre                 581 hucre isaretli    0/581 ayirt edilebilir

tip yukseltme: tek bir kesirli sabit zincirin geri kalanini 64 bite tasir, ayrilan bayt 30320 artar; ucret toplami 31643.72
tasma: 1538 oge 32.767 litre sinirini asiyor; toplam 102034.22 m3 yerine 1239.85 m3 cikar
nobetci: zincirden sonra asimi sifir gorunen hucre 1783; bunun 581'i gercek sifir degil, isaretlenmis bos hucre
```

**Tip yükseltme** zincirin en sessiz kalemidir. Dizi 32 bit tamsayı olarak kuruldu ve ilk halka
tamsayı kaldı; ikinci halka kesirli bir birim fiyatla çarpınca sonuç tamsayıda temsil edilemez ve
bütün dizi 64 bit kesirliye taşınır. Ayrılan bayt 30.400'den 60.720'ye çıkar. Yazılan kodda
büyümeyi gösteren hiçbir işaret yoktur; büyümeye karar veren şey `0.0042` sabitinin kesirli
olmasıdır. Uzun zincirlerde bu, ilk kesirli halkadan sonraki bütün halkaların iki kat yer tutması
demektir.

**Taşma** ters yöndedir. Öğe tipini daraltmak bellek kazandırır: 16 bit tamsayı 3.780 öğeyi 7.560
baytta tutar. Ama litre cinsinden okumaların 1.538'i 32.767 sınırını aşıyor ve bu değerler negatif
tarafa kayıyor. Kümenin toplamı 102.034,22 m³ yerine 1.239,85 m³ çıkar — yüzde 98,8'lik bir kayıp.
Sonuç bir hata iletisiyle değil, makul görünen küçük bir sayıyla gelir; bir denetim yalnız
"toplam pozitif mi" diye bakıyorsa bunu geçirir. Kaydırma davranışı burada açıkça yazıldı, çünkü
öğe tipinin sınırı aşıldığında ne yaptığı tipin kendi kararıdır ve model bunu görünür kılıyor.

**Nöbetçi değer** üçüncü karardır ve önceki dersin bıraktığı yerden devam eder. Boş hücreleri
`-1` ile işaretlemek dizide eksik değer tutmanın bilinen yoludur, ama işaret yalnız **ilk işleme
kadar** yaşar: `-1` değerinden 25 çıkınca -26 olur, kırpma onu sıfıra çeker ve çarpma sıfır
bırakır. Zincirin sonunda 581 hücrenin **hiçbiri** ayırt edilemez. Aşımı sıfır görünen 1.783
hücrenin 581'i aslında hiç okunmamış hücredir ve bu ikisi arasındaki farkı gösterecek hiçbir iz
kalmamıştır. Kırpma işlemi burada iki farklı anlamı tek değere indiriyor: "eşiğin altında kaldı"
ile "ölçülmedi".

Üç kalemin ortak yanı şudur: hiçbiri hata üretmez. Tip yükseltmesi doğru sonucu verir ve yalnız
belleği büyütür, taşma makul görünen bir sayı verir, nöbetçinin kırpılması geçerli bir aşım
değeri verir. Bir soyutlamanın gizlediği kararlar tam olarak bunlardır — çağrının çalıştığı ve
sonuç ürettiği durumlarda alınan kararlar. Bu yüzden kursun kuralı bir çağrının doğru sonuç verip
vermediğine değil, **varsayılanının yazılıp yazılmadığına** bakar.

## Özet

- Vektörleştirilmiş zincir satır sayısını 10'dan 2'ye indirir, geçiş sayısını 1'den 3'e ve ayrılan
  baytı 30.320'den 90.960'a çıkarır; bunun 60.640 baytı ara dizidir.
- Zincirdeki halka sayısı geçiş sayısına birebir yazılır; kod satırı sabit kalır, bedel kodda
  görünmez.
- Kesirli bir sabit zincirin geri kalanını 64 bite taşır ve ayrılan baytı 30.400'den 60.720'ye
  çıkarır.
- 16 bit öğe tipi 3.780 öğenin 1.538'ini kaydırır ve 102.034,22 m³ toplamı 1.239,85 m³ gösterir;
  sonuç hata değil, makul görünen bir sayıdır.
- Nöbetçi değerle işaretlenmiş 581 boş hücrenin ilk işlemden sonra 0'ı ayırt edilebilir kalır;
  aşımı sıfır görünen hücre 1.783'e çıkar ve "eşiğin altında" ile "ölçülmedi" tek değere iner.
- Üç halka tek çağrıya kaynaştırıldığında geçiş 1'e, bayt 30.320'ye iner ve satır sayısı değişmez;
  bedeli yeniden kullanılabilir parça sayısının 3'ten 0'a inmesidir.

## Sonraki Adım

Bu derste bütün işlemler tek bir biçim üzerinde yapıldı: 3.780 öğelik bir dizi ile bir sayı
arasında. Gerçek hesaplarda iki dizi karşılaşır ve biçimleri çoğu zaman aynı olmaz — dönem başına
bir taban, abone başına bir hane sayısı, tarife basamağı başına bir birim fiyat. Sonraki ders
farklı biçimlerin nasıl uyumlu sayıldığını ve uyumsuz iki biçimin neden hata vermek yerine
beklenmedik bir dizi ürettiğini ölçer.
