LEVEL 11
অ্যাডভান্সড আর্কিটেকচার ও পারফরম্যান্স
Advanced Architecture & Performance
এই মডিউল যে প্রশ্নের উত্তর দেয়একই algorithm, একই complexity — তবু একটা ১০ গুণ দ্রুত কেন?
এখানে আমরা "কাজ করে" থেকে "কত দ্রুত এবং কেন" -তে যাই। Cache coherence protocol, memory ordering, false sharing, SIMD, GPU-র SIMT model — আর সবচেয়ে গুরুত্বপূর্ণ: সঠিকভাবে measure করতে শেখা।
লেসন
- 01Microarchitecture Overview — একই ISA, ভিন্ন ভিন্ন ভেতরের গল্পMicroarchitecture হলো একটা ISA-র নির্দিষ্ট হার্ডওয়্যার বাস্তবায়ন — frontend (fetch, decode, branch prediction), backend (out-of-order execution engine), আর retirement (ROB-এর program-order commit), এই তিনটা নামকরণকৃত অংশ, যাদের ভেতরের ডিজাইন সিদ্ধান্তই ঠিক করে দেয় একই কোড কেন একেক CPU-তে একেক গতিতে চলে।
- 02Cache Hierarchy — Inclusive, Exclusive, আর মাঝামাঝিএকাধিক cache level (L1 private, L2 প্রায়ই private, L3 shared) একসাথে কাজ করার সময় একটা design সিদ্ধান্ত নিতে হয় — ইনক্লুসিভ (প্রতিটা outer level inner level-এর সব ধরে রাখে, coherence checking সহজ কিন্তু capacity নষ্ট), এক্সক্লুসিভ (প্রতিটা line ঠিক এক level-এ, বেশি effective capacity কিন্তু eviction জটিল), আর নন-ইনক্লুসিভ (বাস্তবসম্মত মাঝামাঝি) — এই সিদ্ধান্তই পরের লেসনের cache coherence protocol-এর কার্যকারিতাকে সরাসরি প্রভাবিত করে।
- 03Cache Coherence ও MESI Protocol — সবার cache একমত থাকার নিয়মএকাধিক core-এর প্রতিটার নিজস্ব private cache থাকায় একই memory address-এর ভিন্ন কপি ভিন্ন core-এ একসাথে থাকতে পারে — cache coherence protocol (MESI: Modified/Exclusive/Shared/Invalid) সেই কপিগুলোকে bus/interconnect message দিয়ে সমন্বিত রাখে, প্রতিটা লেখাকে অন্য সব কপি invalidate করতে বাধ্য করে — আর এই সমন্বয়ের real, non-zero খরচই পরের লেসনের false sharing সমস্যার মূল কারণ।
- 04False Sharing — যখন সম্পূর্ণ ভিন্ন দুটো variable-ও একে অপরকে ধীর করে দেয়দুটো সম্পূর্ণ আলাদা variable, দুটো আলাদা thread, কোনো true data dependency নেই — তবু ১০ গুণ ধীর। কারণ একটাই: তারা কাকতালীয়ভাবে একই ৬৪-বাইট cache line-এ পড়ে গেছে, আর গত লেসনের MESI protocol সেই line-টাকে প্রতিটা write-এ দুই core-এর মধ্যে ping-pong করাতে বাধ্য। এই লেসনের কেন্দ্রে আছে একটা measured সংখ্যা আর তার সমাধান — padding।
- 05NUMA Topology — যখন 'memory' একটা একক জিনিস থাকে নাএকটা multi-socket সার্ভারে প্রতিটা CPU socket-এর নিজস্ব, সরাসরি সংযুক্ত memory bank আছে — নিজের bank পড়া দ্রুত, পাশের socket-এর bank পড়তে হলে একটা interconnect পার হতে হয়, যা মাপা যায় এমন বাড়তি latency যোগ করে। এই লেসনে আমরা দেখব কেন 'RAM' একটা uniform জিনিস না বড় সার্ভারে, আর কীভাবে thread/memory affinity দিয়ে সেই অসমতাকে নিজের পক্ষে ব্যবহার করা যায় — নাহলে নীরবে ৩০-৫০% throughput হারানো সহজ।
- 06Memory Consistency Models — coherence যথেষ্ট নয়, ক্রমও লাগেগত দুই লেসনে আমরা দেখেছি ডেটা কোথায় বসে (NUMA) আর কীভাবে একই address সব core-এ সামঞ্জস্যপূর্ণ থাকে (coherence, আগের লেসনে)। কিন্তু একটা সম্পূর্ণ ভিন্ন প্রশ্ন বাকি: যখন একটা core দুইটা ভিন্ন address-এ লেখে, অন্য core কি সেই দুইটা লেখা একই ক্রমে দেখে? উত্তর — বাস্তব হার্ডওয়্যারে, প্রায়ই না। এই লেসনে sequential consistency, x86-এর TSO, আর ARM-এর weak memory model — আর কীভাবে C++11-এর memory_order দিয়ে এই সবকিছু portable ভাষায় প্রকাশ করা যায়।
- 07Atomics ও Lock-Free Programming — CAS দিয়ে lock ছাড়াই ডেটা স্ট্রাকচারfutex লেসনে দেখেছিলাম mutex কীভাবে futex-এর উপর বানানো হয়। আজ আরও একধাপ নিচে নামব — সেই futex/spinlock নিজেই কীভাবে একটা raw atomic CAS instruction থেকে বানানো, আর সেই একই CAS দিয়ে কীভাবে সম্পূর্ণ lock-free ডেটা স্ট্রাকচার (একটা stack) বানানো যায়, কোনো lock বা blocking ছাড়াই। কেন্দ্রে থাকবে দুইটা জিনিস — progress guarantee-র আনুষ্ঠানিক টায়ার, আর একটা genuinely subtle, বাস্তব bug class: ABA problem।
- 08Speculative Execution — গতির পেছনে লুকানো নিরাপত্তা ফাঁকMisprediction হলে CPU speculative কাজ 'যেন কখনো ঘটেইনি' এভাবে ফেলে দেয় — কিন্তু শুধু register আর memory-র জন্য। Cache-এ যে ছাপ পড়ে যায় তা থেকেই যায়, আর সেটাই Spectre ও Meltdown-এর ভিত্তি।
- 09Prefetching — ডেটা লাগার আগেই নিয়ে আসাCPU আপনার memory access history দেখে অনুমান করে পরে কী লাগবে আর সেটা আগেভাগেই cache-এ এনে রাখে — কিন্তু এই অনুমান শুধু predictable pattern-এই কাজ করে, pointer chasing-এ সম্পূর্ণ ভেঙে পড়ে।
- 10SIMD Programming — হাতে-লেখা AVX2 আর NEON কোডSIMD-র ইতিহাস আর ধারণা আগেই দেখা হয়েছে — এবার হাতে সত্যিকারের AVX2/NEON intrinsics লিখে, compiler-এর auto-vectorization-এর সাথে তুলনা করে, আর AoS/SoA-এর মতো বাস্তব data-layout সিদ্ধান্ত নিয়ে দেখা হবে।
- 11GPU আর্কিটেকচার — হাজারো সরল কোরের জগৎCPU-তে কয়েকটা জটিল, out-of-order কোর; GPU-তে হাজার হাজার সরল, in-order কোর — একই 'বেশি কাজ দ্রুত করা' সমস্যার সম্পূর্ণ ভিন্ন সমাধান। SM, warp, SIMT, warp divergence, আর GPU memory hierarchy।
- 12CUDA প্রোগ্রামিং মডেল — হার্ডওয়্যারকে কোড দিয়ে address করাএকটা `__global__` kernel, `<<<numBlocks, blockSize>>>` launch, আর `blockIdx.x * blockDim.x + threadIdx.x` — CUDA প্রোগ্রামিং-এর সবচেয়ে গুরুত্বপূর্ণ লাইন। সম্পূর্ণ vector-add উদাহরণ, শেয়ার্ড মেমরি, আর OpenCL-এর সাথে তুলনা।
- 13Parallel Patterns — Map, Reduce, ScanMAP (স্বাধীন, trivially parallel), REDUCE (associative combine, tree দিয়ে log n depth), SCAN (দেখতে সিরিয়াল, কিন্তু Hillis-Steele দিয়ে log n depth) — তিনটা reusable pattern যা দিয়ে বেশিরভাগ বাস্তব parallel প্রোগ্রাম বানানো হয়, single GPU থেকে পুরো data center পর্যন্ত।
- 14Amdahl ও Gustafson-এর সূত্র — সমান্তরালতার সীমাএকটা প্রোগ্রামের p ভাগ সমান্তরাল করা গেলেও, speedup = 1/((1−p)+p/N) — আর N যত বড়ই হোক, এটা কখনো 1/(1−p)-এর বেশি হতে পারে না। Gustafson's Law প্রশ্নটাই পাল্টে দেয়: সমস্যার আকার যদি বাড়ে?
- 15Roofline Model — Compute না Memory Bandwidth, কোনটা আপনাকে থামাচ্ছেএকটাই log-log প্লট যা বলে দেয় আপনার program compute দিয়ে আটকাচ্ছে না memory bandwidth দিয়ে — আর ভুল দিকে optimize করলে কেন সময় নষ্ট হয় তা সংখ্যা দিয়ে দেখায়।
- 16Profiling — অনুমান না করে সত্যিকার Bottleneck মাপাগত ১৫টা লেসন ধরে যা তত্ত্বে আলোচনা করেছি — cache miss, branch misprediction, IPC — এই লেসনে সেগুলোকে বাস্তব সংখ্যায় পরিণত করা শেখা: `perf stat`, `perf record`+flamegraph, আর তাদের নিচে বসে থাকা PMU hardware counter দিয়ে।
- 17Benchmarking Methodology — যেখানে ভুল দাবি জন্ম নেয়, আর যেভাবে ঠেকানো যায়বেঞ্চমার্কিং-এ যেসব ভুল বারবার হয় — warm-up ভুলে যাওয়া, wall-clock/CPU time গুলিয়ে ফেলা, noise না মেপে একটা run বিশ্বাস করা, আর compiler dead-code elimination — প্রতিটার সঠিক প্রতিকার, আর এখানেই এই ১৭-লেসনের module একত্রিত হয় একটা প্রশ্নে: একটা performance claim সত্যিই প্রতিরক্ষাযোগ্য কি না।
যা যা থাকছে
- Microarchitecture — frontend, backend, retirement
- Cache hierarchy L1/L2/L3 ও inclusive/exclusive
- Cache coherence — MESI, MOESI
- False sharing
- NUMA topology ও memory affinity
- Memory consistency models ও memory barriers
- Atomics ও lock-free programming
- Branch prediction ও speculative execution
- Prefetching
- SIMD programming (AVX2/AVX-512, NEON)
- GPU architecture — SM, warp, SIMT
- CUDA/compute programming model
- Parallel patterns — map, reduce, scan
- Amdahl ও Gustafson
- Roofline model
- Profiling — perf, flamegraph, PMU counters
- Benchmarking methodology ও statistical rigor
প্রজেক্ট
Cache Effect Measurement
●●●○○Stride access দিয়ে cache line size ও hierarchy নিজে measure করা।
Matrix Multiply Optimization
●●●●○Naive → tiled → SIMD → threaded, প্রতিটা ধাপে GFLOPS।
Lock-free Queue
●●●●●CAS-based MPSC queue, ABA problem সহ।