Bölüm 3: Bellek Hiyerarşisi
CPU'ya“Sen”iKatmak yazısının parçası: bilgisayarının programları nasıl çalıştırdığına doğru inen uzun bir teknik tavşan deliği.
Bir önceki bölümde CPU’nun talimatları nasıl yürüttüğünü, RAM’in çalışma masası olduğunu ve diskin kalıcı depo olduğunu gördük. Ama bu üçlü arasında aslında çok daha fazla katman var. Bilgisayarın belleği tek düzeyli değil; bir piramit gibi katman katman düzenlenmiş. Neden? Çünkü hızlı bellek pahalıdır, ucuz bellek yavaştır. Piramidin tepesi hızlı ve küçük, tabanı büyük ve yavaş.
Bu bölümde neyi çözüyoruz?
- CPU’dan diske kadar olan bellek piramidini adım adım çıkacağız.
- Register, cache, RAM ve disk arasındaki hız ve maliyet farkını anlayacağız.
- SRAM ile DRAM farkını, cache line kavramını ve locality prensibini öğreneceğiz.
Piramidin Tepesi: Register’lar
CPU’nun içindeki register’lar, daha önce gördüğümüz gibi, işlemcinin doğrudan erişebildiği küçük depolama alanlarıdır. Bir register’ın içeriğine ulaşmak CPU için birkaç nanosaniye sürer. Bu, ışığın birkaç santimetre yol alması kadar kısa bir süredir.
- Hız: ~0.3 - 1 nanosaniye
- Boyut: 64-bit (modern x86-64’te) veya 32-bit (eski sistemlerde)
- Miktar: Birkaç on adet (x86-64’te ~16 genel amaçlı register)
- Maliyet: Çok yüksek (transistör başına en pahalı alan)
Birinci Kademe: L1 Cache
Register’lar yeterli değil. CPU, RAM’den veri almak için yüzlerce saat çevrimi beklemek zorunda kalıyordu. Bu boşluğu doldurmak için cache‘ler (önbellekler) icat edildi. L1 cache, CPU çekirdeğinin içindedir ve register’lardan sonraki en hızlı bellektir.
- Hız: ~1 - 5 nanosaniye (4-10 saat çevrimi)
- Boyut: Genelde 32 KiB - 128 KiB (veri cache’i + talimat cache’i olarak ayrılmış)
- Teknoloji: SRAM (Static RAM)
SRAM vs DRAM
SRAM, her biti için 6 transistör kullanır; bu yüzden hızlı ama pahalıdır. Elektrik kesilse bile veriyi tutar (static = statik). DRAM ise her biti için 1 transistör + 1 kapasitör kullanır; daha ucuz ama kapasitör sürekli tazelenmelidir (dynamic = dinamik). Bu yüzden DRAM daha yavaştır. RAM dediğimiz şey aslında DRAM’dir.
İkinci Kademe: L2 Cache
L2 cache, L1’den biraz daha yavaş ama daha büyüktür. Eskiden anakart üzerindeyken günümüzde CPU çipinin içine alınmıştır.
- Hız: ~5 - 15 nanosaniye (10-30 saat çevrimi)
- Boyut: 256 KiB - 1 MiB (çekirdek başına)
- Teknoloji: SRAM
Üçüncü Kademe: L3 Cache
L3 cache, tüm çekirdekler arasında paylaşılan daha büyük bir önbellektir.
- Hız: ~15 - 40 nanosaniye (30-80 saat çevrimi)
- Boyut: 8 MiB - 128 MiB (işlemciye göre değişir; AMD Epyc’lerde yüzlerce MiB olabilir)
- Teknoloji: SRAM
Ana Bellek: RAM (DRAM)
RAM, çalışan programların verilerinin ve kodunun tutulduğu yerdir. DRAM teknolojisi kullanır.
- Hız: ~80 - 120 nanosaniye (yüzlerce saat çevrimi)
- Boyut: 8 GiB - 128 GiB (günümüz masaüstü/sunucu sistemlerinde)
- Teknoloji: DRAM (DDR4, DDR5 vb.)
DDR nedir? Double Data Rate; her saat çevriminde iki kez veri aktarımı yapar. DDR5, DDR4’e göre daha yüksek bant genişliği sunar.
RAM’in fiziksel yapısı: Bellek modülleri (DIMM’ler), üzerinde bellek çipleri bulunan kartlardır. Anakart üzerindeki bellek denetleyicisi (memory controller), CPU ile RAM arasındaki trafiği yönetir. Modern işlemcilerde bellek denetleyicisi CPU çipinin içindedir.
En Alt Kademe: Disk / SSD
Disk ve SSD, programların kapalıyken saklandığı kalıcı depolardır.
- Hız: SSD ~10-100 mikrosaniye; HDD ~1-10 milisaniye
- Boyut: 256 GiB - 8 TiB ve daha fazlası
- Teknoloji: NAND flash (SSD) veya manyetik plaka (HDD)
SSD, HDD’ye göre 10-100 kat daha hızlıdır ama yine de RAM’e göre 1000 kat yavaştır. Bu yüzden çalışan programlar diskten değil, RAM’den okunur.
Hız ve Boyut Karşılaştırması
| Katman | Tipik Gecikme | Tipik Boyut | Teknoloji |
|---|---|---|---|
| Register | ~0.5 ns | ~1 KiB toplam | CPU transistörü |
| L1 Cache | ~1-5 ns | 32-128 KiB | SRAM |
| L2 Cache | ~5-15 ns | 256 KiB - 1 MiB | SRAM |
| L3 Cache | ~15-40 ns | 8-128 MiB | SRAM |
| RAM | ~80-120 ns | 8-128 GiB | DRAM |
| SSD | ~10-100 µs | 256 GiB - 8 TiB | NAND Flash |
| HDD | ~1-10 ms | 1-20 TiB | Manyetik |
Fark dikkat çekici: Register ile HDD arasında milyonlarca kat hız farkı var.
Cache Line: Cache’in Çalışma Birimi
Cache’ler tek tek byte’ları değil, cache line denen bloklar hâlinde veri taşır. x86-64’te tipik cache line boyutu 64 byte‘tır.
Neden? Çünkü programlar genelde komşu verilere sırayla erişir. CPU bir veriyi istediğinde, cache o verinin komşusu olan 63 byte’ı da getirir. Böylece bir sonraki erişim büyük ihtimalle cache’de bulunur.
Locality: Hızın Sırrı
Cache’lerin işe yaramasının nedeni iki locality prensibidir:
- Temporal Locality (Zamansal Yakınlık): Az önce kullandığın bir veriyi yakında tekrar kullanma ihtimalin yüksektir. Örneğin bir döngüdeki sayaç değişkeni.
- Spatial Locality (Mekânsal Yakınlık): Kullandığın verinin komşusuna da yakında erişme ihtimalin yüksektir. Örneğin bir dizinin elemanlarını sırayla okumak.
İyi yazılmış programlar bu prensipleri kullanarak cache isabet oranını (cache hit rate) yükseltir. Kötü yazılmış kodlar cache’i verimsiz kullanarak performansı düşürebilir.
Cache-Friendly ve Cache-Unfriendly Kod
Locality prensibi pratikte nasıl işler? Aşağıdaki iki C kodu aynı matrisi toplar, ama biri cache’i dostane kullanırken diğeri düşmandır.
Cache-friendly örnek (satır bazlı erişim):
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sum += matrix[i][j]; // Sequential access = cache hitCache-unfriendly örnek (sütun bazlı erişim):
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
sum += matrix[i][j]; // Strided access = cache missNeden satır bazlı (row-major) daha hızlı? C dilinde çok boyutlu diziler satır bazlı saklanır. matrix[i][j] erişimi komşu bellek adreslerine sırayla erişir; bu spatial locality sağlar. Bir cache line (64 byte) içinde ardışık veriler gelir ve CPU bir sonraki erişimde cache’de bulur. Sütun bazlı erişimde ise her erişim farklı bir satıra atlar; bu stride büyük olduğu için her seferinde yeni cache line getirilir ve cache miss oluşur.
Bellek Kanalları ve Bant Genişliği
CPU ile RAM arasında veri, bellek kanalları (memory channels) üzerinden taşınır. Çift kanallı (dual-channel) bellek, iki kanalı paralel kullanarak teorik bant genişliğini iki katına çıkarır.
Bant genişliği, birim zamanda taşınabilen veri miktarıdır. DDR5-5600 bellek, kanal başına ~45 GB/s bant genişliği sunabilir.
TLB: Adres Çevirisinin Hızlı Sözlüğü
CPU sanal adresleri fiziksel adreslere çevirirken sayfa tablolarını (page tables) tarar. Bu tarama çok yavaştır. TLB (Translation Lookaside Buffer), en son kullanılan sanal → fiziksel adres eşleştirmelerini önbellekleyen özel bir donanım önbelleğidir. L1 cache kadar hızlıdır ve birkaç yüz giriş tutar.
Linux çekirdeği, sayfa tabloları değiştiğinde TLB’nin tutarsız hale gelmemesi için explicit TLB flush yapar:
// From arch/x86/include/asm/tlbflush.h
// TLB flush after page table changes
void flush_tlb_mm_range(struct mm_struct *mm, ...);
Bir yana: Neden Cache Line 64 Byte?
Cache line boyutu tarihsel olarak evrimleşmiştir. Pentium 4 döneminde 32 byte kullanılırken, modern x86-64 işlemcilerde standart 64 byte’tır. Bazı ARM tasarımlarında ise 128 byte denenmektedir.
Daha büyük cache line = daha fazla spatial locality avantajı (komşu veriler tek seferde gelir). Ancak yanlış tahmin durumunda (cache miss) 128 byte yerine 64 byte’lık gereksiz veri getirilmiş olur; bu bant genişliği israfıdır. 64 byte, bu denge için endüstride kabul görmüş bir sweet spot’tur.
Kendi Sisteminde Cache’leri Keşfet
Linux sisteminde cache yapılandırmanı komut satırından öğrenebilirsin:
Cache line boyutu:
getconf LEVEL1_DCACHE_LINESIZETüm cache hiyerarşisi:
lscpu | grep -i cacheBeklenen çıktıya örnek:
L1d cache: 384 KiB (8 instances)
L1i cache: 256 KiB (8 instances)
L2 cache: 4 MiB (8 instances)
L3 cache: 32 MiB (2 instances)Tek satırda cache bilgisi:
cat /proc/cpuinfo | grep -m1 cacheÖzet
- Bellek hiyerarşisi, hız ve maliyet arasındaki dengeyi yönetir.
- Register’lar en hızlı ve en pahalı; disk en yavaş ve en ucuz.
- SRAM (cache) hızlı ve pahalı; DRAM (RAM) yavaş ve ucuz.
- Cache line’lar (64 byte) ve locality prensibi, cache verimliliğinin anahtarıdır.
- Programların performansı, büyük ölçüde bu hiyerarşiyi ne kadar verimli kullandıklarına bağlıdır.
- Cache miss, CPU pipeline’ını duraksatır; bu konuyu 5. bölümde işleyeceğiz.
- TLB, sanal bellek çevirisini hızlandırır; sayfa tablolarının detayları 9. bölümde ele alınacak.
Artık CPU’nun talimatları nasıl yürüttüğünü, register’ların ne kadar hızlı olduğunu ve neden RAM’e ihtiyaç duyduğunu daha iyi biliyoruz. Bellek hiyerarşisinin farkında olarak cache-friendly kod yazabilir ve sisteminin cache yapılandırmasını inceleyebilirsin. Bir sonraki bölümde, işletim sisteminin birden fazla programı nasıl aynı anda çalıştırdığını göreceğiz.
4. bölüme devam et: Zamanı Dilimle