এই পর্বে যা শিখবেন
- Memory array, row আর column decoder, word line, bit line আর sense amplifier দিয়ে একটি chip কীভাবে একটি বিট খুঁজে পায়
- SRAM-এর 6T cell আর DRAM-এর 1T1C cell — কীভাবে পড়া হয়, কেন DRAM-এর পড়া ধ্বংসাত্মক আর refresh-এর খরচ কত
- Row buffer, ACTIVATE-READ-PRECHARGE, tRCD, tCL, tRP, tRAS; row hit, miss আর conflict; DRAM-এর channel থেকে column পর্যন্ত সংগঠন আর address mapping
- DDR spec পড়া (MT/s, CL) আর latency ও bandwidth-এর হিসাব; DDR3–DDR5, LPDDR, GDDR, HBM; interleaving-এর miss penalty আর memory controller
- Parity আর SECDED ECC, Rowhammer আর তার প্রতিরক্ষা, ROM-PROM-EPROM-EEPROM, NOR ও NAND flash, SSD আর সামনের দিনের মেমরি
১ · মেমরি chip-এর ভেতরের ছক — array, decoder, word line আর bit line
পর্ব ৪৪-এ দেখেছেন, মেমরি হায়ারার্কির ওপরে ছোট আর দ্রুত cache, নিচে বড় আর ধীর main memory. পর্ব ৪৫–৪৮-এ দেখেছেন, cache কীভাবে ঠিকানা ভাগ করে আর কখন miss হয়। কিন্তু miss হলে ডেটা আসে কোথা থেকে? এই পর্বে সেই নিচের তলায় নামব — একটি মেমরি chip-এর ভেতর থেকে শুরু করে পুরো মেমরি-ব্যবস্থা পর্যন্ত।
যেকোনো মেমরি chip — SRAM, DRAM বা flash — মূলত একই নকশায় সাজানো: একটি বিশাল ছক, যাকে বলে memory array. ছকের প্রতিটি ঘরে একটি bit cell, যা একটি বিট রাখে। প্রতিটি সারির সব cell একটি অনুভূমিক তারে যুক্ত — word line. প্রতিটি কলামের সব cell একটি খাড়া তারে যুক্ত — bit line. একটি word line চালু করলে সেই সারির প্রতিটি cell নিজের কলামের bit line-এর সাথে যুক্ত হয়, আর একসাথে পুরো সারির মান bit line-গুলোতে চলে আসে।
একটি বড় লাইব্রেরির তাক ভাবুন। প্রতিটি তাক একটি সারি, প্রতিটি তাকে পাশাপাশি অনেক বই। লাইব্রেরিয়ান আগে ক্যাটালগ দেখে বলেন “তাক নম্বর ৫”, সহকারী পুরো তাকটি নামিয়ে টেবিলে রাখেন (সারি খোলা), তারপর লাইব্রেরিয়ান টেবিল থেকে “বাঁ দিক থেকে ৭১৯ নম্বর বই” তুলে দেন (কলাম বাছা)। একই তাকের আরেকটি বই চাইলে টেবিলেই আছে — খুব দ্রুত। অন্য তাকের বই চাইলে আগের তাক তুলে রাখা, তারপর নতুনটি নামানো — অনেক ধীর। DRAM ঠিক এভাবেই চলে, আর এই পর্বের অর্ধেক হিসাব এই উপমা থেকেই আসে।
ঠিকানাকে তাই দুই ভাগ করা হয়। ওপরের বিটগুলো যায় row decoder-এ — পর্ব ১২-এর decoder, যা n বিট ঠিকানা থেকে ২nটি word line-এর ঠিক একটিকে চালু করে। নিচের বিটগুলো যায় column decoder বা column mux-এ, যা খোলা সারির হাজার বিটের মধ্য থেকে দরকারি কয়েকটি বেছে বাইরে পাঠায়। কেন দুই ভাগ? শত শত কোটি cell-কে একটি একক decoder দিয়ে বাছতে হলে অসম্ভব বড় circuit লাগত; সারি আর কলামে ভাগ করলে দুটি ছোট decoder-এই হয় — ঠিক মহল্লার “গলি নম্বর” আর “বাড়ি নম্বর”-এর মতো।
বাস্তব chip-এ একটি বড় array-কে আবার অনেক ছোট “mat” বা sub-array-তে ভাঙা হয়, কারণ লম্বা তারের resistance আর capacitance বেশি, ফলে সংকেত ধীর হয় (পর্ব ১৮-এর delay-এর হিসাব মনে করুন)। তবে ধারণা একই: সারি খোলা, কলাম বাছা। এই একই ছক দিয়ে CPU-র register file থেকে শুরু করে বহু গিগাবাইটের DRAM পর্যন্ত সব তৈরি — পার্থক্য শুধু প্রতিটি ঘরের ভেতরের cell-এ।
২ · SRAM আর DRAM-এর cell — ছয় transistor বনাম এক transistor আর এক capacitor
SRAM — দুই inverter-এর আলিঙ্গন
পর্ব ১৫-এর latch মনে করুন: দুটি gate-কে একে অন্যের input-এ জুড়ে দিলে একটি স্থির অবস্থা তৈরি হয়, যা নিজেকে নিজেই ধরে রাখে। SRAM (Static RAM)-এর cell ঠিক তাই — দুটি inverter মুখোমুখি জোড়া (cross-coupled): প্রথমটির output দ্বিতীয়টির input, দ্বিতীয়টির output প্রথমটির input. যদি Q = 1 হয়, তাহলে দ্বিতীয় inverter Q′ = 0 দেয়, যা প্রথম inverter-কে আবার Q = 1 দিতে বাধ্য করে। বিদ্যুৎ থাকা পর্যন্ত এই অবস্থা অটুট — তাই “static”.
পর্ব ০৮-এর CMOS inverter-এ দুটি transistor (একটি pMOS, একটি nMOS). দুটি inverter মানে ৪টি। আর পড়া-লেখার জন্য দুটি access transistor, যাদের gate word line-এ যুক্ত — word line চালু হলে Q আর Q′ যথাক্রমে bit line BL আর BL′-এর সাথে জুড়ে যায়। মোট ৬টি: এটিই বিখ্যাত 6T SRAM cell.
DRAM — একটি ছোট বালতিতে চার্জ
DRAM (Dynamic RAM)-এর cell অনেক সরল: একটি transistor আর একটি capacitor (1T1C). Capacitor-এ চার্জ থাকলে 1, না থাকলে 0. Transistor-টি একটি দরজা: word line চালু হলে capacitor bit line-এর সাথে যুক্ত হয়। এক বিটে ১টি transistor বনাম ৬টি — তাই একই জায়গায় DRAM অনেক গুণ বেশি বিট ধরে, প্রতি বিটের দাম অনেক কম। এটাই কারণ যে আপনার ল্যাপটপে কয়েক MB cache (SRAM) আর কয়েক GB main memory (DRAM).
কিন্তু DRAM-এর এই সরলতার দাম আছে, দুটি। প্রথমত, capacitor খুবই ছোট (কয়েক দশ femtofarad-এর মতো বলে উল্লেখ পাওয়া যায়), আর bit line তার চেয়ে অনেক বড় — অনেক cell-এর সাথে যুক্ত লম্বা তার। Word line চালু হলে cell-এর চার্জ bit line-এর সাথে ভাগ হয়ে যায় (charge sharing), ফলে bit line-এর ভোল্টেজ সামান্য একটু ওঠে বা নামে। এই ক্ষুদ্র পরিবর্তন ধরতে লাগে একটি sense amplifier, যা bit line-কে একটি reference (সাধারণত VDD/2-তে আগে থেকে রাখা) মানের সাথে তুলনা করে পুরো 0 বা VDD-তে টেনে নেয়। আর চার্জ ভাগ হয়ে গেছে বলে cell-এর আসল মান নষ্ট — এটি destructive read. তাই sense amplifier পূর্ণ মানটি আবার cell-এ লিখে দেয় (restore).
দ্বিতীয়ত, capacitor-এর চার্জ ধীরে ধীরে চুইয়ে যায় (leakage) — এক বালতি পানি, যার তলায় সূক্ষ্ম ফুটো। তাই নির্দিষ্ট সময় পরপর প্রতিটি সারি পড়ে আবার লিখতে হয়: refresh. এই “dynamic” শব্দটি সেখান থেকেই। নিচের stepper-এ দুটি cell পাশাপাশি পড়া দেখুন।
| ধাপ | |
| SRAM | |
| DRAM |
- মান ধরে রাখা। SRAM cell-এ Q = 1 আর Q′ = 0; দুটি inverter একে অন্যকে সমর্থন দিয়ে এই অবস্থা সক্রিয়ভাবে ধরে রাখে। DRAM cell-এ capacitor-এ চার্জ আছে, মানে 1 — কিন্তু কোনো circuit তা ধরে রাখছে না, চার্জ ধীরে চুইয়ে যাচ্ছে।
- Bit line precharge. পড়ার আগে SRAM-এর দুটি bit line (BL আর BL′) VDD-তে তোলা হয়। DRAM-এর bit line রাখা হয় ঠিক মাঝখানে, VDD/2-তে — যাতে cell-এর চার্জ এলে ওপরে, না এলে নিচে সরে।
- Word line চালু। SRAM-এ M5, M6 খোলে; Q′ = 0 দিকের inverter BL′-কে একটু নামিয়ে আনে (ε), BL প্রায় VDD-তে থাকে। DRAM-এ capacitor bit line-এর সাথে যুক্ত হয়; চার্জ ভাগ হয়ে bit line সামান্য ওঠে (δ), আর capacitor-এর চার্জ পাতলা হয়ে যায়।
- Sense. দুই ক্ষেত্রেই sense amplifier ছোট পার্থক্যটি বাড়িয়ে পরিষ্কার 1 করে। SRAM দুটি bit line-এর মধ্যে তুলনা করে (differential); DRAM bit line-কে VDD/2-এর reference-এর সাথে তুলনা করে VDD পর্যন্ত টেনে নেয়।
- পড়ার পরে। SRAM-এর cell একটুও বদলায়নি — non-destructive. DRAM-এর capacitor-এর চার্জ পড়ার সময় ভেঙে গিয়েছিল; word line তখনো খোলা, তাই sense amplifier-এর VDD আবার capacitor-এ ঢুকে মান ফিরিয়ে দেয় (restore). এই restore-এর সময় পরের অংশের tRAS-এর একটি কারণ।
- সময় গেলে। SRAM-এর মান বিদ্যুৎ থাকা পর্যন্ত থাকে। DRAM-এর চার্জ কমতে থাকে; একটি নির্দিষ্ট সময়ের (DDR4-এ সাধারণত ৬৪ ms) মধ্যে refresh না হলে মান হারানোর ঝুঁকি। তাই DRAM-কে নিয়মিত সারি ধরে ধরে পড়ে আবার লিখতে হয়।
Refresh-এর খরচ কত?
DDR3 আর DDR4-এ সাধারণ তাপমাত্রায় নিয়ম হলো, প্রতিটি সারি প্রায় ৬৪ ms-এর মধ্যে একবার refresh হবে (খুব গরমে, প্রায় ৮৫°C-এর ওপরে, অর্ধেক সময়ে; DDR5-এ সাধারণত ৩২ ms বলে উল্লেখ পাওয়া যায়)। Controller একবারে একটি সারি নয়, একটি REFRESH command পাঠায়; chip নিজে ভেতরে কয়েকটি সারি refresh করে। ধরুন ৬৪ ms-এ ৮১৯২টি REFRESH command দিতে হবে। তাহলে দুটি command-এর মাঝের সময় tREFI = ৬৪ ms ÷ ৮১৯২ = ৭৮১২.৫ ns ≈ ৭.৮ µs. প্রতিটি REFRESH চলাকালে chip অন্য কাজ নিতে পারে না — এই সময়ের নাম tRFC. উদাহরণ মান হিসেবে tRFC = ৩৫০ ns ধরলে (একটি ৮ Gb DDR4 chip-এর জন্য এমন মান উল্লেখ পাওয়া যায়), মেমরি সময়ের ৩৫০ ÷ ৭৮১২.৫ ≈ ৪.৪৮% ব্যস্ত থাকে শুধু refresh-এ। পুরোনো ছোট chip-এ (tRFC = ১৬০ ns) তা ২.০৫%. আর সরল পাঠ্যবইয়ের মডেলে — ৮১৯২টি সারি, প্রতিটি refresh ৫০ ns — ৬৪ ms-এ ৪০৯.৬ µs, মাত্র ০.৬৪%.
tREFI = refresh window ÷ REFRESH command-এর সংখ্যা; refresh-এর খরচ (সময়ের ভগ্নাংশ) = tRFC ÷ tREFI. Chip যত বড় (বিট বেশি), tRFC তত বাড়ে — তাই refresh-এর খরচ প্রতিটি প্রজন্মে একটি বড় সমস্যা হয়ে উঠছে। এই সংখ্যাগুলো অংশ ৫-এর calculator-এ চালিয়ে মেলানো।
| বৈশিষ্ট্য | SRAM | DRAM |
|---|---|---|
| প্রতি বিটে | ৬টি transistor | ১টি transistor + ১টি capacitor |
| পড়া | non-destructive | destructive — restore লাগে |
| Refresh | লাগে না | লাগে (প্রায় ৬৪ ms-এ প্রতিটি সারি) |
| গতি | দ্রুত — chip-এর ভেতরে মাত্র কয়েক cycle | ধীর — CPU থেকে মোটামুটি কয়েক দশ থেকে ১০০ ns-এর ঘরে, যন্ত্রভেদে আলাদা |
| ঘনত্ব আর দাম | কম ঘন, প্রতি বিটে দামি | অনেক ঘন, প্রতি বিটে সস্তা |
| তৈরি | সাধারণ logic process — CPU chip-এর ভেতরেই | আলাদা বিশেষ process, আলাদা chip |
| ব্যবহার | register file, L1–L3 cache, TLB | main memory, GPU-র মেমরি |
৩ · Row buffer আর DRAM-এর timing — ACTIVATE, READ, PRECHARGE
DRAM-এর sense amplifier-এর সারিটি একটি গুরুত্বপূর্ণ জিনিস: সারি খোলার পর পুরো সারির মান সেখানে ধরা থাকে। একে বলে row buffer (বা “page”; OS-এর page-এর সাথে গুলিয়ে ফেলবেন না)। একটি DDR4 x8 chip-এ এক সারি প্রায় ১ KB; একটি rank-এর ৮টি chip একসাথে কাজ করে, তাই rank-এর একটি খোলা সারি প্রায় ৮ KB. ৬৪ byte-এর একটি cache line এর ক্ষুদ্র একটি অংশ মাত্র।
পুরোনো DRAM-এ ঠিকানা দুই কিস্তিতে দেওয়া হতো, দুটি সংকেত দিয়ে — RAS আর CAS (Row/Column Address Strobe): একই pin-গুলো দিয়ে আগে সারির ঠিকানা, পরে কলামের ঠিকানা, যাতে chip-এর pin অর্ধেক লাগে। আজকের DDR-এ এগুলো command-এর রূপ নিয়েছে, কিন্তু নাম আর ধারণা রয়ে গেছে:
- ACTIVATE (সারি খোলা, পুরোনো RAS): row decoder একটি word line চালু করে, sense amplifier সারিটি row buffer-এ আনে। এরপর কলাম পড়তে অপেক্ষা tRCD.
- READ / WRITE (কলাম, পুরোনো CAS): row buffer থেকে কলাম বেছে ডেটা পাঠানো। READ থেকে প্রথম ডেটা পর্যন্ত CAS latency (CL বা tCL); তারপর একটি burst-এ পরপর কয়েকটি transfer.
- PRECHARGE (সারি বন্ধ): word line বন্ধ, bit line আবার VDD/2-তে। একই bank-এ নতুন সারি খোলার আগে অপেক্ষা tRP. আর সারি খোলার পর অন্তত tRAS সময় না গেলে PRECHARGE দেওয়া যায় না — restore শেষ হওয়া চাই। tRC = tRAS + tRP — একই bank-এ দুটি ACTIVATE-এর ন্যূনতম ব্যবধান।
DDR মেমরির লেবেলে “22-22-22-52” ধরনের যে সংখ্যা দেখেন, সেগুলো এই ক্রমে: CL-tRCD-tRP-tRAS, সব clock cycle-এ. নিচের stepper-এ একটি উদাহরণ chip: DDR4-3200, 22-22-22-52 — এক clock = ০.৬২৫ ns.
| command | |
| cycle | |
| word line | |
| bit line | |
| row buffer |
- Bank precharged. কোনো word line চালু নেই, সব bit line VDD/2-তে, row buffer খালি। Controller-এর কাছে একটি অনুরোধ এসেছে: bank 2, row 2330, column 719 (এই ঠিকানা কোথা থেকে এল, তা অংশ ৪-এ)।
- ACTIVATE. Cycle ০-তে controller row 2330-এর ঠিকানাসহ ACTIVATE পাঠায়। Row decoder word line চালু করে; সারির প্রতিটি cell-এর চার্জ নিজের bit line-এ ভাগ হয়ে সামান্য (±δ) সরিয়ে দেয়।
- Sense amplifier কাজ করে — tRCD. Sense amplifier-রা প্রতিটি bit line-কে পুরো 0 বা VDD-তে টেনে নেয়; একই সাথে মান cell-এ restore হতে থাকে। tRCD = ২২ cycle = ১৩.৭৫ ns পরে, অর্থাৎ cycle ২২-এ, সারিটি পড়ার উপযোগী।
- READ — tCL. Cycle ২২-এ READ column 719. Column mux দরকারি বিটগুলো বাছে; CL = ২২ cycle পরে, cycle ৪৪-এ প্রথম ডেটা বের হয়, আর burst length ৮-এর ৮টি transfer DDR-এ ৪ cycle-এ শেষ (৪৪–৪৮)। ACTIVATE থেকে প্রথম ডেটা: ৪৪ × ০.৬২৫ = ২৭.৫ ns.
- Row hit. একই সারির আরেকটি অংশ (column 727) চাই। সারি তো খোলাই — ACTIVATE লাগবে না। ধরা যাক READ যায় cycle ৩০-এ; ডেটা আসে ২২ cycle পরে, ৫২–৫৬-এ। এটাই row hit-এর লাভ: খরচ শুধু tCL.
- PRECHARGE — tRAS আর tRP. এবার অন্য সারির অনুরোধ এলে খোলা সারি বন্ধ করতে হবে। ACTIVATE-এর পরে অন্তত tRAS = ৫২ cycle যেতে হবে (restore শেষ), আর ডেটাও বের হওয়া চাই; ধরা যাক PRECHARGE cycle ৫৬-এ। tRP = ২২ পরে, cycle ৭৮-এ bank নতুন ACTIVATE নিতে প্রস্তুত। ন্যূনতম tRC = ৫২ + ২২ = ৭৪ cycle = ৪৬.২৫ ns.
Row hit, miss আর conflict — open-page policy
একটি অনুরোধ যখন একটি bank-এ পৌঁছায়, তিনটি অবস্থার একটি হতে পারে:
Row hit
চাওয়া সারিটিই row buffer-এ খোলা। খরচ: tCL. সবচেয়ে দ্রুত।
Row miss (bank বন্ধ)
Bank precharged, কোনো সারি খোলা নেই। খরচ: tRCD + tCL.
Row conflict
Bank-এ অন্য একটি সারি খোলা। আগে বন্ধ, তারপর খোলা, তারপর পড়া। খরচ: tRP + tRCD + tCL. সবচেয়ে ধীর।
তাহলে পড়া শেষে সারিটি খোলা রাখব, না বন্ধ করব? Open-page policy খোলা রাখে — পরের অনুরোধ একই সারিতে এলে hit, অন্য সারিতে এলে conflict. Closed-page policy প্রতিবার বন্ধ করে দেয় — কখনো hit নয়, কিন্তু কখনো conflict-ও নয়; প্রতিটি অনুরোধ miss. কোনটি ভালো, তা নির্ভর করে locality-র ওপর (পর্ব ৪৪): একটি প্রোগ্রাম লম্বা array পরপর পড়লে একই সারিতে অনেক hit — open-page জেতে; অনেক core এলোমেলো ঠিকানা পড়লে conflict বেশি — closed-page জিততে পারে। বাস্তব controller প্রায়ই মাঝামাঝি নীতি নেয় (যেমন কিছুক্ষণ অনুরোধ না এলে বন্ধ)।
নিচের simulator একটি অনুরোধের ক্রম (bank, row) নিয়ে open-page নিয়মে প্রতিটিকে hit, miss বা conflict চিহ্নিত করে, cycle যোগ করে, আর শেষে closed-page-এর সাথে তুলনা করে। সরল রাখতে অনুরোধগুলো একটির পর একটি পরিবেশিত হয় (বাস্তবে আলাদা bank-এর কাজ একসাথে চলে), আর প্রতিটির সাথে burst-এর ৪ cycle যোগ হয়।
// Open-page DRAM timing: each request is a row hit, a miss (bank closed) or a conflict (another row open)
const tRCD = 22, tCL = 22, tRP = 22, BURST = 4; // DDR4-3200 22-22-22 in clock cycles; BL8 = 4 clocks
const tCK = 0.625; // ns per clock at 1600 MHz
const trace = [[0, 5], [0, 5], [1, 9], [0, 5], [0, 7], [1, 9], [0, 7], [1, 3], [1, 3], [0, 5]]; // [bank, row]
const open = {}; // bank -> currently open row (row buffer)
const count = { hit: 0, miss: 0, conflict: 0 };
let total = 0;
console.log("req bank row result cycles = formula");
trace.forEach(([b, r], i) => {
let kind, cyc, f;
if (open[b] === r) { kind = "hit"; cyc = tCL; f = "tCL"; }
else if (open[b] === undefined) { kind = "miss"; cyc = tRCD + tCL; f = "tRCD+tCL"; }
else { kind = "conflict"; cyc = tRP + tRCD + tCL; f = "tRP+tRCD+tCL"; }
cyc += BURST; open[b] = r; count[kind]++; total += cyc;
console.log(` ${String(i).padStart(2)} ${b} ${String(r).padStart(2)} ${kind.padEnd(9)} ${String(cyc).padStart(4)} = ${f}+burst`);
});
const closed = trace.length * (tRCD + tCL + BURST); // closed-page: every access activates (precharge hidden)
console.log(`hits=${count.hit} misses=${count.miss} conflicts=${count.conflict}`);
console.log(`open-page total = ${total} cycles = ${(total * tCK).toFixed(2)} ns`);
console.log(`closed-page total = ${closed} cycles = ${(closed * tCK).toFixed(2)} ns`);আসল আউটপুট:
req bank row result cycles = formula
0 0 5 miss 48 = tRCD+tCL+burst
1 0 5 hit 26 = tCL+burst
2 1 9 miss 48 = tRCD+tCL+burst
3 0 5 hit 26 = tCL+burst
4 0 7 conflict 70 = tRP+tRCD+tCL+burst
5 1 9 hit 26 = tCL+burst
6 0 7 hit 26 = tCL+burst
7 1 3 conflict 70 = tRP+tRCD+tCL+burst
8 1 3 hit 26 = tCL+burst
9 0 5 conflict 70 = tRP+tRCD+tCL+burst
hits=5 misses=2 conflicts=3
open-page total = 436 cycles = 272.50 ns
closed-page total = 480 cycles = 300.00 ns
প্রথম অনুরোধে bank 0 বন্ধ, তাই miss: ২২ + ২২ + ৪ = ৪৮ cycle. দ্বিতীয়টি একই সারি — hit, মাত্র ২৬. অনুরোধ ২-এ bank 1 প্রথমবার, তাই miss; লক্ষ করুন bank 0-এর row 5 তখনো খোলা — আলাদা bank-এর আলাদা row buffer, তাই অনুরোধ ৩ আবার hit. অনুরোধ ৪-এ bank 0-তে row 7 চাওয়া হলো, অথচ row 5 খোলা — conflict, ৭০ cycle. মোট ৫টি hit, ২টি miss, ৩টি conflict: ৪৩৬ cycle = ২৭২.৫ ns; closed-page-এ সব ১০টি miss হলে ৪৮০ cycle = ৩০০ ns. এই ক্রমে locality ভালো, তাই open-page প্রায় ৯% এগিয়ে। Trace বদলে দেখুন: প্রতিটি অনুরোধ আগেরটির থেকে আলাদা সারিতে হলে open-page-এর প্রায় সব conflict, আর closed-page জিতবে (অনুশীলন ৩-এ এমন একটি)।
৪ · DRAM-এর সংগঠন — channel থেকে column, আর address mapping
একটি chip-এর ভেতরে একাধিক array; একটি কম্পিউটারে একাধিক chip. পুরো ব্যবস্থাটি একটি গাছের মতো স্তরে সাজানো:
- Channelcontroller থেকে স্বাধীন পথ
- DIMMslot-এ বসানো বোর্ড
- Rankএকসাথে চলা chip-দল
- Chipযেমন x8: ৮ bit চওড়া
- Bankনিজের row buffer
- Row → Columnসারি খোলা, কলাম বাছা
- Channel — memory controller থেকে একটি স্বাধীন ৬৪-bit data bus আর command bus. দুটি channel মানে একসাথে দুটি স্বাধীন কাজ, দ্বিগুণ bandwidth.
- DIMM — মাদারবোর্ডের slot-এ বসানো বোর্ড; এক channel-এ এক বা দুটি DIMM.
- Rank — DIMM-এর যে chip-গুলো একই chip-select সংকেতে একসাথে কাজ করে আর মিলে ৬৪ bit ভরায়: ৮টি x8 chip (প্রতিটি ৮ bit) বা ১৬টি x4 chip. ECC DIMM-এ আরেকটি chip যোগ হয়ে ৭২ bit (অংশ ৭)।
- Bank — প্রতিটি chip-এর ভেতরের স্বাধীন array, নিজের row buffer-সহ। DDR4 x8 chip-এ ১৬টি bank (৪টি bank group-এ ৪টি করে)। একটি rank-এর সব chip-এর একই নম্বরের bank একসাথে কাজ করে।
Address mapping — একটি ঠিকানা কোন bank, কোন সারি?
একটি উদাহরণ নিন: একটি channel, একটি rank, ৮টি DDR4 x8 chip, প্রতিটি ৮ Gb — ১৬টি bank, প্রতি bank-এ ৬৫,৫৩৬টি সারি (১৬ bit), প্রতি সারিতে ১০২৪টি কলাম (১০ bit), প্রতিটি কলামে ৮ bit. একটি chip = ১৬ × ৬৫৫৩৬ × ১০২৪ × ৮ = ২৩৩ bit = ৮ Gb; ৮টি chip মিলে rank = ৮ GB = ২৩৩ byte, তাই ৩৩ bit-এর physical address. Rank-এর প্রতিটি কলাম-ঠিকানা ৮টি chip থেকে ৮ bit করে, মোট ৮ byte (bus-প্রস্থ) দেয়। একটি সহজ mapping (ওপর থেকে নিচে):
│ row (16) │ bank (4) │ column (10) │ byte-in-bus (3) │ = 33 bit
bit 32-17 bit 16-13 bit 12-3 bit 2-0
ঠিকানা 0x12345678 নিই। byte = ঠিকানা AND 7 = ০; column = (ঠিকানা >> ৩) AND 1023 = ৭১৯; bank = (ঠিকানা >> ১৩) AND 15 = ২; row = ঠিকানা >> ১৭ = ২৩৩০ (একটি ছোট স্ক্রিপ্টে মিলিয়ে নেওয়া)। অংশ ৩-এর stepper-এর “bank 2, row 2330, column 719” এখান থেকেই এসেছে।
লক্ষ করুন, কলাম-বিট নিচে রাখায় পরপর ঠিকানাগুলো একই সারিতে থাকে — একটি ৬৪ byte cache line = ৮টি কলাম = একটি burst (BL8 × ৮ byte = ৬৪ byte), আর পরের ১২৭টি cache line-ও একই ৮ KB সারিতে, তাই একটানা পড়লে অনেক row hit. বিকল্প mapping-এ cache line-এর ঠিক ওপরের বিটে bank রাখা হয়, যাতে পরপর cache line আলাদা bank-এ যায় আর একসাথে কাজ চলে (অংশ ৬-এর interleaving). বাস্তব controller প্রায়ই bank-বিটকে row-এর কিছু বিটের সাথে XOR করে, যাতে কোনো নির্দিষ্ট stride-এ সব অনুরোধ একই bank-এ জমে conflict না বাড়ায়। এই mapping নির্মাতারা সাধারণত প্রকাশ করেন না, আর chip-ভেদে আলাদা।
৫ · SDRAM থেকে DDR5 — double data rate, prefetch আর bandwidth
১৯৯০-এর দশকের শুরু পর্যন্ত DRAM ছিল asynchronous — controller সংকেত দিত, chip নিজের গতিতে উত্তর দিত। SDRAM (Synchronous DRAM) একটি clock-এর সাথে তাল মিলিয়ে command নেয় আর ডেটা দেয়, ফলে command পাইপলাইন করা যায়; JEDEC-এর মান হিসেবে ১৯৯০-এর দশকের মাঝামাঝি এটি প্রচলিত হয়। তারপর DDR SDRAM (Double Data Rate) — clock-এর ওঠা আর নামা দুই প্রান্তেই ডেটা, তাই প্রতি clock-এ দুটি transfer. এজন্য গতি লেখা হয় MT/s-এ (megatransfers per second), MHz-এ নয়: DDR4-3200 মানে ৩২০০ MT/s, কিন্তু I/O clock ১৬০০ MHz.
কিন্তু DRAM-এর ভেতরের array তো এত দ্রুত চলে না। কৌশলটি prefetch: array থেকে একবারে অনেকগুলো বিট চওড়া পথে তুলে আনা, তারপর বাইরের সরু কিন্তু দ্রুত bus-এ একটির পর একটি পাঠানো — গার্মেন্টস কারখানায় গুদাম থেকে একবারে আট বান্ডিল কাপড় এনে লাইনে একটি একটি করে দেওয়ার মতো। DDR-এ ২n, DDR2-এ ৪n, DDR3 আর DDR4-এ ৮n, DDR5-এ ১৬n prefetch. তাই DDR4-3200-এর ভেতরের array চলে প্রায় ৩২০০ ÷ ৮ = ৪০০ MHz-এ। এর সাথে মিলে যায় burst length: DDR4-এ BL8, DDR5-এ BL16.
Spec পড়া: DDR4-3200 CL22 মানে কত ns?
I/O clock = MT/s ÷ ২; এক cycle tCK = ১০০০ ÷ clock (MHz) ns = ২০০০ ÷ MT/s ns. CAS latency (ns) = CL × tCK = CL × ২০০০ ÷ MT/s. উদাহরণ: DDR4-3200 CL22 → ২২ × ২০০০ ÷ ৩২০০ = ১৩.৭৫ ns. সর্বোচ্চ bandwidth = MT/s × bus-প্রস্থ (byte) × channel-সংখ্যা: DDR4-3200, ৬৪ bit = ৮ byte → ৩২০০ × ১০৬ × ৮ = ২৫.৬ GB/s; dual channel → ৫১.২ GB/s.
একটি মজার সত্য: CL-এর সংখ্যা প্রতিটি প্রজন্মে বাড়ে, কিন্তু ns-এ latency প্রায় একই থাকে। নিচের calculator চালিয়ে দেখুন — সাথে অংশ ২-এর refresh-এর হিসাবও।
// DDR spec -> clock, CAS latency in ns and peak bandwidth; then refresh overhead
const specs = [
{ name: "DDR4-2400 CL17", mts: 2400, cl: 17, bits: 64, ch: 1 },
{ name: "DDR4-3200 CL22", mts: 3200, cl: 22, bits: 64, ch: 1 },
{ name: "DDR4-3200 CL22 x2 ch", mts: 3200, cl: 22, bits: 64, ch: 2 },
{ name: "DDR5-4800 CL40", mts: 4800, cl: 40, bits: 64, ch: 1 }, // one DIMM = 2 x 32-bit sub-channels
{ name: "DDR5-6000 CL30 x2 ch", mts: 6000, cl: 30, bits: 64, ch: 2 }];
console.log("spec clock MHz tCK ns CAS ns peak GB/s");
for (const s of specs) {
const clk = s.mts / 2; // double data rate: 2 transfers per clock
const tck = 1000 / clk; // ns
const cas = s.cl * 2000 / s.mts; // = CL x tCK
const bw = s.mts * 1e6 * (s.bits / 8) * s.ch / 1e9;
console.log(`${s.name.padEnd(22)} ${String(clk).padStart(9)} ${tck.toFixed(3)} ${cas.toFixed(2).padStart(6)} ${bw.toFixed(1).padStart(9)}`);
}
// Refresh: every row of a bank must be refreshed once per 64 ms window
const rows = 8192, windowMs = 64;
const tREFI = windowMs * 1e6 / rows; // ns between REFRESH commands
for (const tRFC of [160, 350]) { // ns a REFRESH keeps the device busy (example values)
console.log(`rows=${rows} window=${windowMs} ms -> tREFI=${tREFI.toFixed(1)} ns, tRFC=${tRFC} ns -> busy ${(100 * tRFC / tREFI).toFixed(2)}%`);
}
const perRow = 50; // simple model: refresh one row at a time, 50 ns each
console.log(`row-by-row: ${rows} x ${perRow} ns = ${(rows * perRow / 1000).toFixed(1)} us per ${windowMs} ms = ${(100 * rows * perRow / (windowMs * 1e6)).toFixed(2)}%`);আসল আউটপুট:
spec clock MHz tCK ns CAS ns peak GB/s
DDR4-2400 CL17 1200 0.833 14.17 19.2
DDR4-3200 CL22 1600 0.625 13.75 25.6
DDR4-3200 CL22 x2 ch 1600 0.625 13.75 51.2
DDR5-4800 CL40 2400 0.417 16.67 38.4
DDR5-6000 CL30 x2 ch 3000 0.333 10.00 96.0
rows=8192 window=64 ms -> tREFI=7812.5 ns, tRFC=160 ns -> busy 2.05%
rows=8192 window=64 ms -> tREFI=7812.5 ns, tRFC=350 ns -> busy 4.48%
row-by-row: 8192 x 50 ns = 409.6 us per 64 ms = 0.64%
DDR4-2400 CL17 আর DDR4-3200 CL22 — CL সংখ্যায় ৫ বেশি, কিন্তু ns-এ ১৪.১৭ থেকে মাত্র ১৩.৭৫. DDR5-4800 CL40-এর ১৬.৬৭ ns আসলে একটু বেশি, যদিও bandwidth অনেক বেশি (৩৮.৪ GB/s). দ্রুত (এবং দামি) DDR5-6000 CL30-এ CAS ঠিক ১০.০০ ns, আর দুটি channel-এ ৯৬ GB/s. শিক্ষা: প্রজন্ম বদলে bandwidth অনেক বাড়ে, latency খুব কম কমে — কারণ ভেতরের array, capacitor আর sense amplifier-এর পদার্থবিদ্যা প্রায় একই। মনে রাখবেন, এগুলো শুধু CAS-এর সময়; CPU থেকে দেখা পুরো miss latency-তে এর সাথে tRCD, সম্ভবত tRP, controller-এর সারিতে অপেক্ষা আর on-chip পথ যোগ হয় — মোটামুটি কয়েক দশ থেকে ১০০ ns-এর ঘরে, যন্ত্রভেদে আলাদা। Refresh-এর লাইনগুলো অংশ ২-এর হিসাব মেলায়: ২.০৫%, ৪.৪৮% আর ০.৬৪%.
প্রজন্মের তুলনা আর বিশেষ ধরনের DRAM
| বৈশিষ্ট্য (মোটামুটি, মানভেদে) | DDR3 | DDR4 | DDR5 |
|---|---|---|---|
| প্রচলনের সময় | প্রায় ২০০৭ | প্রায় ২০১৪ | প্রায় ২০২১ (মান ২০২০) |
| সাধারণ গতি | ৮০০–২১৩৩ MT/s | ১৬০০–৩২০০ MT/s (JEDEC) | ৪৮০০ MT/s থেকে শুরু, ক্রমে বাড়ছে |
| ভোল্টেজ | ১.৫ V | ১.২ V | ১.১ V |
| Prefetch / burst | ৮n / BL8 | ৮n / BL8 | ১৬n / BL16 |
| Bank | ৮ | ১৬ (৪টি bank group) | ৩২ (৮টি bank group) |
| DIMM-এর চ্যানেল | একটি ৬৪-bit | একটি ৬৪-bit | দুটি স্বাধীন ৩২-bit sub-channel |
| অন্যান্য | — | bank group | on-die ECC, DIMM-এ নিজস্ব power chip (PMIC) |
DDR5-এর দুটি sub-channel-এর যুক্তি: BL16 × ৩২ bit = ৬৪ byte — ঠিক একটি cache line একটি sub-channel থেকে, আর দুটি sub-channel দুটি আলাদা অনুরোধ একসাথে চালায়। DDR5-এর on-die ECC chip-এর ভেতরের ছোট ভুল সারায় (মূলত ঘন chip-এর নিজস্ব নির্ভরযোগ্যতার জন্য বলে বর্ণিত); এটি server-এর পূর্ণ ECC memory-র (অংশ ৭) বিকল্প নয় — দুটিকে গুলিয়ে ফেলা খুব সাধারণ ভুল।
LPDDR
LPDDR (Low-Power DDR) ফোন, ট্যাবলেট আর অনেক পাতলা ল্যাপটপে। কম ভোল্টেজ, গভীর ঘুমের অবস্থা, সরু (যেমন ১৬-bit) channel, আর processor-এর পাশে বোর্ডে ঝালাই বা একই package-এ — তাই পরে বদলানো যায় না। আপনার ফোনের RAM প্রায় নিশ্চিতভাবে LPDDR.
GDDR
GDDR গ্রাফিক্স কার্ডে: প্রতি pin খুব উঁচু গতি (GDDR6-এ প্রতি pin কয়েক দশ Gb/s-এর ঘরে বলে উল্লেখ পাওয়া যায়), প্রতিটি chip ৩২ bit চওড়া, GPU-র চারপাশে অনেকগুলো chip. Latency-র চেয়ে মোট bandwidth বড়।
HBM
HBM: কয়েকটি DRAM die একটির ওপর আরেকটি সাজানো (stack), খাড়া তার (TSV) দিয়ে যুক্ত, আর processor-এর পাশে একটি silicon interposer-এ বসানো। Stack-প্রতি ১০২৪ bit বা তারও বেশি চওড়া পথ, প্রতি pin তুলনামূলক ধীর — তবু stack-প্রতি শত শত GB/s. AI accelerator আর বড় GPU-তে প্রচলিত; দাম আর তাপ বড় বাধা।
এক transistor-এর বিপ্লব। IBM-এর Robert Dennard ১৯৬৬ সালে এক transistor-এর DRAM cell-এর ধারণা দেন, আর ১৯৬৮ সালে তার patent পান বলে জানা যায়। ১৯৭০ সালে Intel-এর 1103 — ১ Kbit-এর chip — প্রথম বাণিজ্যিকভাবে সফল DRAM হিসেবে পরিচিত, যা কয়েক বছরের মধ্যে magnetic core memory-কে সরিয়ে দেয়। তারপর থেকে আজ পর্যন্ত main memory-র মূল cell সেই একই 1T1C — বদলেছে শুধু আকার, capacitor-এর গড়ন (গভীর গর্ত বা উঁচু স্তম্ভ) আর চারপাশের interface.
৬ · Interleaving আর memory controller — অপেক্ষাকে একসাথে চালানো
পর্ব ৪৭-এ দেখেছেন, AMAT-এর একটি বড় অংশ miss penalty. একটি cache block আনতে মেমরি কত সময় নেয়, তা মেমরির গঠনের ওপর নির্ভর করে। Patterson–Hennessy-র বিখ্যাত উদাহরণটি নিন। অনুমান: ঠিকানা পাঠাতে ১টি bus cycle; প্রতিটি DRAM access-এ ১৫ cycle; এক word (৪ byte) ডেটা পাঠাতে ১ cycle; cache block = ৪ word = ১৬ byte. তিনটি নকশা:
- এক-word চওড়া মেমরি: প্রতিটি word-এর জন্য আলাদা access আর পাঠানো, একটির পর একটি। Miss penalty = ১ + ৪ × (১৫ + ১) = ৬৫ cycle; bandwidth = ১৬ ÷ ৬৫ ≈ ০.২৫ byte/cycle.
- ৪-word চওড়া মেমরি আর bus: একবারে পুরো block access আর পাঠানো। ১ + ১৫ + ১ = ১৭ cycle; ১৬ ÷ ১৭ ≈ ০.৯৪ byte/cycle. কিন্তু চওড়া bus আর চওড়া mux দামি।
- ৪-bank interleaved: bus এক word চওড়াই, কিন্তু মেমরি ৪টি bank-এ ভাগ, আর পরপর word পালা করে আলাদা bank-এ (word 0 → bank 0, word 1 → bank 1, …) — একে বলে low-order interleaving, কারণ ঠিকানার নিচের বিট bank বাছে। একটি ঠিকানা পাঠালে চারটি bank একসাথে access শুরু করে; তারপর word-গুলো একটি একটি পাঠানো। ১ + ১৫ + ৪ × ১ = ২০ cycle; ১৬ ÷ ২০ = ০.৮০ byte/cycle.
| cycle | |
| এক-word চওড়া | |
| ৪-word চওড়া | |
| ৪-bank interleaved | |
| পৌঁছানো word (এক / চওড়া / interleaved) |
- Cycle ১ — ঠিকানা। তিন নকশাতেই প্রথমে block-এর ঠিকানা মেমরিতে পাঠাতে ১ cycle.
- Cycle ২–১৬ — access. এক-word চওড়া মেমরি শুধু word 0 পড়ছে। ৪-word চওড়া মেমরি একবারে চারটিই পড়ছে। Interleaved-এ চারটি bank প্রত্যেকে নিজের word একসাথে পড়ছে — চারটি access-এর সময় একটির মধ্যে ঢুকে গেছে।
- Cycle ১৭ — প্রথম পাঠানো। চওড়া bus চারটি word একসাথে পাঠায়: ১৭ cycle-এ শেষ। Interleaved আর এক-word চওড়া দুটোই সরু bus-এ word 0 পাঠায়।
- Cycle ১৮–২০ — interleaved শেষ। Bank 1, 2, 3-এর word আগেই তৈরি, তাই পরপর তিন cycle-এ পাঠানো: ২০ cycle-এ পুরো block. এক-word চওড়া মেমরি তখন সবে word 1-এর access শুরু করেছে।
- Cycle ২১–৪৯ — একঘেয়ে অপেক্ষা। এক-word চওড়া মেমরি প্রতিটি word-এর জন্য নতুন করে ১৫ cycle অপেক্ষা করে: word 1 পৌঁছায় ৩৩-এ, word 2 ৪৯-এ।
- Cycle ৫০–৬৫ — শেষ। Word 3 পৌঁছায় ৬৫-এ। চূড়ান্ত: ৬৫ / ১৭ / ২০ cycle. Interleaving প্রায় চওড়া মেমরির সমান লাভ দেয়, কিন্তু চওড়া bus-এর খরচ ছাড়াই — এটাই আজকের বহু-bank DRAM-এর মূল যুক্তি।
// Miss penalty for a 4-word cache block: one-word-wide vs wide vs interleaved memory
// send address = 1 bus cycle, each DRAM access = A bus cycles, send one bus-width of data = 1 bus cycle
function penalties(A, words = 4, wordBytes = 4) {
const bytes = words * wordBytes;
return [
["1-word-wide", 1 + words * (A + 1)], // access and send each word one after another
["2-word-wide", 1 + (words / 2) * (A + 1)],
["4-word-wide", 1 + A + 1], // one access, one wide transfer
["4-bank interleaved", 1 + A + words * 1], // banks access in parallel, words sent one by one
].map(([name, c]) => [name, c, bytes / c]);
}
for (const A of [15, 40]) {
console.log(`DRAM access = ${A} bus cycles, block = 4 words x 4 bytes`);
for (const [name, c, bw] of penalties(A))
console.log(` ${name.padEnd(20)} miss penalty = ${String(c).padStart(3)} cycles ${bw.toFixed(2)} bytes/cycle`);
}আসল আউটপুট:
DRAM access = 15 bus cycles, block = 4 words x 4 bytes
1-word-wide miss penalty = 65 cycles 0.25 bytes/cycle
2-word-wide miss penalty = 33 cycles 0.48 bytes/cycle
4-word-wide miss penalty = 17 cycles 0.94 bytes/cycle
4-bank interleaved miss penalty = 20 cycles 0.80 bytes/cycle
DRAM access = 40 bus cycles, block = 4 words x 4 bytes
1-word-wide miss penalty = 165 cycles 0.10 bytes/cycle
2-word-wide miss penalty = 83 cycles 0.19 bytes/cycle
4-word-wide miss penalty = 42 cycles 0.38 bytes/cycle
4-bank interleaved miss penalty = 45 cycles 0.36 bytes/cycle
প্রথম চারটি লাইন পাঠ্যবইয়ের সংখ্যা: ৬৫, ১৭, ২০ (আর মাঝামাঝি ২-word চওড়া ৩৩)। দ্বিতীয় ক্ষেত্রে access ৪০ cycle — CPU দ্রুত হলে bus cycle-এর হিসাবে DRAM আরও “ধীর” দেখায়। এক-word চওড়া তখন ১৬৫ cycle, কিন্তু interleaved মাত্র ৪৫: access যত লম্বা, interleaving-এর লাভ তত বেশি (৬৫ ÷ ২০ ≈ ৩.২৫ গুণ থেকে ১৬৫ ÷ ৪৫ ≈ ৩.৬৭ গুণ), আর চওড়া মেমরির সাথে পার্থক্য সবসময় শুধু (word − ১) টি পাঠানোর cycle. সূত্রটি সাধারণভাবে: interleaved penalty = ১ + A + n × ১, যেখানে n = block-এর word, শর্ত bank-সংখ্যা ≥ n.
Memory controller — DRAM-এর ট্রাফিক পুলিশ
CPU চায় “ঠিকানা X থেকে ৬৪ byte”; DRAM বোঝে ACTIVATE, READ, PRECHARGE, REFRESH আর ডজনখানেক timing-নিয়ম। মাঝখানে অনুবাদক আর সময়রক্ষক হলো memory controller: ঠিকানা থেকে channel-rank-bank-row-column বের করা (অংশ ৪), প্রতিটি bank-এর অবস্থা মনে রাখা, refresh-এর সময় মেনে চলা, আর সবচেয়ে গুরুত্বপূর্ণ — অপেক্ষমাণ অনুরোধগুলোর মধ্যে কোনটি আগে যাবে, তা ঠিক করা।
আগে controller ছিল মাদারবোর্ডের আলাদা chip-এ (northbridge). AMD ২০০৩ সালের দিকে Athlon 64 আর Opteron-এ এটি CPU chip-এর ভেতরে আনে, আর Intel ২০০৮ সালের দিকে Nehalem (প্রথম Core i7)-এ — এতে একটি বাড়তি chip পার হওয়ার latency কমে। ফলে একাধিক socket-এর server-এ প্রতিটি CPU-র নিজের মেমরি থাকে, আর অন্য CPU-র মেমরি পড়া ধীর — NUMA, যা পর্ব ৫৪-এ আসবে।
Scheduling-এর একটি প্রচলিত নীতির নাম FR-FCFS (First-Ready, First-Come-First-Served), ২০০০ সালের দিকে Rixner ও সহকর্মীদের একটি গবেষণায় বর্ণিত বলে জানা যায়: প্রথমে যে অনুরোধ এখনই চালানো যায় (সাধারণত খোলা সারির row hit), তারপর সবচেয়ে পুরোনো। অংশ ৩-এর trace-এ অনুরোধ ৩-এর পরে bank 0-তে row 5 খোলা; তখন অনুরোধ ৪ (row 7) আর পরে আসা অনুরোধ ৯ (row 5) একসাথে অপেক্ষায় থাকলে FR-FCFS নতুন হলেও ৯-কে (row hit) আগে দিত, আর ৪-কে (conflict) পরে। সমস্যা ন্যায্যতা: যে core একটানা row hit তৈরি করে, সে অন্য core-কে আটকে রাখতে পারে — তাই বাস্তব controller-এ বয়সের সীমা আর নানা ন্যায্যতার নিয়ম যোগ হয়। আজকের chip-গুলোর ঠিক নীতি সাধারণত প্রকাশিত নয়।
আরও গভীরে: আধুনিক controller-এ প্রতি channel-এ কয়েক ডজন অনুরোধের সারি থাকে, আর read ও write আলাদা সারিতে জমিয়ে দলে দলে পাঠানো হয়, কারণ bus-এর দিক বদলাতে (read থেকে write) কয়েক cycle নষ্ট হয়। DDR4-এর bank group আনা হয়েছিল আংশিকভাবে এজন্যই — আলাদা bank group-এ পরপর READ-এর ব্যবধান (tCCD_S) একই group-এর চেয়ে (tCCD_L) কম। Controller power-ও সামলায়: অলস rank-কে কম শক্তির অবস্থায় পাঠানো, আর ফিরিয়ে আনার latency-র সাথে তার ভারসাম্য।
৭ · ভুল ধরা আর সারানো — parity, SECDED ECC আর Rowhammer
কোটি কোটি ক্ষুদ্র capacitor — কখনো কখনো একটির চার্জ বদলে যায়: মহাজাগতিক রশ্মি বা package-এর তেজস্ক্রিয় কণার আঘাতে (soft error), দুর্বল cell-এ, বা অতিরিক্ত গরমে। একটি ল্যাপটপে এমন ঘটনা বিরল, কিন্তু হাজার হাজার server-এর ডেটা সেন্টারে প্রতিদিনের ব্যাপার। সমাধান: ডেটার সাথে বাড়তি check bit.
সবচেয়ে সরল parity bit: মোট 1-এর সংখ্যা জোড় রাখার একটি বিট। একটি বিট উল্টালে ধরা পড়ে, কিন্তু কোনটি উল্টেছে জানা যায় না, আর দুটি উল্টালে ধরাই পড়ে না। এর চেয়ে শক্তিশালী Hamming code: check bit বসানো হয় ১, ২, ৪, ৮ … অবস্থানে, আর প্রতিটি check bit সেই অবস্থানগুলোর parity রাখে, যাদের binary নম্বরে সংশ্লিষ্ট বিটটি 1. পড়ার সময় check bit-গুলো আবার হিসাব করলে যে সংখ্যা পাওয়া যায় — syndrome — তা শূন্য হলে ভুল নেই, অন্যথায় সেটিই ভুল বিটের অবস্থান। Hamming distance (Hamming distance) আর এর পুরো গাণিতিক ভিত্তি Computer Networks কোর্সের Error detection পর্বে বিস্তারিত।
m বিট ডেটার জন্য একটি ভুল সারাতে r টি check bit লাগে, যেখানে ২r ≥ m + r + ১ (syndrome-কে “ভুল নেই” আর m + r টি অবস্থানের যেকোনো একটি বোঝাতে হবে)। দুটি ভুল ধরতে আরও একটি overall parity বিট: এটাই SECDED. m = ৬৪ হলে r = ৭ (১২৮ ≥ ৭২), সাথে ১ = ৮টি check bit — (৭২, ৬৪) কোড, বাড়তি ১২.৫%. তাই ECC DIMM-এর bus ৭২ bit চওড়া: ৮টি ডেটা chip-এর সাথে একটি বাড়তি chip. m = ৪ হলে r = ৩, সাথে ১ = (৮, ৪); m = ৩২ হলে (৩৯, ৩২)।
ডিকোড করার নিয়ম: syndrome s আর overall parity p দেখুন। s = ০ আর p = ০: ভুল নেই। p = ১: একটি ভুল (বিজোড় সংখ্যক বিট উল্টেছে), অবস্থান s — s = ০ হলে ভুলটি parity বিটেই। s ≠ ০ কিন্তু p = ০: জোড় সংখ্যক বিট উল্টেছে — দুটি ভুল, ধরা গেল কিন্তু সারানো যাবে না। নিচের C প্রোগ্রাম ছোট (৮, ৪) সংস্করণে ঠিক এটাই দেখায়।
#include <stdio.h>
/* SECDED (8,4): Hamming(7,4) in positions 1..7 + overall parity in position 0 */
static unsigned bit(unsigned w, unsigned i) { return (w >> i) & 1u; }
static void show(unsigned w) { for (int i = 7; i >= 0; i--) putchar('0' + (int)bit(w, (unsigned)i)); }
static unsigned encode(unsigned d) { /* data bits go to positions 3,5,6,7 */
unsigned c = bit(d, 0) << 3 | bit(d, 1) << 5 | bit(d, 2) << 6 | bit(d, 3) << 7;
for (unsigned p = 1; p <= 4; p <<= 1) { /* check bits at positions 1,2,4 */
unsigned x = 0;
for (unsigned i = 1; i <= 7; i++) if (i & p) x ^= bit(c, i);
c |= x << p;
}
unsigned all = 0;
for (unsigned i = 1; i <= 7; i++) all ^= bit(c, i);
return c | all; /* position 0 makes the total parity even */
}
static void decode(unsigned c, const char *label) {
unsigned s = 0, all = 0;
for (unsigned i = 1; i <= 7; i++) if (bit(c, i)) s ^= i; /* syndrome */
for (unsigned i = 0; i <= 7; i++) all ^= bit(c, i); /* overall parity */
printf("%-15s ", label); show(c); printf(" syndrome=%u parity=%u -> ", s, all);
if (s == 0 && all == 0) puts("no error");
else if (all == 1) { c ^= 1u << s; printf("single error at bit %u, fixed: ", s); show(c); putchar('\n'); }
else puts("double error: detected, cannot fix");
}
int main(void) {
unsigned d = 0xB, c = encode(d); /* data 1011 */
printf("data=1011 codeword="); show(c); putchar('\n');
decode(c, "no flip");
decode(c ^ 1u << 6, "flip bit 6");
decode(c ^ 1u << 0, "flip bit 0");
decode(c ^ (1u << 6 | 1u << 3), "flip bits 6,3");
return 0;
}আসল আউটপুট:
data=1011 codeword=10101010
no flip 10101010 syndrome=0 parity=0 -> no error
flip bit 6 11101010 syndrome=6 parity=1 -> single error at bit 6, fixed: 10101010
flip bit 0 10101011 syndrome=0 parity=1 -> single error at bit 0, fixed: 10101010
flip bits 6,3 11100010 syndrome=5 parity=0 -> double error: detected, cannot fix
ডেটা 1011-এর বিটগুলো বসে অবস্থান ৩, ৫, ৭-এ (অবস্থান ৬-এ 0). Check bit: অবস্থান ১ দেখে ৩, ৫, ৭ — তিনটি 1, তাই 1; অবস্থান ২ দেখে ৩, ৬, ৭ — দুটি 1, তাই 0; অবস্থান ৪ দেখে ৫, ৬, ৭ — দুটি 1, তাই 0. মোট 1 চারটি, তাই overall parity 0: codeword 10101010. বিট ৬ উল্টালে 1-ওয়ালা অবস্থান ১, ৩, ৫, ৬, ৭; তাদের XOR = ৬ — syndrome সরাসরি ভুলের ঠিকানা, আর parity 1 বলে এটি একক ভুল, সারানো হলো। বিট ০ (parity বিট নিজে) উল্টালে syndrome ০ কিন্তু parity 1 — ভুল parity বিটেই। দুটি বিট (৬ আর ৩) উল্টালে syndrome = ৫, যা দেখে মনে হতে পারে “বিট ৫ ভুল” — কিন্তু parity 0, তাই SECDED বোঝে দুটি ভুল, আর ভুল “সংশোধন” না করে সতর্ক করে। এই বাড়তি বিটটি না থাকলে decoder বিট ৫ উল্টে তৃতীয় একটি ভুল তৈরি করত।
বাস্তব server-এর ECC memory-তে controller প্রতিটি ৬৪-bit শব্দের সাথে ৮টি check bit লেখে আর পড়ার সময় যাচাই করে; একক ভুল নিঃশব্দে সারিয়ে OS-কে জানায়, যাতে বারবার ভুল করা DIMM বদলানো যায়। বড় server-এ আরও শক্তিশালী কোড (একটি পুরো chip নষ্ট হলেও টিকে থাকা, যেমন Chipkill ধরনের নকশা) ব্যবহৃত হয়। আর controller মাঝে মাঝে নিজেই পুরো মেমরি পড়ে একক ভুল সারায় (scrubbing), যাতে দুটি ভুল জমে না যায়।
Rowhammer — নির্ভরযোগ্যতা যখন নিরাপত্তার প্রশ্ন
২০১৪ সালে Carnegie Mellon আর Intel-এর গবেষকদের (Yoongu Kim ও সহকর্মী) একটি গবেষণাপত্র দেখায়, একটি DRAM সারি খুব অল্প সময়ে বহু হাজার বার খোলা-বন্ধ করলে পাশের সারির কিছু cell-এর চার্জ বিঘ্নিত হয়ে বিট উল্টে যেতে পারে — যদিও পাশের সারিতে কেউ হাত দেয়নি। এর নাম Rowhammer. কারণ ঘনত্ব: cell যত কাছাকাছি, তাদের মধ্যে বৈদ্যুতিক প্রভাব তত বেশি। পরের বছরগুলোতে নিরাপত্তা-গবেষকরা দেখান, এমন বিট-উল্টানো দিয়ে process isolation-এর মতো সুরক্ষাও ভাঙা সম্ভব — তাই এটি শুধু নির্ভরযোগ্যতা নয়, নিরাপত্তারও প্রশ্ন। (পর্ব ৪১-এর Spectre-এর মতোই, এখানে আমরা শুধু ধারণা আর প্রতিরক্ষা দেখব।)
- Refresh বাড়ানো: refresh-এর হার দ্বিগুণ করলে বিঘ্নিত হওয়ার সময় কমে; দাম — অংশ ২-এর refresh-এর খরচ দ্বিগুণ। অনেক নির্মাতা প্রথম দিকে BIOS update দিয়ে এটি করেছিলেন বলে জানা যায়।
- Target Row Refresh (TRR): DRAM বা controller ঘন ঘন খোলা সারি গুনে তার পাশের সারিগুলো আগেভাগে refresh করে। DDR4-এর অনেক chip-এ এমন ব্যবস্থা আছে; তবে ২০২০ সালের দিকের গবেষণা দেখায়, কিছু TRR বাস্তবায়ন অসম্পূর্ণ।
- ECC: একক উল্টানো সারায়, অনেকগুলো একসাথে হলে ধরতে পারে — সাহায্য করে, কিন্তু একা যথেষ্ট নয়।
- নতুন মান: DDR5-এ controller আর DRAM-এর মধ্যে refresh management-এর মতো ব্যবস্থা, আর পরে প্রতি সারিতে activation গোনার প্রস্তাব (PRAC) যোগ হয়েছে বলে জানা যায়। ব্যবস্থাগুলো এখনো বিবর্তিত হচ্ছে।
৮ · Non-volatile memory — ROM থেকে flash আর SSD, আর সামনের দিন
SRAM আর DRAM দুটোই volatile — বিদ্যুৎ গেলে সব মুছে যায়। কম্পিউটার চালু হওয়ার মুহূর্তে CPU-কে প্রথম instruction কোথাও থেকে পড়তে হয়; সেই কোড (Operating Systems কোর্সের Boot process পর্বে বিস্তারিত) রাখা হয় non-volatile memory-তে। এর বিবর্তন:
| ধরন | কীভাবে লেখা হয় | মোছা | ব্যবহার |
|---|---|---|---|
| Mask ROM | কারখানায় chip তৈরির সময়ই সংযোগ দিয়ে | অসম্ভব | বড় পরিমাণে একই কোড — পুরোনো game cartridge, boot ROM |
| PROM | ব্যবহারকারী একবার, fuse পুড়িয়ে | অসম্ভব | ছোট পরিমাণ, একবারের firmware |
| EPROM | floating gate-এ চার্জ ঢুকিয়ে | জানালা দিয়ে UV আলো, পুরো chip, কয়েক মিনিট | ১৯৭০–৮০-এর দশকের firmware উন্নয়ন |
| EEPROM | বিদ্যুৎ দিয়ে | বিদ্যুৎ দিয়ে, byte ধরে, ধীরে | ছোট সেটিংস — microcontroller-এর calibration |
| Flash | বিদ্যুৎ দিয়ে, page ধরে | বিদ্যুৎ দিয়ে, বড় block ধরে, দ্রুত | BIOS/UEFI firmware, pen drive, ফোন, SSD |
EPROM থেকে flash পর্যন্ত সবার মূলে একই ধারণা: transistor-এর gate-এর নিচে চারদিকে অন্তরক দিয়ে ঘেরা একটি “floating gate” (বা নতুন নকশায় charge-trap স্তর)। সেখানে ইলেকট্রন আটকে রাখলে transistor-এর চালু হওয়ার ভোল্টেজ (threshold) বদলায় — এটাই বিট, আর অন্তরকের কারণে বিদ্যুৎ ছাড়াও বছরের পর বছর থাকে। Flash-এর নাম এসেছে একটি বড় block একসাথে “এক ঝলকে” মোছার ক্ষমতা থেকে; Toshiba-র Fujio Masuoka ১৯৮০-এর দশকের প্রথম ভাগে এটি উদ্ভাবন করেন বলে পরিচিত।
NOR flash
NOR flash-এ প্রতিটি cell সরাসরি bit line-এ — যেকোনো byte দ্রুত, এলোমেলো ক্রমে পড়া যায়, প্রায় ROM-এর মতো। তাই CPU সেখান থেকে সরাসরি কোড চালাতে পারে (execute-in-place). লেখা আর মোছা ধীর, ঘনত্ব কম। Microcontroller-এর ভেতরের program flash আর অনেক বোর্ডের firmware chip.
NAND flash
NAND flash-এ cell-গুলো সারি বেঁধে একটির পর আরেকটি যুক্ত (যেমন NAND gate-এর nMOS সারি) — অনেক কম তার, তাই অনেক ঘন আর সস্তা। পড়া-লেখা page ধরে (কয়েক KB), মোছা block ধরে (বহু page). এলোমেলো byte-পড়া ধীর। SSD, ফোনের storage, memory card.
NAND-এর তিনটি বিশেষ সমস্যা storage-এর পুরো নকশা ঠিক করে দেয়। এক, আগে মোছা, তারপর লেখা: একটি page-এর ওপর সরাসরি নতুন করে লেখা যায় না; পুরো block মুছতে হয়। দুই, ক্ষয়: প্রতিটি মোছা-লেখায় অন্তরক একটু ক্ষতিগ্রস্ত হয়, তাই প্রতিটি block সীমিত বার (ধরন ভেদে কয়েকশো থেকে বহু হাজার বার বলে উল্লেখ পাওয়া যায়) মোছা যায়। তিন, প্রতি cell-এ বেশি বিট: SLC-তে ১ বিট, MLC-তে ২, TLC-তে ৩, QLC-তে ৪ — প্রতি cell-এ ২nটি আলাদা চার্জ-মাত্রা চেনা লাগে। বেশি বিট মানে সস্তা আর ঘন, কিন্তু ধীর লেখা, কম সহনশীলতা আর বেশি ভুল — তাই NAND-এ শক্তিশালী ECC অপরিহার্য। ২০১৩ সালের দিক থেকে NAND-কে খাড়া স্তরে (3D NAND, শত স্তরের বেশি) সাজানো শুরু হয়।
এই সমস্যাগুলো লুকায় SSD-র controller-এর firmware: FTL (Flash Translation Layer). OS অনুরোধ পাঠায়: “block ১০০-তে এই ডেটা লেখা হোক”; FTL সেটি একটি নতুন, আগে মোছা page-এ লেখে, আর একটি map-এ মনে রাখে logical ১০০ এখন কোথায় — পুরোনো page “অচল” চিহ্নিত হয়। পরে garbage collection অচল page-ভরা block থেকে সচল page সরিয়ে block মোছে। আর wear leveling লেখাগুলো সব block-এ সমানভাবে ছড়ায়, যাতে একটি block আগেভাগে নষ্ট না হয়। SSD-কে তাই একটি ছোট কম্পিউটার বলা যায় — নিজের processor, DRAM cache আর firmware সহ। OS-এর দিক থেকে storage আর file system আছে Operating Systems কোর্সের File system implementation আর Disk scheduling পর্বে।
সামনের দিন — যা এখনো বিবর্তিত হচ্ছে
- 3D-stacked DRAM: HBM ইতিমধ্যে die-গুলো stack করে; গবেষণা আর শিল্প এর পরে NAND-এর মতো একটি die-এর ভেতরেই খাড়া স্তরে cell সাজানোর (3D DRAM) পথ খুঁজছে বলে খবর — capacitor-এর গড়নই প্রধান বাধা।
- CXL: Compute Express Link — PCIe-র physical স্তরের ওপর একটি খোলা মান (প্রথম সংস্করণ ২০১৯ সালের দিকে)। CXL memory expander কার্ড দিয়ে server-এ DIMM slot-এর বাইরেও মেমরি যোগ করা যায়, আর CPU তা সাধারণ load-store দিয়ে ব্যবহার করে — latency স্থানীয় DRAM-এর চেয়ে বেশি, অনেকটা আরেকটি NUMA node-এর মতো। কয়েকটি server-এর মধ্যে মেমরি ভাগ করার (pooling) ধারণাও আছে।
- Processing-in-memory: ডেটাকে CPU পর্যন্ত আনার খরচ (শক্তি আর bandwidth) প্রায়ই হিসাবের চেয়ে বেশি। তাই মেমরি chip-এর ভেতরে বা পাশে ছোট হিসাব-যন্ত্র বসানোর প্রস্তাব — কয়েকটি বাণিজ্যিক আর গবেষণা-নমুনা (যেমন HBM-এর ভেতরে হিসাব-একক) ঘোষিত হয়েছে বলে জানা যায়, তবে programming model এখনো বড় প্রশ্ন।
৯ · AI-এর যুগে — মেমরির হিসাবে AI, আর যাচাইয়ের অভ্যাস
মেমরির প্রশ্নে AI-এর উত্তর শুনতে বিশ্বাসযোগ্য, কিন্তু কয়েকটি ভুল বারবার দেখা যায় — বিশেষ করে একক গুলিয়ে ফেলা আর বানানো spec:
| AI-এর সাধারণ ভুল | কীভাবে ধরবেন |
|---|---|
| DDR4-3200-কে “৩২০০ MHz” ধরে tCK = ০.৩১২৫ ns, ফলে CAS latency অর্ধেক | MT/s ÷ ২ = clock; CL × ২০০০ ÷ MT/s দিয়ে নিজে হিসাব করুন |
| Bandwidth-এ bit আর byte গুলিয়ে ৮ গুণ ভুল, বা dual channel-কে একটি ১২৮-bit bus ভেবে অন্য সিদ্ধান্ত | একক লিখে লিখে হিসাব: MT/s × byte × channel |
| “DDR5-এ on-die ECC আছে, তাই সব DDR5 ECC memory” | On-die ECC chip-এর ভেতরে; পূর্ণ ECC-তে DIMM-এ বাড়তি chip আর controller-এর সমর্থন লাগে |
| Interleaving-এর penalty-তে access-কে n বার গোনা, বা ঠিকানার cycle বাদ দেওয়া | একটি cycle-ধরা ছক আঁকুন, বা অংশ ৬-এর calculator চালান |
| নির্দিষ্ট chip-এর tRFC, bank-সংখ্যা বা HBM-এর bandwidth বানিয়ে বলা | JEDEC-এর মান বা নির্মাতার datasheet দেখুন; উৎস চান |
| Rowhammer-এর প্রশ্নে আক্রমণের কোড দিতে চাওয়া | শুধু ধারণা আর প্রতিরক্ষা (TRR, ECC, refresh, নতুন মান) নিন |
AI-কে মেমরির হিসাব করতে দিলে অনুমানগুলো স্পষ্ট দিন, আর প্রতিটি ধাপ দেখাতে বলুন:
AI-এর দেওয়া মেমরি-হিসাব হাতে পেলে — চেকলিস্ট
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- SRAM আর DRAM-এর পার্থক্য, আর কোনটি কোথায়? — SRAM: ৬T, static, দ্রুত, বড় — cache; DRAM: 1T1C, destructive read, refresh, ঘন — main memory.
- DDR4-3200 CL16-এর CAS latency ns-এ? — ১৬ × ২০০০ ÷ ৩২০০ = ১০ ns.
- DDR4-2400, একটি ৬৪-bit channel-এর সর্বোচ্চ bandwidth? — ২৪০০ × ৮ = ১৯.২ GB/s.
- Row conflict-এর খরচ কেন সবচেয়ে বেশি? — আগে খোলা সারি বন্ধ (tRP), নতুন খোলা (tRCD), তারপর পড়া (tCL).
- ৬৪ bit ডেটায় SECDED-এ কয়টি check bit? — ২৭ = ১২৮ ≥ ৭২, তাই ৭টি, সাথে ১টি parity — ৮টি; (৭২, ৬৪)।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১Dennard-এর এক transistor-এর cell আর Intel 1103 — DRAM কেন magnetic core আর SRAM-কে হারিয়ে main memory-র আসন পেল, আর পঞ্চাশ বছর ধরে কেন সেখানেই আছে?
১৯৬০-এর দশকে main memory ছিল magnetic core: ছোট ছোট ferrite আংটির ভেতর দিয়ে তার, প্রতিটি আংটি একটি বিট, অনেকটা হাতে বোনা। এটি non-volatile আর নির্ভরযোগ্য ছিল, কিন্তু বানানো শ্রমসাধ্য আর ঘনত্ব বাড়ানো কঠিন। Semiconductor মেমরির প্রথম চেষ্টা ছিল SRAM-ধরনের flip-flop cell — কিন্তু প্রতি বিটে ছয়টি বা তারও বেশি transistor, তখনকার প্রযুক্তিতে যা খুব দামি।
IBM-এর Robert Dennard ১৯৬৬ সালে একটি সাহসী সরলীকরণ ভাবলেন: বিটটিকে সক্রিয়ভাবে ধরে রাখার দরকার কী? একটি capacitor-এ চার্জ রাখলেই হয়, আর একটি transistor দরজার কাজ করবে। দাম দুটি — চার্জ চুইয়ে যায়, তাই refresh; আর পড়লে মান নষ্ট, তাই restore. কিন্তু সেই জটিলতা প্রতিটি cell-এ নয়, array-র কিনারে sense amplifier আর controller-এ একবার — হাজার cell মিলে ভাগ করে নেয়। প্রতি বিটের খরচ নেমে এল ভয়ংকরভাবে। ১৯৭০ সালের Intel 1103 (১ Kbit) এর প্রথম বড় বাণিজ্যিক সাফল্য বলে পরিচিত, আর কয়েক বছরের মধ্যে core memory প্রায় হারিয়ে যায়।
পঞ্চাশ বছর পরেও কেন একই cell? কারণ এর অর্থনীতি এখনো অপরাজেয়। SRAM দ্রুত, কিন্তু প্রতি বিটে বহু গুণ জায়গা নেয় — একটি সাধারণ ল্যাপটপের ১৬ GB SRAM দিয়ে বানালে chip-এর আকার আর দাম অবাস্তব। Flash ঘন আর সস্তা, কিন্তু লেখা ধীর আর ক্ষয়শীল — প্রতি সেকেন্ডে কোটিবার লেখা main memory-র কাজে অচল। আর নতুন প্রযুক্তি (phase-change, MRAM, ReRAM) বহু বছর ধরে চেষ্টা করছে, কিছু বিশেষ জায়গায় এসেছেও, কিন্তু দাম-গতি-সহনশীলতার পুরো মিশ্রণে DRAM-কে এখনো সরাতে পারেনি।
তবে DRAM-এর ঘনত্ব বাড়ার গতি আগের মতো নেই — capacitor-কে ছোট করতে করতে প্রতি cell-এ যথেষ্ট চার্জ রাখা কঠিন, refresh-এর খরচ বাড়ছে, আর Rowhammer-এর মতো সমস্যা দেখা দিচ্ছে। এটাই বর্তমান “DRAM scaling”-এর সংকট।
মূল উপলব্ধি: একটি নকশা টেকে যখন জটিলতা প্রতিটি cell থেকে সরিয়ে ভাগ করা কিনারে রাখা যায় — DRAM-এর জয় সরল cell আর চতুর periphery-র জয়।
প্র ০২DDR-এর প্রতিটি প্রজন্মে bandwidth কয়েক গুণ বাড়ল, কিন্তু ns-এ latency প্রায় একই থাকল। কেন, আর এর ফল CPU-নকশায় কী?
অংশ ৫-এর calculator-এ দেখেছেন: DDR4-2400 CL17-এ CAS ১৪.১৭ ns, DDR4-3200 CL22-এ ১৩.৭৫ ns, DDR5-4800 CL40-এ ১৬.৬৭ ns. অথচ bandwidth ১৯.২ থেকে ৩৮.৪ GB/s. কারণটা DRAM-এর ভেতরে। Bandwidth বাড়ানো যায় interface দিয়ে — দুই প্রান্তে transfer, চওড়া prefetch (২n থেকে ১৬n), বেশি bank আর bank group, দুটি sub-channel. এগুলো সবই chip-এর কিনারার কাজ, যা logic-এর মতো দ্রুত উন্নত হয়।
কিন্তু latency নির্ধারণ করে array-র পদার্থবিদ্যা: একটি ক্ষুদ্র capacitor লম্বা bit line-এ কতটা সংকেত দেয়, sense amplifier কত দ্রুত তা বাড়ায়, লম্বা word line কত দ্রুত চার্জ হয়। Cell ছোট হলে চার্জও কমে, ফলে sense করতে সময় একই থাকে বা বাড়ে। এ কারণে ভেতরের array-র clock DDR4-3200-এও মোটামুটি ৪০০ MHz-এর ঘরে — দশকের পর দশক প্রায় একই। ১৯৯৫ সালে William Wulf আর Sally McKee “Hitting the Memory Wall” নামে একটি ছোট প্রবন্ধে সতর্ক করেছিলেন: CPU-র গতি যদি মেমরির চেয়ে অনেক দ্রুত বাড়ে, শেষে মেমরির অপেক্ষাই সব ঠিক করবে। পর্ব ৪৪-এর memory wall-এর ধারণা সেখান থেকে।
ফলাফল CPU-নকশার প্রায় সব কিছুতে দেখা যায়। বহুস্তর cache (পর্ব ৪৭) latency কমাতে; prefetcher, যা ভবিষ্যতের অনুরোধ আগেভাগে পাঠায়; out-of-order core (পর্ব ৪০), যা miss-এর অপেক্ষার সময় অন্য কাজ করে, আর একসাথে অনেকগুলো miss চালু রাখে (memory-level parallelism); SMT (পর্ব ৪৩), যা অন্য thread দিয়ে অপেক্ষা ঢাকে। এগুলো সবই এক কৌশলের রূপ: latency কমানো যায় না, তাই bandwidth দিয়ে তাকে লুকানো। Little-এর সূত্রে: একসাথে চলমান অনুরোধ = latency × bandwidth — bandwidth বাড়লে একসাথে বেশি অনুরোধ চালু রাখতে হয়, আর সেটাই আধুনিক core আর controller করে।
মূল উপলব্ধি: মেমরিতে bandwidth কেনা যায়, latency প্রায় কেনা যায় না — তাই আধুনিক কম্পিউটার latency লুকানোর যন্ত্র।
প্র ০৩Rowhammer দেখাল একটি hardware-এর নির্ভরযোগ্যতার সমস্যা নিরাপত্তার সমস্যা হতে পারে। কেন এটি ঠিক করা এত কঠিন, আর প্রতিরক্ষার স্তরগুলো কী?
Computer নিরাপত্তার একটি মৌলিক অনুমান হলো, মেমরি যা লেখা হয়েছে তাই ফেরত দেয়, আর একটি প্রসেস অন্যের মেমরিতে লিখতে পারে না — page table আর privilege level (পর্ব ৫০) তা নিশ্চিত করে। ২০১৪ সালের Kim ও সহকর্মীদের গবেষণাপত্র দেখাল, এই অনুমান DRAM-এর পদার্থবিদ্যার ওপর দাঁড়িয়ে, আর সেই পদার্থবিদ্যা নিখুঁত নয়। একটি সারি বারবার খোলা হলে word line-এর ভোল্টেজের ওঠানামা পাশের সারির cell-এ চার্জ-চুইয়ে-যাওয়া দ্রুততর করে; refresh আসার আগেই কিছু বিট উল্টে যায়। গবেষণায় পরীক্ষিত বহু DDR3 module-এ এটি দেখা গিয়েছিল বলে প্রতিবেদন।
কেন বিপজ্জনক? কারণ যে আক্রমণকারী শুধু নিজের মেমরি পড়ছে, সে পাশের সারিতে — যেখানে অন্যের ডেটা বা page table থাকতে পারে — বিট বদলাতে পারে। পরের বছর নিরাপত্তা-গবেষকরা দেখান, এটি দিয়ে সুরক্ষার সীমা ভাঙা সম্ভব। এখানে আমরা কৌশলে যাব না — গুরুত্বপূর্ণ হলো কেন ঠিক করা কঠিন।
প্রথম কারণ: এটি একটি ঘনত্বের সমস্যা, আর ঘনত্বই DRAM-এর অর্থনীতি। প্রতিটি নতুন প্রজন্মে cell কাছাকাছি, তাই কম activation-এ বিট উল্টায় — গবেষণায় নতুন chip-এ সীমা কমতে দেখা গেছে বলে উল্লেখ আছে। দ্বিতীয়: প্রতিরক্ষার দাম। Refresh দ্বিগুণ করলে bandwidth আর শক্তি দুটোই খরচ হয় (অংশ ২-এর হিসাব)। ECC একক বিট সারায়, কিন্তু একই শব্দে অনেক বিট উল্টালে হার মানতে পারে। TRR ঘন ঘন খোলা সারি গুনে পাশেরগুলো refresh করে, কিন্তু chip-এর ভেতরে সীমিত counter থাকায় ২০২০ সালের দিকের TRRespass গবেষণা দেখায়, অনেক সারি একসাথে ব্যবহার করে কিছু বাস্তবায়ন এড়ানো যায়।
তাই প্রতিরক্ষা এখন স্তরে স্তরে: DRAM-এর ভেতরে আরও নিখুঁত গণনা (DDR5-এর refresh management, প্রতি সারিতে activation গোনার নতুন প্রস্তাব), controller-এ নজরদারি, ECC আর scrubbing, OS-এ সংবেদনশীল ডেটা (যেমন page table) আলাদা অঞ্চলে রাখা, আর cloud-এ বিভিন্ন গ্রাহকের মেমরি আলাদা রাখা।
মূল উপলব্ধি: নিরাপত্তার নিশ্চয়তা যতটা শক্ত, ততটাই শক্ত তার নিচের পদার্থবিদ্যা — আর যন্ত্র যত ঘন, তত সতর্ক প্রতিরক্ষা লাগে।
প্র ০৪Memory controller মাদারবোর্ড থেকে CPU-র ভেতরে চলে এল। এই সিদ্ধান্তের লাভ, দাম আর তার থেকে জন্মানো NUMA আর scheduling-এর প্রশ্নগুলো কী?
২০০০-এর দশকের শুরুতে সাধারণ PC-তে CPU একটি front-side bus দিয়ে northbridge chip-এর সাথে যুক্ত ছিল, আর northbridge-এর ভেতরে memory controller. প্রতিটি miss-এ অনুরোধকে CPU থেকে bus পেরিয়ে northbridge, তারপর DRAM, তারপর একই পথে ফেরত আসতে হতো। এই বাড়তি পথ latency-তে উল্লেখযোগ্য সময় যোগ করত, আর একটি bus-এ সব core-এর ভিড় bandwidth সীমিত করত।
AMD ২০০৩ সালের দিকে Opteron আর Athlon 64 (K8)-এ controller CPU-র ভেতরে আনল, আর CPU-গুলোর মধ্যে HyperTransport নামের সরাসরি সংযোগ দিল। Intel ২০০৮ সালের দিকে Nehalem-এ একই পথে যায়, QuickPath Interconnect দিয়ে। লাভ: miss latency কমল, controller CPU-র clock-এ চলে, আর প্রতিটি socket-এর নিজের channel থাকায় মোট bandwidth socket-সংখ্যার সাথে বাড়ে।
দাম দুটি। প্রথমত, CPU এখন একটি নির্দিষ্ট মেমরি-প্রজন্মে বাঁধা — DDR4 থেকে DDR5-এ যেতে নতুন CPU লাগে (কিছু chip দুটোই সমর্থন করে)। দ্বিতীয়ত এবং গভীরতর: বহু-socket server-এ প্রতিটি CPU-র কাছে নিজের মেমরি দ্রুত, অন্য CPU-র মেমরি interconnect পেরিয়ে ধীর। একে বলে NUMA (Non-Uniform Memory Access), যা পর্ব ৫৪-এ আসবে। এখন OS-কে জানতে হয় কোন thread কোন CPU-তে চলছে আর তার ডেটা কোন মেমরিতে — Linux-এর NUMA-সচেতন allocator আর scheduler এজন্যই।
Controller-এর ভেতরে scheduling-ও কঠিন হয়ে উঠল, কারণ একটি controller-এ এখন অনেক core-এর অনুরোধ। FR-FCFS row hit-কে আগে দিয়ে মোট throughput বাড়ায়, কিন্তু যে প্রোগ্রাম ধারাবাহিক পড়ে (অনেক row hit) সে এলোমেলো-পড়া প্রোগ্রামকে না খাইয়ে রাখতে পারে। ২০০০-এর দশকের শেষ থেকে গবেষণায় এর জন্য নানা ন্যায্য scheduler প্রস্তাবিত হয়েছে — প্রতিটি thread-এর ধীর হওয়া মেপে অগ্রাধিকার বদলানো, বা thread-গুলোকে দলে ভাগ করা। বাস্তব chip-এর নীতি সাধারণত গোপন।
মূল উপলব্ধি: Controller কাছে আনলে latency কমে, কিন্তু মেমরি তখন “সবার সমান দূরে” থাকে না — software-কেও জানতে হয় ডেটা কোথায়।
প্র ০৫SLC থেকে QLC আর 3D NAND — flash প্রতি cell-এ বেশি বিট আর বেশি স্তরে কীভাবে এত সস্তা হলো, আর তার দাম কে দিচ্ছে?
Toshiba-র Fujio Masuoka-র দল ১৯৮০-এর দশকে flash-এর ধারণা দেন — প্রথমে NOR, পরে NAND, যার cell সারি বেঁধে যুক্ত হওয়ায় অনেক কম জায়গা নেয়। ২০০০-এর দশকে mp3 player, ক্যামেরা আর ফোন NAND-এর বিশাল বাজার তৈরি করল, আর ২০১০-এর দশকে SSD ল্যাপটপ থেকে hard disk প্রায় সরিয়ে দিল।
দাম কমানোর প্রথম কৌশল ছিল প্রতি cell-এ বেশি বিট। একটি cell-এর threshold ভোল্টেজকে দুই মাত্রায় না রেখে চার (MLC, ২ বিট), আট (TLC, ৩ বিট) বা ষোলো (QLC, ৪ বিট) মাত্রায় ভাগ করা। একই সংখ্যক cell-এ দ্বিগুণ, তিন গুণ, চার গুণ ডেটা। কিন্তু মাত্রাগুলো এখন কাছাকাছি: সামান্য চার্জ চুইয়ে গেলেই এক মাত্রা আরেক মাত্রা হয়ে যায়। ফল — লেখা ধীর (নিখুঁত মাত্রায় পৌঁছাতে বারবার ছোট ছোট pulse), মোছা-লেখার সহনশীলতা কম, আর ভুল বেশি। তাই QLC SSD-তে শক্তিশালী ECC (প্রায়ই LDPC ধরনের কোড) আর বুদ্ধিমান firmware অপরিহার্য।
দ্বিতীয় কৌশল উচ্চতা। সমতলে cell আরও ছোট করা কঠিন হয়ে পড়ায় ২০১৩ সালের দিকে Samsung খাড়া স্তরে cell সাজানো 3D NAND বাজারে আনে বলে জানা যায়; আজ শত স্তরের বেশি। খাড়া স্তরে cell আসলে কিছুটা বড় রাখা যায়, ফলে নির্ভরযোগ্যতা কিছুটা ফিরে আসে।
দাম কে দেয়? অনেকটা firmware: FTL, wear leveling, garbage collection, ECC আর অনেক SSD-তে একটি অংশ SLC হিসেবে চালিয়ে দ্রুত লেখার cache — যা ভরে গেলে লেখার গতি হঠাৎ কমে। আর ব্যবহারকারীও দেয়: QLC SSD একটানা বড় লেখায় ধীর হতে পারে, আর প্রস্তুতকারক কত TB লেখা পর্যন্ত নিশ্চয়তা দেন (TBW), তা দেখা দরকার। অন্যদিকে বাজারের সস্তা, বিশাল storage ঠিক এই সমঝোতার ফল।
মূল উপলব্ধি: Flash-এর ঘনত্ব এসেছে পদার্থবিদ্যার নিশ্চয়তা কমিয়ে আর সেই ঘাটতি firmware ও ECC দিয়ে পূরণ করে — storage আজ hardware আর software-এর যৌথ নকশা।
অনুশীলন
পরীক্ষার ধাঁচে: bandwidth আর CAS latency, interleaving-এর miss penalty, refresh-এর খরচ আর DRAM trace, Hamming check bit আর ডিকোড। আগে নিজে চেষ্টা করুন।
-
Spec থেকে latency আর bandwidth: (ক) DDR5-5600 CL46-এর I/O clock, tCK আর CAS latency (ns) কত? (খ) দুটি DIMM, প্রতিটির মোট data-প্রস্থ ৬৪ bit (দুটি ৩২-bit sub-channel), আলাদা channel-এ — মোট সর্বোচ্চ bandwidth? (গ) DDR4-3600 CL16-এর CAS latency আর একটি ৬৪-bit channel-এর bandwidth কত? প্রথম ডেটা কোনটিতে আগে আসে?
(ক) Clock = ৫৬০০ ÷ ২ = ২৮০০ MHz; tCK = ১০০০ ÷ ২৮০০ ≈ ০.৩৫৭ ns; CAS = ৪৬ × ২০০০ ÷ ৫৬০০ ≈ ১৬.৪৩ ns.
(খ) প্রতি DIMM: ৫৬০০ × ১০৬ × ৮ byte = ৪৪.৮ GB/s; দুটিতে ৮৯.৬ GB/s.
(গ) ১৬ × ২০০০ ÷ ৩৬০০ ≈ ৮.৮৯ ns; bandwidth ৩৬০০ × ৮ = ২৮.৮ GB/s. প্রথম ডেটা DDR4-3600 CL16-এ প্রায় ৭.৫ ns আগে আসে, যদিও মোট bandwidth DDR5-এর অনেক কম — latency আর bandwidth দুটি আলাদা প্রশ্ন। (সংখ্যাগুলো অংশ ৫-এর একই সূত্রে স্ক্রিপ্টে মিলিয়ে দেখা।)
-
Interleaving-এর miss penalty: ঠিকানা পাঠাতে ১ cycle, প্রতিটি DRAM access ২০ cycle, এক word পাঠাতে ১ cycle; cache block = ৮ word, word = ৪ byte. (ক) এক-word চওড়া, (খ) ২-word চওড়া (প্রতিবার ২ word access ও পাঠানো), (গ) ৮-bank low-order interleaved মেমরিতে miss penalty আর bandwidth (byte/cycle) কত?
(ক) ১ + ৮ × (২০ + ১) = ১৬৯ cycle; ৩২ ÷ ১৬৯ ≈ ০.১৯ byte/cycle.
(খ) ১ + ৪ × (২০ + ১) = ৮৫ cycle; ৩২ ÷ ৮৫ ≈ ০.৩৮ byte/cycle.
(গ) আটটি bank একসাথে access, তারপর ৮টি word একটি একটি: ১ + ২০ + ৮ = ২৯ cycle; ৩২ ÷ ২৯ ≈ ১.১০ byte/cycle — এক-word চওড়ার চেয়ে প্রায় ৫.৮ গুণ দ্রুত, চওড়া bus ছাড়াই।
-
Refresh-এর খরচ আর DRAM trace (আউটপুট অনুমান): (ক) একটি DRAM-এর refresh window ৩২ ms, এর মধ্যে ৮১৯২টি REFRESH command, প্রতিটি tRFC = ২৯৫ ns. tREFI আর refresh-এ ব্যস্ত সময়ের শতাংশ কত? (খ) অংশ ৩-এর simulator-এ (tRCD = tCL = tRP = ২২, burst ৪, open-page) trace বদলে
[[0,1],[0,1],[0,2],[1,2],[0,1]]দিলে প্রতিটি অনুরোধের ফল, open-page-এর মোট cycle আর closed-page-এর মোট কত হবে? কোন নীতি জিতবে?(ক) tREFI = ৩২ ms ÷ ৮১৯২ = ৩৯০৬.২৫ ns; খরচ = ২৯৫ ÷ ৩৯০৬.২৫ ≈ ৭.৫৫% — DDR4-এর উদাহরণের ৪.৪৮%-এর চেয়ে বেশি, কারণ window অর্ধেক আর tRFC বড়।
(খ) (0,1): bank 0 বন্ধ — miss, ৪৮. (0,1): hit, ২৬. (0,2): bank 0-তে row 1 খোলা — conflict, ৭০. (1,2): bank 1 বন্ধ — miss, ৪৮. (0,1): bank 0-তে এখন row 2 — conflict, ৭০. মোট hit ১, miss ২, conflict ২: open-page = ২৬২ cycle (১৬৩.৭৫ ns); closed-page = ৫ × ৪৮ = ২৪০ cycle (১৫০ ns). এই trace-এ একই bank-এ সারি বারবার বদলায়, তাই closed-page জেতে. Simulator-এ চালিয়ে ঠিক এই সংখ্যাগুলো পাওয়া গেছে।
-
Hamming check bit আর ডিকোড: (ক) ১৬ bit ডেটার জন্য একক ভুল সারাতে কয়টি check bit লাগে, আর SECDED-এ মোট শব্দের দৈর্ঘ্য কত? (খ) অংশ ৭-এর (৮, ৪) SECDED-এ (অবস্থান ১–৭ Hamming, অবস্থান ০ overall parity, বিট ৭ থেকে ০ বাঁ থেকে ডানে লেখা) দুটি শব্দ পড়া হলো:
10101110আর00101011. প্রতিটির syndrome, parity আর সিদ্ধান্ত কী? প্রথমটির সংশোধিত ডেটা (অবস্থান ৭, ৬, ৫, ৩) কী?(ক) ২r ≥ ১৬ + r + ১: r = ৪-এ ১৬ ≥ ২১ নয়; r = ৫-এ ৩২ ≥ ২২ — তাই ৫টি; SECDED-এ আরও ১টি, মোট (২২, ১৬).
(খ)
10101110: 1-ওয়ালা অবস্থান (১–৭-এর মধ্যে) ১, ২, ৩, ৫, ৭; XOR: ১ ⊕ ২ = ৩, ⊕ ৩ = ০, ⊕ ৫ = ৫, ⊕ ৭ = ২ — syndrome ২; সব ৮ বিটে ৫টি 1, তাই parity ১ ⇒ একক ভুল, অবস্থান ২ (একটি check bit). সংশোধিত শব্দ 10101010, ডেটা (৭, ৬, ৫, ৩) = 1011.00101011: অবস্থান ১, ৩, ৫ (আর অবস্থান ০); XOR ১ ⊕ ৩ ⊕ ৫ = ৭; মোট ৪টি 1, parity ০ ⇒ syndrome শূন্য নয় অথচ parity জোড় — দুটি ভুল, ধরা গেল, সারানো যাবে না। (আসলে আসল 10101010-এর বিট ৭ আর বিট ০ উল্টেছিল।) Syndrome ৭ দেখে বিট ৭ উল্টালে ভুল “সংশোধন” হতো — overall parity বিট ঠিক এটাই ঠেকায়।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি বন্ধ DRAM bank থেকে ডেটা পড়ার ঘটনাগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- 📨 Controller ঠিকানা থেকে bank আর row বের করে ACTIVATE পাঠায়
- ⚡ Word line চালু হয়, cell-এর চার্জ bit line-এ ভাগ হয়
- 🔊 Sense amplifier সংকেত বাড়িয়ে row buffer ভরে, cell-এ মান restore করে
- 📖 tRCD পরে READ: column mux কলাম বাছে, tCL পরে burst-এ ডেটা বের হয়
- 🔒 tRAS পেরোলে PRECHARGE: word line বন্ধ, bit line আবার VDD/2
- ✅ tRP পরে bank নতুন সারি খোলার জন্য প্রস্তুত
নিচের কোন বৈশিষ্ট্য DRAM cell-এর, কিন্তু SRAM cell-এর নয়?
- প্রতি বিটে ছয়টি transistor
- পড়লে মান নষ্ট হয় আর নিয়মিত refresh লাগে
- CPU-র L1 cache-এ ব্যবহার
- বিদ্যুৎ থাকলে refresh ছাড়াই মান ধরে রাখা
একটি মেমরি module-এর লেবেল DDR4-3200 CL16. এর CAS latency কত ns?
- ৫ ns
- ১০ ns
- ১৬ ns
- ২০ ns
DDR4-2400 মেমরির একটি ৬৪-bit channel-এর সর্বোচ্চ (peak) bandwidth কত?
- ২.৪ GB/s
- ৯.৬ GB/s
- ১৯.২ GB/s
- ১৫৩.৬ GB/s
Open-page policy-তে একটি অনুরোধ এমন bank-এ এল, যেখানে অন্য একটি সারি খোলা। প্রথম ডেটা পর্যন্ত কোন timing-গুলোর যোগফল লাগবে?
- tCL
- tRCD + tCL
- tRP + tCL
- tRP + tRCD + tCL
ঠিকানা পাঠাতে ১ cycle, প্রতিটি DRAM access ১৫ cycle, এক word পাঠাতে ১ cycle. ৪-word-এর একটি cache block ৪-bank low-order interleaved মেমরি থেকে (bus এক word চওড়া) আনতে miss penalty কত?
- ২০ cycle
- ১৭ cycle
- ৬৫ cycle
- ৬৪ cycle
৬৪ bit ডেটায় একটি ভুল সারানো আর দুটি ভুল ধরার (SECDED) জন্য কয়টি check bit লাগে?
- ১টি
- ৭টি
- ৮টি
- ১৬টি
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Memory array: row decoder একটি word line চালু করে পুরো সারি খোলে, bit line দিয়ে মান sense amplifier-এ, column mux দরকারি অংশ বাছে।
- SRAM = ৬T, static, দ্রুত, বড় — cache ও register file; DRAM = 1T1C, destructive read, refresh (প্রায় ৬৪ ms), ঘন — main memory. Refresh-এর খরচ = tRFC ÷ tREFI.
- Timing: row hit = tCL, miss = tRCD + tCL, conflict = tRP + tRCD + tCL; CAS (ns) = CL × ২০০০ ÷ MT/s; DDR4-3200 CL22 = ১৩.৭৫ ns.
- Bandwidth = MT/s × byte × channel (DDR4-3200: ২৫.৬ GB/s, dual ৫১.২); interleaving: ১ + A + n — উদাহরণে ৬৫ / ১৭ / ২০ cycle; controller CPU-র ভেতরে, FR-FCFS ধাঁচের scheduling.
- ECC: ২r ≥ m + r + ১, SECDED (৭২, ৬৪); Rowhammer-এর প্রতিরক্ষা TRR, ECC, refresh. Flash: NOR = এলোমেলো পড়া, NAND = ঘন, block-এ মোছা, FTL আর wear leveling.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৫০ · Virtual memory-র hardware — page table, TLB আর page walkপরবর্তী পর্বঠিকানা-অনুবাদের hardware.
- পর্ব ৪৭ · Cache-এর পারফরম্যান্স — write policy, AMAT আর multi-level cacheআগের ধাপMiss penalty কীভাবে AMAT-এ ঢোকে।
- কম্পিউটার আর্কিটেকচার ও ডিজিটাল লজিক · কোর্স হোম৬২টি পর্বপুরো কোর্সের রোডম্যাপ।
- Computer Networks · Error detection — parity, checksum, CRC আর Hammingপাশের ট্র্যাকHamming code-এর পূর্ণ গণিত।
- Operating Systems · মেমরি ব্যবস্থাপনার ভিত্তিপাশের ট্র্যাকএকই মেমরি, OS-এর চোখে।
- C প্রোগ্রামিং · পারফরম্যান্স আর cacheহাতে-কলমেমেমরি-বান্ধব কোড লেখা।