সালটা ২০১৭। আমি আমার জীবনের সবচেয়ে বোল্ড সিদ্ধান্তটা নিয়ে ফেললাম—ক্যারিয়ার শিফট করে ঢুকে পড়লাম সফটওয়্যার ইন্ডাস্ট্রিতে।
আমি তখন একজন নন-CSE ব্যাকগ্রাউন্ডের মানুষ। পড়াশোনা করেছি গার্মেন্টস ডিজাইন অ্যান্ড প্যাটার্ন মেকিং ইঞ্জিনিয়ারিং নিয়ে। কোডিং শিখতে শিখতে অনেকটা ভালোবাসাও জন্মে গিয়েছিল, কিন্তু একটা জিনিস আমাকে বারবার ভাবাতো—
আমি কোড তো লিখছি, কিন্তু কম্পিউটার ভিতরে বসে এগুলো আসলে কীভাবে চালায়?
তখন শুধু code লিখতে পারতাম কিন্তু বুঝতাম না যে আমার লেখা program টা আসলে computer এর ভিতরে কিভাবে কাজ করে। CPU, Memory, OS এই বিষয়গুলো বুঝতে গিয়ে অনেকটা সময় ও শ্রম লেগেছে এবং অনেক struggle এর পর ধীরে ধীরে বুজতে শুরু করি।
আজকে সেই অভিজ্ঞতা থেকে খুব সহজ করে বোঝানোর চেষ্টা করব যে CPU এর ভিতরে আসলে কি হয়। বাংলায় সহজ ভাষায় ও গভীরভাবে ব্যাখ্যা করা রিসোর্স খুব কম, তাই এই আর্টিকেলটি লেখা—যাতে আপনার মতো আরেকজন আগ্রহী মানুষ সহজ ভাষায় এই জটিল বিষয়গুলো বুঝতে পারেন।
CPU কি এবং কেন গুরুত্বপূর্ণ?
CPU মানে Central Processing Unit - একে computer এর "brain" বলা হয়। কিন্তু আসলে এটা brain এর মতো চিন্তা করে না, বরং খুব দ্রুত গতিতে simple mathematical operations করে। আমরা যে program লিখি, সেটা শেষ পর্যন্ত CPU এর কাছে গিয়ে পৌঁছায় 0 আর 1 হিসেবে, যাকে বলি machine code।
CPU এর প্রধান অংশগুলো
1. Control Unit (CU)
এটা হলো CPU এর "traffic controller"। Program এর instruction গুলো কোন order এ execute হবে, কোন data কোথায় পাঠাতে হবে - এসব control করে CU।
Example: মনে করেন আপনি একটা recipe follow করছেন। CU হলো সেই person যে বলছে "প্রথমে চাল ধুয়ে নাও, তারপর পানি দাও, তারপর চুলায় দাও"।
2. Arithmetic Logic Unit (ALU)
এখানে সব mathematical calculations হয়। Addition, subtraction, multiplication, division এবং logical operations (AND, OR, NOT) সব এখানে হয়।
Example: যদি আপনি লিখেন var result int = 5 + 3;
তাহলে এই addition টা ALU তে হবে।
3. Registers
এগুলো হলো CPU এর সবচেয়ে fast memory। খুব small amount এর data temporarily store করে রাখে। CPU যখন কোনো ডেটা বা নির্দেশ নিয়ে কাজ করে, তখন সেই ডেটা বা নির্দেশ সাময়িকভাবে রেজিস্টারে জমা রাখা হয়। এতে করে ALU খুব দ্রুত ডেটা অ্যাক্সেস করতে পারে এবং কাজ সম্পন্ন করতে পারে। যেমন:
- Accumulator: Calculation এর result store করে
- Program Counter (PC): পরবর্তী instruction এর address রাখে
- Instruction Register (IR): Current instruction রাখে
4. Cache Memory
RAM থেকে data আনতে time লাগে। তাই frequently used data cache এ রাখা হয় যাতে দ্রুত access করা যায়।
- L1 Cache: সবচেয়ে fast, CPU এর সাথে attached
- L2 Cache: একটু slow কিন্তু বড়\n
- L3 Cache: সবচেয়ে বড় কিন্তু comparative slow
Program Execution Process: Step by Step
এখন একটা simple calculator program দিয়ে দেখাবো কিভাবে step by step execution হয়:
package main
import "fmt"
func main() {
var a int = 10
var b int = 5
var sum int = a + b
fmt.Printf("Sum: %d\n", sum)
}
Step 1: Program Loading (Storage থেকে Memory তে)
যখন আপনি program run করেন:
- Hard disk/SSD থেকে compiled program (executable file) RAM এ load হয়
- Operating System একটা process create করে
- Program এর instructions এবং data আলাদা আলাদা memory segment এ রাখা হয়
Hard Disk → RAM
[program.exe] → [Code Segment | Data Segment | Stack | Heap]
Step 2: Fetch Cycle শুরু
- Program Counter (PC) এ first instruction এর address থাকে
- CPU সেই address থেকে instruction fetch করে
- Instruction Instruction Register (IR) এ store হয়
PC: 0x1000 → Memory[0x1000] → IR: "var a int = 10"
Step 3: Decode Phase
Control Unit instruction decode করে বুঝে:
- এটা একটা variable declaration
- Value 10 কে register এ store করতে হবে
- Memory তে space allocate করতে হবে
Step 4: Execute Phase - Line by Line
Line 1: var a int = 10
1. Memory তে 8 bytes space allocate করে → address: 0x2000 (Go তে int হয় 64-bit)
2. Value 10 কে register এ load → R1 = 10
3. R1 এর value memory তে store → Memory[0x2000] = 10
Line 2: var b int = 5
1. Memory তে আরো 8 bytes space → address: 0x2008
2. Value 5 কে register এ load → R2 = 5
3. Memory তে store → Memory[0x2008] = 5
Line 3: var sum int = a + b
1. Variable 'a' এর value register এ load → R1 = Memory[0x2000] = 10
2. Variable 'b' এর value register এ load → R2 = Memory[0x2008] = 5
3. ALU তে addition operation → R3 = R1 + R2 = 15
4. Result কে memory তে store → Memory[0x2010] = 15
Visual Representation:
CPU
┌─────────────────┐
│ Registers │
│ R1: 10 │
│ R2: 5 │
│ R3: 15 │
│ │
│ ALU │
│ [+] [×] [-] │
│ │
│ Control Unit │
│ PC: 0x1004 │
│ IR: add R1,R2 │
└─────────────────┘
↕
┌─────────┐
│ Cache │
│ L1: ... │
│ L2: ... │
└─────────┘
↕
┌─────────────────┐
│ RAM │
│ 0x2000: 10 (a) │
│ 0x2008: 5 (b) │
│ 0x2010: 15(sum) │
└─────────────────┘
Step 5: fmt.Printf Function Call
fmt.Printf("Sum: %d\n", sum)
এটা একটু complex:
- Stack এ sum (function parameters) push হয়
- Function Call হয় → CPU jumps to fmt.Printf
- Output print করে → “Sum: 15”
- Stack clean up হয়
CPU এর Internal Process:
1. PUSH sum → Stack: [15]
2. CALL fmt.Printf → PC jumps to fmt.Printf address
3. fmt.Printf executes → Screen output: "Sum: 15"
4. POP stack → Stack: []
5. RETURN → PC returns to main
Cache এর ভূমিকা
আমাদের program execute করার সময়:
- প্রথমে L1 cache check করে data আছে কিনা
- না থাকলে L2, তারপর L3 check করে
- কোথাও না থাকলে RAM থেকে fetch করে
- Frequently used data cache এ রেখে দেয়
CPU Request: "a এর value দাও"
L1 Cache: "নেই"
L2 Cache: "নেই"
RAM: "আছে, 10" → Cache এ copy → CPU কে দেয়
Program Counter এর Journey
Program Counter (PC) continuously track করে কোন instruction execute হবে:
Initial: PC = 0x1000 (var a int = 10)
After: PC = 0x1004 (var b int = 5)
After: PC = 0x1008 (var sum int = a + b)
After: PC = 0x100C (fmt.Printf call)
After: PC = 0x1010 (function end)
Memory Layout এর চিত্র
High Address
┌─────────────┐
│ Stack │ ← Local variables, function calls
├─────────────┤
│ Heap │ ← Dynamic allocation
├─────────────┤
│ Data │ ← Global variables
├─────────────┤
│ Code │ ← Program instructions
└─────────────┘
Low Address
কেন এত Complex Process?
আপনি হয়তো ভাবছেন এত simple একটা program এর জন্য এতো steps কেন? কারণ:
- Security: Memory protection, unauthorized access prevent করা
- Efficiency: Multiple programs same time run করা
- Optimization: Cache ব্যবহার করে speed বাড়ানো
- Error Handling: Program crash হলে পুরো system যাতে crash না হয়
Performance এর বিষয়
CPU এর speed measure করা হয় Clock Speed দিয়ে (GHz এ)। Modern CPU প্রতি second এ billions instructions execute করতে পারে। কিন্তু:
- Memory access: RAM থেকে data আনতে time লাগে
- Cache miss: Data cache এ না থাকলে slow হয়
- Branch prediction: if-else statements এর জন্য CPU guess করে
Practical Tips
Programming করার সময় যেসব বিষয় মাথায় রাখবেন:
- Local variables use করবেন - cache friendly
- Loop optimization করবেন - branch prediction এর জন্য
- Data structures choose করবেন carefully - memory access pattern এর জন্য
শেষ কথা
এই পুরো process টা milliseconds এর fraction এ হয়ে যায়। কিন্তু behind the scenes এ CPU এর সাথে memory, cache সবার coordination এ আমাদের program run হয়।
যখন আমি প্রথম এসব জানতাম না, তখন শুধু code লিখতাম। কিন্তু এখন যখন জানতে শুরু করেছি internal process টা কেমন, এখন আমি ফিল করতে পারি যে কোড ইন্টারনালি কিভাবে work করতেছে।
আশা করি এই article টা আপনাদের কাজে লাগবে। যদি আসলেই ভালো লেগে থাকে তাহলে অবশ্যই like, comment এন্ড share দিতে ভুলবেননা।
সর্বপরি ভুল ত্রুটি ক্ষমা সুন্দর দৃষ্টিতে দেখবেন