10.1 Önbellek Yerelliği (Cache Locality) Mimarisi

Modern işlemcilerde bellek hızı, işlemci hızının çok gerisinde kalmıştır. Bu uçurumu kapatmak için Önbellek Hiyerarşisi (Cache Hierarchy - L1, L2, L3) kullanılır. Verimli bir C++ programı, Önbellek Iskalalarını (Cache Misses) minimize etmeli ve veriyi bellekte ardışık (contiguous) tutmalıdır.

Mekansal Yerellik (Spatial Locality)

Bir veri adresine erişildiğinde, ona yakın adreslerdeki verilerin de önbelleğe alınmasıdır. Diziler (Arrays) ve `std::vector` bu konuda mükemmeldir; bağlı listeler (Linked Lists) ise kötüdür.

Zamansal Yerellik (Temporal Locality)

Erişilen bir veriye yakın zamanda tekrar erişileceği varsayımıdır. Döngülerin (Loops) verimli kurgulanması bu prensibe dayanır.

10.2 Derleyici Optimizasyon Akışı

graph LR Source[C++ Kaynak Kod] -->|O0: No Opt| D[Debug Mode] Source -->|O2: Balanced| R[Release Mode] Source -->|O3: Aggressive| P[HPC Mode] subgraph "Teknikler" Inlining[Satır İçi Genişletme - Function Inlining] LoopUnroll[Döngü Çözme - Loop Unrolling] Vectorization[Vektörizasyon - SIMD] end P --> Inlining P --> LoopUnroll P --> Vectorization

Şema 10.1: Derleme Zamanı Optimizasyon Stratejileri

10.3 Uygulama: Cache-Friendly Veri İşleme

cache_locality_analysis.cpp
#include <iostream>
#include <vector>
#include <chrono>

/**
 * @brief Akademik Analiz: Satır ve Sütun Bazlı Matris Erişimi
 * @details Önbellek satırı (Cache Line) kavramının performans üzerindeki etkisi.
 */
const int BOYUT = 10000;
int matris[BOYUT][BOYUT];

void verimli_erisim() {
    // Satır bazlı erişim: Önbellek dostudur (Cache-friendly)
    for (int i = 0; i < BOYUT; ++i) {
        for (int j = 0; j < BOYUT; ++j) {
            matris[i][j] = 1; 
        }
    }
}

void verimsiz_erisim() {
    // Sütun bazlı erişim: Sürekli önbellek ıskalaması (Cache miss) yaratır
    for (int j = 0; j < BOYUT; ++j) {
        for (int i = 0; i < BOYUT; ++i) {
            matris[i][j] = 2; 
        }
    }
}

int main() {
    // Profiling: Zaman ölçümü (Micro-benchmarking)
    auto t1 = std::chrono::high_resolution_clock::now();
    verimli_erisim();
    auto t2 = std::chrono::high_resolution_clock::now();
    
    std::cout << "Verimli sure: " 
              << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() 
              << "ms\n";

    return 0;
}

Mimarın Analizi:

C++'da çok boyutlu diziler bellekte satır satır saklanır. Bu yüzden iç döngüde sütunları (j) artırmak, bellekte ardışık ilerlemeyi sağlar. Sütun bazlı erişim ise her adımda bir sonraki satıra atlar; bu da işlemcinin her defasında ana bellekten (RAM) veri beklemesine (Stall) neden olur. Akademik ölçümlerde bu fark 10-20 kat performans değişimine yol açabilir.

Profiling Araçları:

Valgrind (Cachegrind) ile önbellek ıskalamalarını, GDB ile çalışma zamanı hatalarını ve AddressSanitizer (ASan) ile bellek taşmalarını profesyonelce analiz edebiliriz.

⚠️ Erken Optimizasyon ve Yanılgılar

Erken Optimizasyon (Premature Optimization): Donald Knuth'un dediği gibi: "Erken optimizasyon tüm kötülüklerin anasıdır." Önce çalışan ve temiz bir kod yazın, ardından profil oluşturucu (profiler) sonuçlarına göre darboğazları (bottlenecks) giderin.
Yanıltıcı Kıyaslama (Bad Benchmarking): Derleyicinin "unused" (kullanılmayan) değişkenleri tamamen silerek testi geçersiz kılmasını göz ardı etmek. Ölçüm yaparken optimizasyon bayraklarına dikkat edilmelidir.

10.5 Performans Bilgi Ölçümü

Soru: 'Önbellek Iskalası' (Cache Miss) ne anlama gelir?

Pratik Görev (Telegram Challenge):

"trcpp-telegram topluluğunda 'Small Vector Optimization' (SVO) konusu tartışılmaktadır. Küçük miktardaki verileri yığında (stack), büyük verileri öbekte (heap) tutarak performans kazanan bir yapı tasarlamanın mimari avantajlarını araştırın."