মেমরি প্রান্তিককরণের উদ্দেশ্য


196

স্বীকার করেছি আমি তা পাই না। বলুন আপনার কাছে 1 বাইট দৈর্ঘ্যের মেমরি শব্দ সহ একটি স্মৃতি রয়েছে। স্বাক্ষরিত ঠিকানাগুলির ক্ষেত্রে এটি কেন আপনি একটি স্বাক্ষরিত ঠিকানায় (যেমন 4 দ্বারা বিভাজ্য নয়) একক মেমরি অ্যাক্সেসে 4 বাইট দীর্ঘ পরিবর্তনশীল অ্যাক্সেস করতে পারবেন না?


17
কিছু অতিরিক্ত গুগলিং করার পরে আমি এই দুর্দান্ত লিঙ্কটি পেয়েছি , যা সমস্যাটিকে সত্যিই ভালভাবে ব্যাখ্যা করে।
সিন্দুক

যারা এই শিখতে শুরু করেন তাদের জন্য এই ছোট্ট নিবন্ধটি দেখুন: blog.virtualmethodstudio.com/2017/03/mmory-alignment-run-fools
অন্ধকার

3
@ ইয়র্ক লিঙ্কটি ভাঙা হয়েছে
জন জিয়াং

2
@ জোহানজিয়াং আমি মনে করি যে আমি এখানে নতুন লিঙ্কটি পেয়েছি: বিকাশকারী.আইবিএম
টেকনোলজিস

উত্তর:


63

এটি অনেকগুলি অন্তর্নিহিত প্রসেসরের সীমাবদ্ধতা। এটি প্রায়শই একটি দক্ষ শব্দ আনার পরিবর্তে 4 অদক্ষ একক বাইট ফেচ করে কাজ করা যেতে পারে, তবে অনেক ভাষা নির্দিষ্টকারীরা সিদ্ধান্ত নিয়েছে যে কেবল তাদের আটকানো সহজ হবে এবং সবকিছুকে সারিবদ্ধ করার জন্য বাধ্য করা হবে।

এই লিঙ্কে আরও অনেক তথ্য রয়েছে যা ওপি আবিষ্কার করেছিল।


311

একটি আধুনিক প্রসেসরের মেমরি সাবসিস্টেমটি তার শব্দ আকারের গ্রানুলারিটি এবং প্রান্তিককরণে মেমরি অ্যাক্সেসের মধ্যে সীমাবদ্ধ; এটি বেশ কয়েকটি কারণে কেস হয়।

গতি

আধুনিক প্রসেসরগুলির ক্যাশে মেমরির একাধিক স্তর রয়েছে যা অবশ্যই ডেটা দিয়ে টানতে পারে; একক বাইট রিড সমর্থন করে মেমরি সাবসিস্টেম থ্রুপুটটিকে শক্তভাবে এক্সিকিউশন ইউনিট থ্রুপুট (ওরফে সিপিইউ-আবদ্ধ) হিসাবে আবদ্ধ করে তোলে; এটিই স্মরণ করিয়ে দেয় যে হার্ড ড্রাইভে একই কারণে অনেকগুলি কারণে ডিএমএ দ্বারা পিআইও মোডকে কীভাবে ছাড়িয়ে গিয়েছিল

সিপিইউ সর্বদা তার শব্দের আকারে (32-বিট প্রসেসরের 4 বাইট) পড়ে থাকে, সুতরাং যখন আপনি একটি স্বাক্ষরবিহীন ঠিকানার অ্যাক্সেস করেন - এমন কোনও প্রসেসরে এটি সমর্থন করে - প্রসেসর একাধিক শব্দ পড়তে চলেছে। সিপিইউ মেমরির প্রতিটি শব্দ পড়বে যা আপনার অনুরোধ করা ঠিকানাটি বিভক্ত হয়। এটি অনুরোধিত ডেটা অ্যাক্সেস করতে প্রয়োজনীয় মেমরি লেনদেনের সংখ্যা 2X পর্যন্ত বাড়িয়ে তোলে।

এ কারণে, চারটির চেয়ে দুটি বাইট পড়তে খুব সহজেই ধীর হতে পারে। উদাহরণস্বরূপ, বলুন আপনার মেমরির একটি কাঠামো রয়েছে যা দেখতে দেখতে এটির মতো দেখাচ্ছে:

struct mystruct {
    char c;  // one byte
    int i;   // four bytes
    short s; // two bytes
}

একটি 32-বিট প্রসেসরে এটি সম্ভবত এখানে দেখানো মত প্রান্তিককরণ করা হবে:

স্ট্রাক্ট লেআউট

প্রসেসর এই সদস্যদের প্রত্যেককে একটি লেনদেনে পড়তে পারে।

বলুন আপনার স্ট্রাক্টের একটি প্যাক সংস্করণ ছিল, সম্ভবত সেই নেটওয়ার্ক থেকে যেখানে এটি ট্রান্সমিশন দক্ষতার জন্য প্যাক করা হয়েছিল; এটি দেখতে এরকম কিছু দেখাচ্ছে:

প্যাক স্ট্রাক্ট

প্রথম বাইট পড়া একই হতে চলেছে।

আপনি প্রসেসরের কাছে আপনাকে 0x0005 থেকে 16 বিট দিতে বললে 0x0004 থেকে কোনও শব্দ পড়তে হবে এবং এটি 16-বিট রেজিস্টারে রাখার জন্য বাম 1 বাইটে স্থানান্তরিত করতে হবে; কিছু অতিরিক্ত কাজ, তবে বেশিরভাগ এটি একটি চক্রের মধ্যে পরিচালনা করতে পারে।

আপনি 0x0001 থেকে 32 বিটের জন্য জিজ্ঞাসা করলে আপনি একটি 2 এক্স পরিবর্ধন পাবেন। প্রসেসর 0x0000 থেকে ফলাফল নিবন্ধের মধ্যে পড়বে এবং বাম 1 বাইট শিফট করবে, তারপরে 0x0004 থেকে আবার অস্থায়ী রেজিস্টারে পড়বে, ডানদিকে 3 বাইট শিফট ORকরবে , তারপরে এটি ফলাফলের নিবন্ধের সাথে থাকবে।

পরিসর

প্রদত্ত কোনও ঠিকানার জায়গার জন্য, যদি আর্কিটেকচারটি ধরে নিতে পারে যে 2 টি এলএসবি সর্বদা 0 (যেমন, 32-বিট মেশিন) থাকে তবে এটি 4 গুণ বেশি মেমোরি অ্যাক্সেস করতে পারে (2 টি সংরক্ষিত বিট 4 স্বতন্ত্র অবস্থার প্রতিনিধিত্ব করতে পারে), বা একই পরিমাণে পতাকা হিসাবে কিছু জন্য 2 বিট সঙ্গে মেমরি। কোনও ঠিকানা ছাড়াই 2 টি এলএসবি নেওয়া আপনাকে একটি 4-বাইট প্রান্তিককরণ দেয়; এছাড়াও 4 বাইট একটি ধাপ হিসাবে চিহ্নিত করা হয় । প্রতিবার কোনও ঠিকানা বর্ধিত হলে এটি কার্যকরভাবে বিট 2 বৃদ্ধি করে, বিট 0 হয় না, অর্থাৎ শেষ 2 বিট সর্বদা চলতে থাকবে 00

এটি এমনকি সিস্টেমের দৈহিক নকশাকেও প্রভাবিত করতে পারে। যদি অ্যাড্রেস বাসে 2 টি কম বিটের প্রয়োজন হয়, সিপিইউতে 2 টি কম পিন এবং সার্কিট বোর্ডে 2 টি কম চিহ্ন থাকতে পারে।

পারমাণবিক পরিমাণ

সিপিইউ পারমাণবিকভাবে মেমরির এক প্রান্তযুক্ত শব্দের উপর পরিচালনা করতে পারে যার অর্থ অন্য কোনও নির্দেশ সেই অপারেশনটিতে বাধা দিতে পারে না। এটি অনেকগুলি লক-ফ্রি ডেটা স্ট্রাকচার এবং অন্যান্য সম্মতিযুক্ত দৃষ্টান্তগুলির সঠিক ক্রিয়াকলাপের জন্য গুরুত্বপূর্ণ ।

উপসংহার

প্রসেসরের মেমরি সিস্টেমটি এখানে বর্ণিত চেয়ে কিছুটা জটিল এবং জড়িত; কোনও x86 প্রসেসর কীভাবে প্রকৃতপক্ষে মেমরিটিকে সম্বোধন করে তার উপর আলোচনা (অনেকগুলি প্রসেসর একইভাবে কাজ করে)।

মেমরি প্রান্তিককরণ মেনে চলার আরও অনেক সুবিধা রয়েছে যা আপনি এই আইবিএম নিবন্ধে পড়তে পারেন ।

কম্পিউটারের প্রাথমিক ব্যবহার হ'ল ডেটা ট্রান্সফর্ম করা। আধুনিক মেমরি আর্কিটেকচার এবং প্রযুক্তিগুলি বেশ নির্ভরযোগ্য উপায়ে - আরও ডেটা, ইন, আউট এবং আরও বেশি দ্রুত কার্যকরকরণ ইউনিটের মধ্যে পাওয়ার সুবিধার জন্য কয়েক দশক ধরে অনুকূলীকৃত হয়েছে।

বোনাস: ক্যাশে

পারফরম্যান্সের জন্য আরও একটি প্রান্তিককরণ যা আমি পূর্বে ইঙ্গিত করেছিলাম তা হ'ল ক্যাশে লাইনে প্রান্তিককরণ যা (উদাহরণস্বরূপ, কিছু সিপিইউতে) 64 বি।

ক্যাশে উপার্জনের মাধ্যমে কতটা পারফরম্যান্স অর্জন করা যায় সে সম্পর্কে আরও তথ্যের জন্য , প্রসেসরের ক্যাশে প্রভাবগুলির গ্যালারীটি একবার দেখুন ; ক্যাশে-লাইন আকারে এই প্রশ্ন থেকে

নির্দিষ্ট ধরণের প্রোগ্রামের অপ্টিমাইজেশনের জন্য ক্যাশে লাইনগুলি বোঝা গুরুত্বপূর্ণ হতে পারে। উদাহরণস্বরূপ, ডেটা সারিবদ্ধকরণ নির্ধারণ করতে পারে কোনও অপারেশন এক বা দুটি ক্যাশে লাইন স্পর্শ করে কিনা। উপরের উদাহরণে যেমন আমরা দেখেছি, এর অর্থ সহজেই বোঝানো যেতে পারে যে ভুল পথে চালিত মামলায় অপারেশন দ্বিগুণ ধীর হয়ে যাবে।


নিম্নলিখিত স্ট্রাইকগুলি xyz এর বিভিন্ন আকার রয়েছে, কারণ প্রতিটি সদস্যের নিয়মের কারণে ঠিকানাটির সাথে শুরু করতে হবে যা এটির আকারের বহুগুণ এবং স্ট্রাকটটি এমন ঠিকানা দিয়ে শেষ করতে হবে যা কাঠামোর সদস্যের বৃহত্তম আকারের বহুগুণ। স্ট্রাক্ট x {সংক্ষিপ্ত গুলি; // 2 বাইট এবং 2 প্যাডিং টাইটস ইনট আই; // 4 বাইট চার চর; // 1 বাইট এবং 3 প্যাডিং বাইট দীর্ঘ দীর্ঘ l; }; কাঠামো y {int i; // 4 বাইট চার চর; // 1 বাইট এবং 1 প্যাডিং বাইট শর্ট এস; // 2 বাইট}; কাঠামো z {int i; // 4 বাইট শর্ট এস; // 2 বাইট চার চর; // 1 বাইট এবং 1 প্যাডিং বাইট};
গ্যাভিন

1
যদি আমি সঠিকভাবে বুঝতে পারি তবে কম্পিউটার কেন এক ধাপে একটি স্বাক্ষরবিহীন শব্দটি পড়তে পারে না কারণ অ্যাডেসেসগুলি 32 বিট ব্যবহার করে 32 বিট ব্যবহার করে না ??
getFree

1
@ চিচস হ্যাঁ এটি সত্য, নিরবচ্ছিন্নতা কখনই ধরে না। ৮০৮৮ গতি এবং ব্যয়ের মধ্যে বাণিজ্য সম্পর্কে একটি আকর্ষণীয় অধ্যয়ন, এটি মূলত একটি 16-বিট 8086 ছিল (যার একটি পূর্ণ 16-বিট বহিরাগত বাস ছিল) তবে উত্পাদন খরচ বাঁচাতে কেবল অর্ধেক বাস-লাইন ছিল। ৮০৮৮ এর তুলনায় ৮০৮৮ টি স্মৃতি অ্যাক্সেসের জন্য দ্বিগুণ ঘড়ির চক্রের প্রয়োজন ছিল কারণ পুরো ১--বিট শব্দটি পেতে দুটি পাঠ করতে হয়েছিল। মজার অংশটি, ৮০86৮ একটি শব্দ একটি সিলেক্টে ১--বিট প্রান্তিককরণ করতে পারে , আন-সাইনড পাঠাগুলি গ্রহণ করে ২ গ্রহণ করে। ৮০৮৮-এর অর্ধ-শব্দযুক্ত বাসটি এই ধীরগতিতে মুখোশ পড়েছিল।
জোশপুরি

2
@ জোশ্প্পেরি: সামান্য সংশোধন: ৮০৮৮ টি চারটি চক্রের মধ্যে একটি শব্দ-সংযুক্ত 16-বিট পড়তে পারে, এবং স্বাক্ষরবিহীন পাঠকগুলি আট নিতে পারে । ধীর মেমরি ইন্টারফেসের কারণে, ৮৮৮৮-ভিত্তিক মেশিনে কার্যকরকরণের সময় সাধারণত নির্দেশিকা ফেচ দ্বারা প্রভাবিত হয়। "এমওভিএক্স, বিএক্স" এর মতো নির্দেশনা "এক্সসিএইচজি এএক্স, বিএক্স" এর তুলনায় নামমাত্র একটি চক্র দ্রুত, তবে যদি এর আগে বা নির্দেশ অনুসরণ না করা হয় যার কোড বাইটে চারটি চক্রের চেয়ে বেশি কার্যকর হয় তবে এটি চারটি চক্র বেশি সময় নিতে পারে এক্সিকিউট. 8086-তে কোড আনয়ন কখনও কখনও মৃত্যুদণ্ড কার্যকর রাখতে পারে, তবে ৮০৮৮ এ যদি না ব্যবহার করা হয় ...
সুপারক্যাট

1
খুব সত্য, @ মার্টিন আমি এই প্যাডিং বাইটগুলিকে আলোচনার অন্তর্-কাঠামোর দিকে মনোনিবেশ করার জন্য সহায়তা করেছি, তবে সম্ভবত সেগুলি অন্তর্ভুক্ত করা ভাল।
জোশপুরি

22

আপনি কিছু প্রসেসরের সাহায্যে করতে পারেন ( নেহালেম এটি করতে পারে ), তবে পূর্বে সমস্ত স্মৃতি অ্যাক্সেস একটি 64-বিট (বা 32-বিট) লাইনে সংযুক্ত ছিল, কারণ বাসটি 64 বিট প্রশস্ত, আপনাকে একবারে bit৪ বিট আনতে হয়েছিল , এবং এগুলি 64 বিটের সারিবদ্ধ 'খণ্ডগুলিতে আনার বিষয়টি উল্লেখযোগ্যভাবে সহজ ছিল।

সুতরাং, যদি আপনি একটি একক বাইট পেতে চান, আপনি 64৪-বিট খণ্ডটি এনেছেন এবং তারপরে আপনি চান না এমন বিটগুলি মুখোশযুক্ত করেছেন। আপনার বাইটটি যদি সঠিক প্রান্তে থাকে তবে সহজ এবং দ্রুত, তবে এটি যদি 64৪-বিটের অংশের মাঝামাঝি হয় তবে আপনাকে অযাচিত বিটগুলি মুখোশ করতে হবে এবং তারপরে ডেটাটি সঠিক জায়গায় সরিয়ে নিতে হবে। সবচেয়ে খারাপ, যদি আপনি 2 বাইট পরিবর্তনশীল চান তবে এটি 2 টি অংশে বিভক্ত হয়ে যায়, তারপরে প্রয়োজনীয় মেমরি অ্যাক্সেস দ্বিগুণ করতে হবে।

সুতরাং, সবাই যেমন মনে করে মেমোরিটি সস্তা, তারা কেবল প্রসেসরের খাঁটি আকারের ডেটা প্রান্তিককরণ করিয়েছে যাতে আপনার কোডটি নষ্ট মেমোরির মূল্যে আরও দ্রুত এবং আরও দক্ষতার সাথে চালিত হয়।


5

মূলত, কারণটি কারণ মেমরি বাসের কিছু নির্দিষ্ট দৈর্ঘ্য রয়েছে যা মেমরির আকারের চেয়ে অনেক ছোট।

সুতরাং, সিপিইউ অন-চিপ এল 1 ক্যাশেটি পড়েছে, যা আজকাল প্রায়শই 32KB থাকে। তবে মেমোরি বাস যা এল 1 ক্যাশে সিপিইউতে সংযুক্ত করে তাতে ক্যাশে লাইনের আকারের প্রশস্ত আকার কম হবে। এটি 128 বিটের ক্রম হবে ।

তাই:

262,144 bits - size of memory
    128 bits - size of bus

মিসলাইনযুক্ত অ্যাক্সেসগুলি মাঝেমধ্যে দুটি ক্যাশে লাইনগুলিকে ওভারল্যাপ করবে এবং ডেটা প্রাপ্ত করার জন্য এটি সম্পূর্ণ নতুন ক্যাশে পড়তে হবে। এমনকি ড্রামের বাইরে যাওয়ার সমস্ত উপায় এটি মিস করতে পারে।

তদুপরি, সিপিইউর কিছু অংশকে এই দুটি পৃথক ক্যাশে লাইনগুলির মধ্যে একটিতে একটি আইটেম একসাথে রাখার জন্য তার মাথার উপরে দাঁড়াতে হবে যার প্রতিটি তথ্যের একটি অংশ রয়েছে। এক লাইনে এটি খুব হাই অর্ডার বিটের মধ্যে থাকবে, অন্যটিতে খুব নিম্ন অর্ডার বিট হবে।

পাইপলাইনে সম্পূর্ণ উত্সর্গীকৃত হার্ডওয়্যার থাকবে যা সিপু ডেটা বাসের প্রয়োজনীয় বিটগুলিতে প্রান্তিকৃত বস্তুগুলিকে সরিয়ে রাখে, তবে এই জাতীয় হার্ডওয়্যারটি ভুল পথে চালিত বস্তুর অভাবের কারণ হতে পারে কারণ সঠিকভাবে অপ্টিমাইজড গতির জন্য সেই ট্রানজিস্টরগুলি ব্যবহার করা সম্ভবত আরও বোধগম্য হয় প্রোগ্রাম।

যাইহোক, দ্বিতীয় মেমরিটি পড়ার জন্য যা কখনও কখনও প্রয়োজনীয় হয় পাইপলাইনটি ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে নামিয়ে ফেলত না কতটুকু বিশেষ উদ্দেশ্যমূলক হার্ডওয়্যার (অনুমান এবং মূর্খতা) ভুল সংকেতযুক্ত মেমরি ক্রিয়াকলাপগুলি সংযুক্ত করার জন্য উত্সর্গীকৃত।


5

@ জোশ্প্পেরি এই প্রশ্নের দুর্দান্ত উত্তর দিয়েছেন। তার উত্তর ছাড়াও, আমার কিছু নম্বর রয়েছে যা গ্রাফিক্যালি প্রভাবগুলি বর্ণনা করে যা বর্ণনা করা হয়েছিল, বিশেষত 2 এক্স প্রশস্তকরণ। এখানে একটি গুগল স্প্রেডশিটের লিঙ্ক রয়েছে যা বিভিন্ন শব্দের প্রান্তিককরণের প্রভাব দেখতে কেমন তা দেখায়। এ ছাড়া পরীক্ষার কোড সহ গিথুব সংক্ষেপে এখানে একটি লিঙ্ক রয়েছে । পরীক্ষামূলক কোডটি জোনাথন রেন্টজচের লিখিত নিবন্ধ থেকে অভিযোজিত যা @ জোশ্পেরি রেফারেন্স করেছেন। কোয়াড-কোর ২.৮ গিগাহার্টজ ইন্টেল কোর আই 64৪-বিট প্রসেসর এবং ১ RAM জিবি র‌্যামের সাহায্যে এই পরীক্ষাগুলি একটি ম্যাকবুক প্রোতে চালানো হয়েছিল।

এখানে চিত্র বর্ণনা লিখুন


4
কী করতে xএবং yসমন্বয় মানে?
শুভা

1
কোন প্রজন্মের কোর i7? (কোডের লিঙ্কগুলি পোস্ট করার জন্য ধন্যবাদ!)
নিক দেশালিউনার্স

2

বাইট-অ্যাড্রেসযোগ্য মেমরির কোনও সিস্টেমে যদি 32-বিট-প্রশস্ত মেমরির বাস থাকে, তার মানে কার্যকরভাবে চারটি বাইট-ওয়াইড মেমরি সিস্টেম রয়েছে যা সমস্ত একই ঠিকানা পড়তে বা লিখতে তারযুক্ত। একটি সারিবদ্ধ 32-বিট রিডের জন্য চারটি মেমরি সিস্টেমে একই ঠিকানায় তথ্য সংরক্ষণ করা দরকার, যাতে সমস্ত সিস্টেম একই সাথে ডেটা সরবরাহ করতে পারে। একটি স্বাক্ষরবিহীন 32-বিট রিডের জন্য একটি ঠিকানা থেকে ডেটা ফেরত দেওয়ার জন্য কিছু মেমরি সিস্টেমের প্রয়োজন হবে এবং কিছুটিকে পরবর্তী উচ্চতর ঠিকানা থেকে ডেটা ফেরত পাঠানো হবে। যদিও এমন কিছু মেমরি সিস্টেম রয়েছে যা এই জাতীয় অনুরোধগুলি পূরণ করতে সক্ষম হয়ে উঠেছে (তাদের ঠিকানা ছাড়াও, তাদের কার্যকরীভাবে একটি "প্লাস ওয়ান" সিগন্যাল রয়েছে যার কারণে তারা নির্দিষ্ট চেয়ে উচ্চতর কোনও ঠিকানা ব্যবহার করতে পারে) এই জাতীয় বৈশিষ্ট্যটি যথেষ্ট ব্যয় যোগ করে এবং একটি মেমরি সিস্টেমের জটিলতা;


2

আপনার যদি 32 বিট ডেটা বাস থাকে তবে মেমরিটির সাথে যুক্ত ঠিকানা বাস ঠিকানা লাইনগুলি A 2 থেকে শুরু হবে , সুতরাং কেবল 32 বিট প্রান্তিক ঠিকানাগুলি একটি একক বাস চক্রে প্রবেশ করা যায়।

সুতরাং যদি কোনও শব্দ একটি ঠিকানা প্রান্তিককরণের সীমানা বিস্তৃত করে - যেমন 16/32 বিট ডেটার জন্য একটি 0 বা 32 বিট ডেটার জন্য একটি 1 শূন্য নয়, ডেটা পেতে দুটি বাস চক্রের প্রয়োজন।

কিছু আর্কিটেকচার / নির্দেশিকা সেট স্বাক্ষরবিহীন অ্যাক্সেস সমর্থন করে না এবং এই ধরনের প্রচেষ্টাগুলিতে একটি ব্যতিক্রম উত্পন্ন করবে, সুতরাং সংকলকটি উত্পন্ন স্বাক্ষরবিহীন অ্যাক্সেস কোড কেবল অতিরিক্ত বাস চক্র নয়, অতিরিক্ত নির্দেশাবলীর প্রয়োজন, এটি আরও কম দক্ষ করে তোলে।


0

পাওয়ারপিসিতে আপনি কোনও সমস্যা ছাড়াই বিজোড় ঠিকানা থেকে পূর্ণসংখ্যা লোড করতে পারেন।

স্পার্ক এবং আই 86 এবং (আমি মনে করি) আপনি এটি চেষ্টা করার পরে Itatnium হার্ডওয়্যার ব্যতিক্রম বাড়ায়।

এক 32 বিট লোড বনাম চার 8 বিট লোড বেশিরভাগ আধুনিক প্রসেসরের উপর অনেক বেশি পার্থক্য আনতে চলেছে। ডেটা ইতিমধ্যে ক্যাশে রয়েছে কিনা তা আরও বেশি প্রভাব ফেলবে।


স্পার্কে এটি একটি "বাসের ত্রুটি" ছিল, তাই পিটার ভ্যান ডার লিন্ডেনের "বিশেষজ্ঞ সি প্রোগ্রামিং: গভীর সি সিক্রেটস"
জেজেজি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.