মেমরি অর্গানাইজেশন ও ইন্টারলিভিং
এই পাঠে যা শিখবেন
- কীভাবে একাধিক মেমরি চিপ/ব্যাংক সাজিয়ে একটি একক, বড় অ্যাড্রেসেবল মেমরি সিস্টেম বানানো হয়
- মেমরি ইন্টারলিভিং কী এবং কেন এটি ব্যান্ডউইথ বাড়ায়
- লো-অর্ডার ও হাই-অর্ডার ইন্টারলিভিং স্কিমের গাণিতিক পার্থক্য
- একটি সিকোয়েনশিয়াল অ্যাক্সেস প্যাটার্নে কোন স্কিম বেশি প্যারালালিজম দেয়, তা কোড দিয়ে যাচাই
১ · মেমরি অর্গানাইজেশন — একাধিক চিপ থেকে একটি সিস্টেম
বাস্তব মেইন মেমরি একটি একক বিশাল চিপ নয় — বরং একাধিক ছোট মেমরি চিপ বা ব্যাংক একসাথে সাজিয়ে বানানো হয়। একটি মেমরি ঠিকানা এলে, তার বিটগুলোকে ভাগ করে বোঝা হয় কোন চিপ/ব্যাংক, তার ভেতরে কোন সারি (row), এবং কোন কলাম (column) — সরাসরি L24-এর বিট-ফিল্ড এক্সট্র্যাকশনের বাস্তব প্রয়োগ। কোন নির্দিষ্ট ব্যাংক এই মুহূর্তে সক্রিয় হবে তা ঠিক করে একটি ডিকোডার (L11-এর সরাসরি বাস্তব প্রয়োগ) — ঠিকানার নির্দিষ্ট বিটগুলো দেখে ঠিক একটি ব্যাংক "সিলেক্ট" করে।
২ · মেমরি ইন্টারলিভিং — ব্যান্ডউইথ বাড়ানোর কৌশল
একাধিক ব্যাংক থাকলে একটি সুযোগ তৈরি হয় — যদি পরপর মেমরি অ্যাক্সেসগুলো আলাদা আলাদা ব্যাংকে পড়ে, তাহলে সেগুলো একই সাথে সমান্তরালে শুরু করা যায় (একটি ব্যাংক ব্যস্ত থাকলেও অন্য ব্যাংক নিজের কাজ শুরু করে দিতে পারে), একের পর এক সিরিয়ালি অপেক্ষা করার বদলে। এটাই মেমরি ইন্টারলিভিং — এবং এটি সরাসরি L37-এর স্প্যাশিয়াল লোকালিটি তত্ত্বের সাথে যুক্ত — সিকোয়েনশিয়াল অ্যাক্সেস প্যাটার্ন (যা বাস্তব প্রোগ্রামে সবচেয়ে সাধারণ) থেকেই সবচেয়ে বেশি লাভ পাওয়া যায়।
দুটি প্রধান ইন্টারলিভিং স্কিম:
- লো-অর্ডার ইন্টারলিভিং: পরপর ঠিকানাগুলো পরপর ব্যাংকে যায় — কোন ব্যাংক তা ঠিক হয় ঠিকানার শেষের (কম গুরুত্বপূর্ণ) বিট দিয়ে: $bank = address \bmod N$। সিকোয়েনশিয়াল অ্যাক্সেসের জন্য সর্বোচ্চ প্যারালালিজম দেয়, কারণ পরপর প্রতিটি ঠিকানাই ভিন্ন ব্যাংকে পড়ে।
- হাই-অর্ডার ইন্টারলিভিং: পরপর ঠিকানাগুলো একই ব্যাংকের ভেতরেই থাকে, যতক্ষণ না সেই ব্যাংকের পুরো রেঞ্জ শেষ হয়, তারপর পরের ব্যাংকে যায়: $bank = \lfloor address / bank\_size \rfloor$। অ্যাড্রেসিং সরল, কিন্তু সিকোয়েনশিয়াল অ্যাক্সেসে অনেক কম প্যারালালিজম দেয়, কারণ পরপর ঠিকানাগুলো বেশিরভাগ সময়ই একই ব্যাংকে পড়ে থাকে।
বাস্তব সিস্টেমে লো-অর্ডার ইন্টারলিভিং সাধারণত পছন্দ করা হয়, ঠিক এই কারণে যে বেশিরভাগ বাস্তব মেমরি অ্যাক্সেস প্যাটার্নেই শক্তিশালী সিকোয়েনশিয়াল/স্প্যাশিয়াল লোকালিটি থাকে (L37) — এবং লো-অর্ডার স্কিমই ঠিক সেই প্যাটার্নে সবচেয়ে বেশি সুবিধা দেয়।
# লো-অর্ডার বনাম হাই-অর্ডার ইন্টারলিভিং -- সিকোয়েনশিয়াল অ্যাক্সেসে প্যারালালিজম স্কোর তুলনা
def low_order_bank(address, num_banks):
"""পরপর ঠিকানা -> পরপর ব্যাংক"""
return address % num_banks
def high_order_bank(address, num_banks, bank_size):
"""পরপর ঠিকানা -> একই ব্যাংক, bank_size শেষ হলে পরের ব্যাংক"""
return address // bank_size
addresses = list(range(8)) # সিকোয়েনশিয়াল অ্যাক্সেস প্যাটার্ন: 0,1,2,...,7
num_banks = 4
bank_size = len(addresses) // num_banks # = 2, যাতে ৮টি ঠিকানা ৪টি ব্যাংকে সমানভাবে ভাগ হয়
low_order_banks = [low_order_bank(a, num_banks) for a in addresses]
high_order_banks = [high_order_bank(a, num_banks, bank_size) for a in addresses]
print("ঠিকানা: ", addresses)
print("লো-অর্ডার ব্যাংক: ", low_order_banks)
print("হাই-অর্ডার ব্যাংক:", high_order_banks)
def parallelism_score(bank_sequence):
"""পরপর দুটি অ্যাক্সেস ভিন্ন ব্যাংকে পড়লে +1 -- সমান্তরাল ওভারল্যাপের সুযোগ গণনা"""
score = 0
for i in range(len(bank_sequence) - 1):
if bank_sequence[i] != bank_sequence[i + 1]:
score += 1
return score
low_score = parallelism_score(low_order_banks)
high_score = parallelism_score(high_order_banks)
print()
print(f"লো-অর্ডার প্যারালালিজম স্কোর = {low_score} / {len(addresses) - 1} জোড়া")
print(f"হাই-অর্ডার প্যারালালিজম স্কোর = {high_score} / {len(addresses) - 1} জোড়া")
print()
if low_score > high_score:
print("নিশ্চিত: এই সিকোয়েনশিয়াল প্যাটার্নে লো-অর্ডার ইন্টারলিভিং বেশি প্যারালালিজম দিচ্ছে।")
[0,1,2,3,0,1,2,3] — পরপর প্রতিটি জোড়াই ভিন্ন
ব্যাংক, তাই স্কোর ৭/৭। হাই-অর্ডার স্কিমে ব্যাংক-ক্রম হয় [0,0,1,1,2,2,3,3] — মাত্র ৩টি জোড়া (ব্যাংক
বদলের মুহূর্তে) ভিন্ন ব্যাংকে পড়ে, বাকি ৪টি জোড়া একই ব্যাংকে থেকে যায়, তাই স্কোর ৩/৭। এটাই সংখ্যাগতভাবে নিশ্চিত
করে যে সিকোয়েনশিয়াল অ্যাক্সেসে লো-অর্ডার ইন্টারলিভিং সত্যিই বেশি প্যারালালিজম দেয়।
মেমরি ইন্টারলিভিং দেখায় কীভাবে সাধারণ অ্যাড্রেস-থেকে-ব্যাংক ম্যাপিং ফাংশন বদলিয়েই একই হার্ডওয়্যার থেকে উল্লেখযোগ্য বেশি ব্যান্ডউইথ আদায় করা যায়, সফটওয়্যারের কোনো পরিবর্তন ছাড়াই। লো-অর্ডার ইন্টারলিভিং সিকোয়েনশিয়াল অ্যাক্সেসের (L37-এর স্প্যাশিয়াল লোকালিটি) সাথে স্বাভাবিকভাবে মিলে যায় বলেই বাস্তব সিস্টেমে বেশি ব্যবহৃত হয়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ যদি একটি প্রোগ্রামের মেমরি অ্যাক্সেস প্যাটার্ন সিকোয়েনশিয়াল না হয়ে সম্পূর্ণ র্যান্ডম হতো, তাহলে কি লো-অর্ডার ইন্টারলিভিং তখনও হাই-অর্ডারের চেয়ে ভালো হতো?
সম্পূর্ণ র্যান্ডম অ্যাক্সেসে সুবিধাটা অনেকটাই কমে যায় — কারণ লো-অর্ডার ইন্টারলিভিং-এর সুবিধা নির্ভর করে পরপর ঠিকানাগুলো predictably ভিন্ন ব্যাংকে পড়বে তার ওপর, যা সিকোয়েনশিয়াল প্যাটার্নেই নিশ্চিত। র্যান্ডম অ্যাক্সেসে দুটি স্কিমই মোটামুটি একই রকম গড় ব্যাংক-বণ্টন দেখাবে (কোনো নির্দিষ্ট প্যাটার্ন না থাকায়), যদিও তাত্ত্বিকভাবে লো-অর্ডার তখনও সামান্য এগিয়ে থাকতে পারে। এটাই দেখায় কেন L37-এর লোকালিটি তত্ত্ব এখানে সরাসরি প্রাসঙ্গিক — ইন্টারলিভিং-এর আসল সুবিধা প্যাটার্নের ওপর নির্ভরশীল, নিরঙ্কুশ নয়।
প্র ০২ হাই-অর্ডার ইন্টারলিভিং-এর "সরল অ্যাড্রেসিং" সুবিধাটা ঠিক কী অর্থে সরল — কীভাবে এটি সার্কিট ডিজাইনে সহজ হয়?
হাই-অর্ডার স্কিমে ব্যাংক নির্ধারণ হয় ঠিকানার সবচেয়ে গুরুত্বপূর্ণ (উচ্চ) বিটগুলো দিয়ে — এই বিটগুলো সরাসরি, বাড়তি গণনা ছাড়াই একটি ডিকোডারে পাঠানো যায় (L11)। লো-অর্ডার স্কিমে address মড num_banks গণনা করতে হয়, যা num_banks ২-এর ঘাত না হলে বাড়তি সার্কিট লাগতে পারে (যদিও ২-এর ঘাত হলে এটাও নিচের কয়েকটি বিট নেওয়ার মতোই সহজ)। ব্যবহারিকভাবে দুটোই বাস্তবে প্রায়ই সহজ সার্কিটেই বাস্তবায়িত হয়, কিন্তু ঐতিহাসিকভাবে হাই-অর্ডার-কে "সরল" ধরা হতো ব্যাংক-রেঞ্জ পরিকল্পনা সহজ হওয়ায়।
প্র ০৩
উপরের কোড সেলে parallelism_score ফাংশনটি শুধু "পরপর জোড়া ভিন্ন ব্যাংকে কিনা" গণনা করে। এটি কি প্রকৃত হার্ডওয়্যার প্যারালালিজমের নিখুঁত পরিমাপ, নাকি একটি সরলীকৃত সূচক?
এটি একটি সরলীকৃত শিক্ষামূলক সূচক, বাস্তব হার্ডওয়্যার প্যারালালিজমের নিখুঁত পরিমাপ নয়। বাস্তব সিস্টেমে প্রকৃত ওভারল্যাপ নির্ভর করে ব্যাংক অ্যাক্সেস টাইমিং, বাস ব্যান্ডউইথ, এবং কয়টি অ্যাক্সেস একসাথে "ইন-ফ্লাইট" থাকতে পারে তার ওপরও। তবে এই সরল স্কোরটি ঠিক এই পাঠের মূল ধারণা — কোন স্কিম বেশি ব্যাংক-বৈচিত্র্য তৈরি করে, যা প্রকৃত সমান্তরালতার একটি প্রয়োজনীয় (যদিও একমাত্র নয়) পূর্বশর্ত — স্পষ্টভাবে তুলে ধরার জন্য যথেষ্ট।
অনুশীলন
-
হিসাব করুন: যদি
num_banks=2(২টি ব্যাংক) হয় এবং একই সিকোয়েনশিয়াল প্যাটার্ন (0-7) ব্যবহার হয়, লো-অর্ডার স্কিমে ব্যাংক-ক্রমটি কী হবে এবং প্যারালালিজম স্কোর কত হবে?low_order_bank(a, 2) = a % 2— তাই ব্যাংক-ক্রম:[0,1,0,1,0,1,0,1]। পরপর প্রতিটি জোড়াই ভিন্ন (0≠1, 1≠0, ইত্যাদি), তাই প্যারালালিজম স্কোর = ৭/৭ — ব্যাংক-সংখ্যা কমলেও, যতক্ষণ সিকোয়েনশিয়াল প্যাটার্ন ব্যাংক-সংখ্যার সাথে "পুরোপুরি বিভাজ্য না হয়" (এখানে ৮ ভাগ ২ = ৪, নিখুঁত), স্কোর সর্বোচ্চই থাকে। -
চিন্তা করুন: L37-এর "স্প্যাশিয়াল লোকালিটি" ধারণাটির সাথে এই পাঠের লো-অর্ডার ইন্টারলিভিং-এর সম্পর্ক ঠিক কোথায়?
স্প্যাশিয়াল লোকালিটি বলে — একটি ঠিকানা অ্যাক্সেস করলে তার কাছাকাছি ঠিকানাগুলোও শীঘ্রই অ্যাক্সেস হওয়ার সম্ভাবনা বেশি (যেমন array traversal)। লো-অর্ডার ইন্টারলিভিং ঠিক এই ধরনের কাছাকাছি, পরপর ঠিকানাগুলোকে ইচ্ছাকৃতভাবে ভিন্ন ব্যাংকে ছড়িয়ে দেয় — তাই স্প্যাশিয়াল লোকালিটিসহ একটি প্রোগ্রাম চালালে, তার পরপর অ্যাক্সেসগুলো স্বাভাবিকভাবেই ভিন্ন ব্যাংকে পড়বে ও সমান্তরালে চলবে। অর্থাৎ ইন্টারলিভিং স্কিমের নকশাটাই বাস্তব প্রোগ্রামের আচরণ (locality) মাথায় রেখে করা।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ পরবর্তী মডিউল (M10) — I/O ও ইন্টারকানেক্ট: পোর্ট-ম্যাপড বনাম মেমরি-ম্যাপড I/O দিয়ে শুরু।
- মেমরি হায়ারার্কি ও লোকালিটি অফ রেফারেন্স L37 স্প্যাশিয়াল লোকালিটির মূল ধারণা, যা এই পাঠের ইন্টারলিভিং আলোচনার ভিত্তি।