"ক্যাশে-বান্ধব" কোড কী?


738

" ক্যাশে আনফ্রেন্ডলি কোড " এবং " ক্যাশে ফ্রেন্ডলি " কোডের মধ্যে পার্থক্য কী ?

আমি কীভাবে নিশ্চিত করতে পারি যে আমি ক্যাশে-দক্ষ কোডটি লিখি?


28
এটি আপনাকে একটি ইঙ্গিত দিতে পারে: stackoverflow.com/questions/9936132/…
রবার্ট মার্টিন

4
ক্যাশে লাইনের আকার সম্পর্কেও সচেতন থাকুন। আধুনিক প্রসেসরগুলিতে এটি প্রায়শই 64৪ বাইট।
জন ডিবলিং

3
এখানে আরও একটি খুব ভাল নিবন্ধ। নীতিগুলি যে কোনও ওএসে সি / সি ++ প্রোগ্রামগুলিতে প্রয়োগ হয় (লিনাক্স, ম্যাকসোস বা উইন্ডোজ): lwn.net/Articles/255364
পলস্ম 4

4
সম্পর্কিত প্রশ্ন: স্ট্যাকওভারফ্লো
ম্যাট

উত্তর:


965

preliminaries

আধুনিক কম্পিউটারগুলিতে, কেবলমাত্র সর্বনিম্ন স্তরের মেমরি স্ট্রাকচার ( নিবন্ধগুলি ) একক ঘড়ির চক্রের মধ্যে ডেটা স্থানান্তর করতে পারে। তবে, নিবন্ধগুলি খুব ব্যয়বহুল এবং বেশিরভাগ কম্পিউটারের কম্পিউটারে কয়েক ডজনের চেয়ে কম রেজিস্টার থাকে (কয়েকশ থেকে এক হাজার বাইটস মোট)। মেমোরি স্পেকট্রামের ( ডিআরএএম ) অপর প্রান্তে , মেমরিটি খুব সস্তা (অর্থাত্ আক্ষরিক কয়েক মিলিয়ন গুণ সস্তায় ) তবে ডেটা পাওয়ার অনুরোধের পরে শত চক্র গ্রহণ করে। সুপার দ্রুত এবং ব্যয়বহুল এবং সুপার ধীর এবং সস্তার মধ্যে এই ব্যবধানটি পূরণ করার জন্য ক্যাশে স্মৃতি, ক্রমহ্রাসমান এবং ব্যয়কে L1, L2, L3 নামকরণ করেছে। ধারণাটি হ'ল বেশিরভাগ এক্সিকিউটিভ কোডটি প্রায়শই একটি ভেরিয়েবলের একটি ছোট সেটকে আঘাত করবে এবং বাকিগুলি (ভেরিয়েবলের অনেক বড় সেট) প্রায়শই ঘটবে। প্রসেসর যদি L1 ক্যাশে ডেটাটি খুঁজে না পায় তবে এটি L2 ক্যাশে দেখায়। যদি সেখানে না থাকে, তবে L3 ক্যাশে, এবং যদি না থাকে তবে মূল স্মৃতি। এই প্রতিটি "মিস" সময় ব্যয়বহুল।

(সাদৃশ্যটি হ'ল ক্যাশে মেমরিটি হ'ল সিস্টেম মেমোরি, কারণ সিস্টেম মেমরিটি খুব হার্ড ডিস্ক স্টোরেজ disk হার্ড ডিস্ক স্টোরেজ অত্যন্ত সস্তা তবে খুব ধীর)।

ক্যাশিং প্রধান পদ্ধতি প্রভাব কমাতে এক লেটেন্সি । ভেষজ সুটার (নীচে সিএফআর। লিঙ্কগুলি) প্যারাফ্রেজ করতে: ব্যান্ডউইথকে বাড়ানো সহজ, তবে আমরা বিলম্বের বাইরে আমাদের উপায় কিনতে পারি না

মেমরি হায়ারার্কির মাধ্যমে ডেটা সর্বদা পুনরুদ্ধার করা হয় (ক্ষুদ্রতম == দ্রুততম থেকে ধীর)। একটি ক্যাশে হিট / মিস সাধারণত সিপিইউতে ক্যাশের সর্বোচ্চ স্তরের একটি হিট / মিস বোঝায় - উচ্চ স্তরের দ্বারা আমি বৃহত্তম == ধীরতম মানে। ক্যাশে হিট রেট পারফরম্যান্সের জন্য অত্যন্ত গুরুত্বপূর্ণ যেহেতু প্রতিটি ক্যাশে মিসের ফলে র‍্যাম থেকে ডেটা আনার ফলাফল মিস হয় (বা আরও খারাপ ...) যা অনেক সময় নেয় (র‌্যামের জন্য কয়েকশ চক্র, এইচডিডি জন্য কয়েক মিলিয়ন চক্র)। তুলনায়, (সর্বোচ্চ স্তরের) ক্যাশে থেকে ডেটা পড়তে সাধারণত কয়েকটি মুখ্য চক্র লাগে।

আধুনিক কম্পিউটার আর্কিটেকচারে, পারফরম্যান্সের বাধাটি সিপিইউ ডাই ছাড়ছে (যেমন র‌্যাম বা তার চেয়ে বেশি উচ্চতর অ্যাক্সেস)। এটি সময়ের সাথে সাথে আরও খারাপ হবে। প্রসেসরের ফ্রিকোয়েন্সি বৃদ্ধি বর্তমানে কর্মক্ষমতা বাড়াতে প্রাসঙ্গিক নয়। সমস্যা মেমরি অ্যাক্সেস। সিপিইউগুলিতে হার্ডওয়্যার ডিজাইনের প্রচেষ্টাগুলি বর্তমানে ক্যাশে, প্রিফেচিং, পাইপলাইনগুলি এবং একযোগিতায় অনুকূলকরণের দিকে বেশি মনোযোগ দেয়। উদাহরণস্বরূপ, আধুনিক সিপিইউগুলি প্রায় 85% মরণ ক্যাশে এবং 99% ডেটা সঞ্চয় / চলন্ত জন্য ব্যয় করে!

বিষয়টিতে অনেক কিছু বলা দরকার। এখানে ক্যাশে, মেমোরি শ্রেণিবদ্ধকরণ এবং সঠিক প্রোগ্রামিং সম্পর্কে কয়েকটি দুর্দান্ত উল্লেখ রয়েছে:

ক্যাশে-বান্ধব কোডের জন্য মূল ধারণাগুলি

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

নিম্নোক্ত বিশেষ দিকগুলি ক্যাচিংকে অনুকূল করতে উচ্চ গুরুত্ব দেয়:

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

উপযুক্ত ব্যবহার করুন পাত্রে

ক্যাশে-বান্ধব বনাম ক্যাশে-বন্ধুত্বের একটি সাধারণ উদাহরণ 'গুলি std::vectorবনাম std::list। এর উপাদানসমূহ std::vectorসামঞ্জস্যপূর্ণ মেমোরিতে সংরক্ষণ করা হয় এবং এগুলিতে অ্যাক্সেস করা উপাদানগুলির অ্যাক্সেসের চেয়ে এগুলিকে অ্যাক্সেস করা অনেক বেশি ক্যাশে-বান্ধব std::list, যা এর স্থানটি সমস্ত স্থান জুড়ে রাখে। এটি স্থানীয় স্থানের কারণে।

এর একটি খুব সুন্দর চিত্র তুলে ধরেছেন এই ইউটিউব ক্লিপটিতে বারজন স্ট্রোস্ট্রুপ (লিঙ্কটির জন্য @ মোহাম্মদ আলী বায়দৌনকে ধন্যবাদ!)

ডেটা স্ট্রাকচার এবং অ্যালগরিদম ডিজাইনে ক্যাশে অবহেলা করবেন না

যখনই সম্ভব, আপনার ডেটা স্ট্রাকচার এবং গণনার ক্রমটিকে এমনভাবে মানিয়ে নেওয়ার চেষ্টা করুন যাতে ক্যাশে সর্বাধিক ব্যবহারের অনুমতি দেয়। এক্ষেত্রে একটি সাধারণ কৌশল হ'ল ক্যাশে ব্লকিং (আর্কাইভ.অর্গ সংস্করণ) , যা উচ্চ-পারফরম্যান্স কম্পিউটিংয়ে (সিএফআর। উদাহরণস্বরূপ এটিএসএলএস ) অত্যন্ত গুরুত্ব দেয় ।

ডেটার অন্তর্নিহিত কাঠামোটি জেনে নিন এবং তাদের ব্যবহার করুন

আর একটি সহজ উদাহরণ, যা ক্ষেত্রের অনেক লোক কখনও কখনও ভুলে যায় তা হ'ল কলাম-মেজর (প্রাক্তন)। ,) বনাম সারি-প্রধান ক্রম (প্রাক্তন)। ,) দ্বিমাত্রিক অ্যারে সঞ্চয় করার জন্য। উদাহরণস্বরূপ, নিম্নলিখিত ম্যাট্রিক্স বিবেচনা করুন:

1 2
3 4

সারি-প্রধান ক্রমে, এটি মেমরি হিসাবে সংরক্ষণ করা হয় 1 2 3 4; কলাম-প্রধান ক্রমে, এটি হিসাবে সংরক্ষণ করা হবে 1 3 2 4। এটি দেখতে সহজ যে বাস্তবায়নগুলি যে এই ক্রমটি ব্যবহার করে না তা দ্রুত (সহজেই এড়ানো যায়!) ক্যাশে সমস্যাগুলির মধ্যে চলে আসবে। দুর্ভাগ্যবশত, আমি কাপড় এই মত দেখতে খুব প্রায়ই আমার ডোমেইন (মেশিন লার্নিং) এ। @ মাত্তিও ইটালিয়া তার উত্তরে আরও বিশদে এই উদাহরণটি দেখিয়েছে।

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

সরলতার জন্য, ধরে নিন ক্যাশে একটি একক ক্যাশে লাইন রয়েছে যা 2 ম্যাট্রিক্স উপাদান থাকতে পারে এবং যখন কোনও প্রদত্ত উপাদান মেমরি থেকে আনা হয়, পরেরটিটিও হয়। বলুন যে আমরা উপরে 2x2 ম্যাট্রিক্সের উদাহরণগুলিতে সমস্ত উপাদানগুলির সমষ্টি নিতে চাই (এটি কল করতে দিন M):

ক্রম অনুসন্ধান (উদাহরণস্বরূপ কলাম সূচক প্রথমে পরিবর্তন করা) ):

M[0][0] (memory) + M[0][1] (cached) + M[1][0] (memory) + M[1][1] (cached)
= 1 + 2 + 3 + 4
--> 2 cache hits, 2 memory accesses

ক্রমটি ব্যবহার করে না (যেমন প্রথমে সারি সূচক পরিবর্তন করা changing ):

M[0][0] (memory) + M[1][0] (memory) + M[0][1] (memory) + M[1][1] (memory)
= 1 + 3 + 2 + 4
--> 0 cache hits, 4 memory accesses

এই সাধারণ উদাহরণে, অর্ডারটি প্রায়শই কার্যকর করার গতি দ্বিগুণ করে শোষণ করে (যেহেতু মেমরি অ্যাক্সেসের অঙ্কগুলি গণনা করার চেয়ে অনেক বেশি চক্রের প্রয়োজন হয়)। অনুশীলনে, পারফরম্যান্স পার্থক্য অনেক বড় হতে পারে ।

অপ্রত্যাশিত শাখা এড়িয়ে চলুন

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

এটি এখানে খুব ভালভাবে ব্যাখ্যা করা হয়েছে (লিঙ্কটির জন্য @ 0x90 ধন্যবাদ): কেন একটি বাছাই করা অ্যারে প্রক্রিয়াজাতকরণের চেয়ে একটি ক্রমবর্ধমান অ্যারে প্রক্রিয়াজাতকরণের চেয়ে দ্রুত হয়?

ভার্চুয়াল ফাংশন এড়িয়ে চলুন

এর প্রেক্ষাপটে , virtualপদ্ধতিগুলি ক্যাশে মিসের বিষয়ে একটি বিতর্কিত সমস্যা উপস্থাপন করে (একটি সাধারণ sensকমত্য বিদ্যমান যে পারফরম্যান্সের ক্ষেত্রে যখন সম্ভব হয় তখন এড়ানো উচিত)। ভার্চুয়াল ফাংশনগুলি অনুসন্ধানের সময় ক্যাশে মিস করতে পারে তবে এটি তখনই ঘটে যখন নির্দিষ্ট ফাংশনটি প্রায়শই বলা হয় না (অন্যথায় এটি সম্ভবত ক্যাশে হবে), তাই এটি কারও দ্বারা অ-ইস্যু হিসাবে বিবেচিত হয়। এই সমস্যাটি সম্পর্কে রেফারেন্সের জন্য, দেখুন: একটি সি ++ শ্রেণিতে ভার্চুয়াল পদ্ধতি থাকার পারফরম্যান্স ব্যয় কত?

সাধারন সমস্যা

মাল্টিপ্রসেসর ক্যাশে সহ আধুনিক স্থাপত্যগুলির একটি সাধারণ সমস্যাটিকে মিথ্যা ভাগাভাগি বলা হয় । এটি ঘটে যখন প্রতিটি পৃথক প্রসেসর অন্য মেমরি অঞ্চলে ডেটা ব্যবহার করার চেষ্টা করে এবং একই ক্যাশে লাইনে এটি সঞ্চয় করার চেষ্টা করে । এটি ক্যাশে লাইন তৈরি করে - যার মধ্যে এমন ডেটা রয়েছে যা অন্য প্রসেসর ব্যবহার করতে পারে - বারবার ওভাররাইট করা যায়। কার্যকরভাবে, বিভিন্ন থ্রেড এই পরিস্থিতিতে ক্যাশে মিস করতে প্ররোচিত করে একে অপরকে অপেক্ষা করে। আরও দেখুন (লিঙ্কটির জন্য @ ম্যাটকে ধন্যবাদ): কখন এবং কখন লাইন আকারে সারিবদ্ধ হবে?

র‌্যাম মেমরিতে দরিদ্র ক্যাচিংয়ের একটি চরম লক্ষণ (যা সম্ভবত আপনি এই প্রসঙ্গে বোঝাতে চাইছেন না) তথাকথিত থ্রেশিং । প্রক্রিয়াটি ধারাবাহিকভাবে পৃষ্ঠা ত্রুটিগুলি উত্পন্ন করে (উদাহরণস্বরূপ মেমরিটিতে প্রবেশ করে যা বর্তমান পৃষ্ঠায় নেই) যা ডিস্ক অ্যাক্সেসের প্রয়োজন হয় এটির ঘটনা ঘটে।


27
সম্ভবত আপনি উত্তর যে ব্যাখ্যা, -multithreaded code- তথ্য দ্বারা একটি বিট খুব স্থানীয় হতে পারে (যেমন মিথ্যা শেয়ারিং) প্রসারিত করতে পারে
TemplateRex

2
চিপ ডিজাইনাররা দরকারী বলে মনে করেন সেখানে ক্যাশের অনেকগুলি স্তর থাকতে পারে। সাধারণত তারা গতি বনাম আকারের ভারসাম্য বজায় রাখে। আপনি যদি নিজের এল 1 ক্যাশেটিকে L5 এর মতো বড় করে তুলতে পারেন এবং ঠিক তত দ্রুত, আপনার কেবলমাত্র L1 দরকার।
রাফায়েল ব্যাপটিস্টা

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

2
@ জ্যাকএডলি আপনার প্রশংসা করার জন্য ধন্যবাদ! এই প্রশ্নটি যে পরিমাণ মনোযোগ পেল আমি দেখেছি, আমি বুঝতে পেরেছিলাম যে অনেক লোক কিছুটা বিস্তৃত ব্যাখ্যায় আগ্রহী হতে পারে। আমি আনন্দিত এটি কার্যকর।
মার্ক ক্লেসেন

1
আপনি যা উল্লেখ করেননি তা হ'ল ক্যাশে বন্ধুত্বপূর্ণ ডেটা স্ট্রাকচারগুলি ক্যাশে লাইনের মধ্যে ফিট করার জন্য ডিজাইন করা হয়েছে এবং ক্যাশে লাইনের অনুকূল ব্যবহারের জন্য মেমরির সাথে সংযুক্ত করা হয়েছে। দুর্দান্ত উত্তর যদিও! অসাধারণ.
ম্যাট

140

@ মার্ক ক্লেসেনের উত্তর ছাড়াও, আমি মনে করি ক্যাশে-আনফ্রেন্ডলি কোডের একটি শিক্ষামূলক ক্লাসিক উদাহরণ কোড যা সারি-ওয়াইসের পরিবর্তে একটি সি দ্বি মাত্রিক অ্যারে (যেমন একটি বিটম্যাপ চিত্র) কলাম অনুসারে স্ক্যান করে।

সারিবদ্ধ সংলগ্ন উপাদানগুলি স্মৃতিতেও সংলগ্ন হয়, সুতরাং ক্রমগুলিতে তাদের অ্যাক্সেস করা মানে ক্রমবর্ধমান মেমরি ক্রমে তাদের অ্যাক্সেস করা; এটি ক্যাশে-বান্ধব, যেহেতু ক্যাশে মেমরির সংলগ্ন ব্লকগুলিকে প্রিফেট করে।

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

এবং পারফরম্যান্স নষ্ট করতে যা লাগে তা হ'ল

// Cache-friendly version - processes pixels which are adjacent in memory
for(unsigned int y=0; y<height; ++y)
{
    for(unsigned int x=0; x<width; ++x)
    {
        ... image[y][x] ...
    }
}

প্রতি

// Cache-unfriendly version - jumps around in memory for no good reason
for(unsigned int x=0; x<width; ++x)
{
    for(unsigned int y=0; y<height; ++y)
    {
        ... image[y][x] ...
    }
}

এই প্রভাবটি ছোট ক্যাশে এবং / অথবা বড় অ্যারে (উদাহরণস্বরূপ 10+ মেগাপিক্সেল 24 বিপিপি চিত্র বর্তমান মেশিনে) এর সাথে কাজ করে এমন সিস্টেমে বেশ নাটকীয় (গতিবেগের একাধিক ক্রমের) হতে পারে; এই কারণে, যদি আপনাকে অনেকগুলি উল্লম্ব স্ক্যান করতে হয় তবে প্রায়শই 90 ডিগ্রির চিত্রটি প্রথমে ঘোরানো ভাল হয় এবং পরে বিশ্লেষণগুলি সম্পাদন করা ভাল, ক্যাশে-বন্ধুত্বপূর্ণ কোডটি কেবল ঘোরার মধ্যে সীমাবদ্ধ করে দেওয়া।


ত্রুটি, এটি x <প্রস্থ হওয়া উচিত?
mowwwalker

13
আধুনিক চিত্র সম্পাদকগণ টাইলগুলি অভ্যন্তরীণ স্টোরেজ হিসাবে ব্যবহার করেন, যেমন 64৪x64৪৪ পিক্সেলের ব্লক। এটি স্থানীয় ক্রিয়াকলাপের জন্য অনেক বেশি ক্যাশে-বান্ধব (একটি ছোঁয়া বসানো, একটি ঝাপসা ফিল্টার চালানো) কারণ প্রতিবেশী পিক্সেল উভয় দিকের মেমরির কাছে থাকে, বেশিরভাগ সময়।
ম্যাক্সি

আমি আমার মেশিনে অনুরূপ উদাহরণ দেওয়ার সময় চেষ্টা করেছি এবং আমি দেখতে পেলাম যে সময়গুলি একই ছিল। অন্য কেউ কি সময় দেওয়ার চেষ্টা করেছে?
gsingh2011

@ আই3আরনন: না, প্রথমে ক্যাশে-বান্ধব, যেহেতু সাধারণত সি অ্যারেগুলিতে সারি-প্রধান ক্রমে সংরক্ষণ করা হয় (অবশ্যই যদি কোনও কারণে আপনার চিত্রটি কলাম-প্রধান ক্রমে সংরক্ষণ করা হয় তবে বিপরীতটি সত্য হয়)।
মাত্তেও ইটালিয়া

1
@ গৌথির: হ্যাঁ, প্রথম স্নিপেটটি ভাল; আমি মনে করি যে আমি যখন এটি লিখেছিলাম তখন "" এটি প্রয়োগ করা [একটি কাজের অ্যাপ্লিকেশনটির কার্যকারিতা নষ্ট করতে] লাগে ... থেকে ... "
মাত্তিও ইটালিয়া

88

ক্যাশের ব্যবহারকে অনুকূলকরণ করা মূলত দুটি কারণের মধ্যে নেমে আসে।

রেফারেন্সের লোকেশন

প্রথম ফ্যাক্টর (যা ইতিমধ্যে অন্যরা ইঙ্গিত করেছে) হ'ল রেফারেন্সের লোকেশন। রেফারেন্সের লোকেশনটির সত্যই দুটি মাত্রা রয়েছে: স্থান এবং সময়।

  • স্থান-সংক্রান্ত

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

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

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

  • সময়

সময়ের মাত্রাটির অর্থ হ'ল আপনি যখন কিছু ডেটাতে কিছু অপারেশন করেন, আপনি সেই ডেটাতে সমস্ত অপারেশন একবারে করতে চান (যতটা সম্ভব)।

আপনি সি হিসাবে এই বাঁধা থাকেন যেহেতু ++ আমি একটি অপেক্ষাকৃত ক্যাশে-অনাত্মীয় নকশা এটা একটা ধ্রুপদী উদাহরণ নির্দেশ করব: std::valarrayvalarrayoverloads সবচেয়ে গাণিতিক অপারেটর, তাই আমি করতে পারেন (উদাহরণস্বরূপ) বলে a = b + c + d;(যেখানে a, b, cএবং dসব valarrays হয়) ঐ অ্যারে উপাদান-অনুযায়ী উপরন্তু না।

এটির সাথে সমস্যাটি হ'ল এটি একজোড়া ইনপুটগুলির মধ্য দিয়ে যায়, একটি অস্থায়ী ফলাফল দেয়, অন্য জোড়া ইনপুটগুলির মধ্য দিয়ে যায়। প্রচুর ডেটা সহ, পরবর্তী গণিতে ব্যবহারের আগে একটি গণনার ফলাফল ক্যাশে থেকে অদৃশ্য হয়ে যেতে পারে, সুতরাং আমরা আমাদের চূড়ান্ত ফলাফল পাওয়ার আগেই বারবার তথ্যটি পড়া (এবং লেখা) শেষ করি। চূড়ান্ত ফলাফল প্রতিটি উপাদান ভালো কিছু হতে হবে (a[n] + b[n]) * (c[n] + d[n]);, সাধারণভাবে আমরা প্রতিটি পড়তে পছন্দ a[n], b[n], c[n]এবং d[n]একবার গণনার, কি ফলে বৃদ্ধি লিখতে nএবং পুনরাবৃত্তি 'তিল আমরা কাজ সম্পন্ন হয়। 2

লাইন ভাগ করে নেওয়া

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

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

সমস্যাটি সম্ভবত মোটামুটি সুস্পষ্ট: সরাসরি-ম্যাপযুক্ত ক্যাশে, একই ক্যাশে অবস্থিত মানচিত্রে দুটি ক্রিয়াকলাপ খারাপ আচরণের দিকে পরিচালিত করতে পারে। একটি এন-ওয়ে সেট-অ্যাসোসিয়েটিভ ক্যাশে সংখ্যাটি 2 থেকে এন + 1 এ বৃদ্ধি করে। আরও "উপায়ে" ক্যাশে সংগঠিত করতে অতিরিক্ত সার্কিটরি লাগে এবং সাধারণত ধীর হয়ে যায়, সুতরাং (উদাহরণস্বরূপ) 8192-ওয়ে সেট অ্যাসোসিয়েটিভ ক্যাশে খুব কমই খুব ভাল সমাধান হয়।

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

  • মিথ্যা ভাগ করে নেওয়া

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


  1. যাঁরা সি ++++++++++++++++++++++++++++++++++++++++++++++++++ अन्यার अन्य টাইমস টাইপস টাইপস টেক্সট টেক্সট জাতীয় কিছু মাধ্যমে অপ্টিমাইজেশনের জন্য উন্মুক্ত কিনা তা অবাক করে দিতে পারে। আমি পুরোপুরি নিশ্চিত যে উত্তরটি হ্যাঁ, এটি করা যেতে পারে এবং যদি এটি হয় তবে এটি সম্ভবত একটি যথেষ্ট পরিমাণে জিততে হবে। আমি অবশ্য কারও দ্বারা এটি করেছে সে সম্পর্কে আমি সচেতন নই এবং কীভাবে সামান্য valarrayব্যবহার হয় তা দেওয়া হলেও আমি কারও পক্ষে এটি করে দেখে কমপক্ষে একটু অবাক হব।

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

  3. হ্যাঁ, আমি সরলীকরণ করছি: বেশিরভাগ ক্যাশে প্রকৃতপক্ষে সম্প্রতি ব্যবহৃত আইটেমটিকে সঠিকভাবে পরিমাপ করে না, তবে তারা প্রতিটি অ্যাক্সেসের জন্য পুরো সময়-স্ট্যাম্প না রেখেই কাছাকাছি থাকার উদ্দেশ্যে কিছু হিউরিস্টিক ব্যবহার করে।


1
আমি আপনার উত্তরের অতিরিক্ত টুকরো তথ্য বিশেষত valarrayউদাহরণটি পছন্দ করি।
মার্ক ক্লেসেন

1
+1 শেষ অবধি: সেট সাহসিকতার একটি সাধারণ বর্ণনা! আরও সম্পাদনা করুন: এটি এসও-র অন্যতম তথ্যমূলক উত্তর। ধন্যবাদ.
ইঞ্জিনিয়ার

32

ডেটা ওরিয়েন্টেড ডিজাইনের বিশ্বে আপনাকে স্বাগতম। মূল মন্ত্রটি বাছাই করা, শাখা বিলোপ করা, ব্যাচ করা, virtualকল সরিয়ে ফেলা - আরও ভাল লোকালয়ের দিকে সমস্ত পদক্ষেপ।

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


1
ব্যাচ বলতে কী বোঝাতে চাইলে কেউ বুঝতে পারে না।
0x90

5
ব্যাচিং: একক বস্তুর উপর কাজের একক সম্পাদনের পরিবর্তে এটি বস্তুর একটি ব্যাচে সম্পাদন করুন।
arul

একে একে ব্লক করা, রেজিস্টারগুলি ব্লক করা, ক্যাশে ব্লক করা।
0x90

1
অবরুদ্ধকরণ / অ-ব্লকিং সাধারণত বোঝায় যে কীভাবে অবজেক্টগুলি একই সাথে পরিবেশগত পরিবেশে আচরণ করে।
arul


23

কেবল পাইলিং: ক্যাশে-বন্ধুত্বপূর্ণ বনাম ক্যাশে-বান্ধব কোডের ক্লাসিক উদাহরণ হ'ল ম্যাট্রিক্স গুণনের "ক্যাশে ব্লকিং"।

নাইভ ম্যাট্রিক্স গুণমানটি দেখতে:

for(i=0;i<N;i++) {
   for(j=0;j<N;j++) {
      dest[i][j] = 0;
      for( k==;k<N;i++) {
         dest[i][j] += src1[i][k] * src2[k][j];
      }
   }
}

যদি Nবড় হয়, উদাহরণস্বরূপ যদি N * sizeof(elemType)ক্যাশে আকারের চেয়ে বড় হয় তবে এর প্রতিটি অ্যাক্সেস src2[k][j]ক্যাশে মিস হবে।

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

int itemsPerCacheLine = CacheLineSize / sizeof(elemType);

for(i=0;i<N;i++) {
   for(j=0;j<N;j += itemsPerCacheLine ) {
      for(jj=0;jj<itemsPerCacheLine; jj+) {
         dest[i][j+jj] = 0;
      }
      for( k=0;k<N;k++) {
         for(jj=0;jj<itemsPerCacheLine; jj+) {
            dest[i][j+jj] += src1[i][k] * src2[k][j+jj];
         }
      }
   }
}

যদি ক্যাশে লাইনের আকার by৪ বাইট হয় এবং আমরা 32 বিট (4 বাইট) ফ্লোটে অপারেট করছি তবে ক্যাশে লাইনে 16 টি আইটেম রয়েছে are এবং কেবল এই সাধারণ রূপান্তরটির মাধ্যমে ক্যাশে মিস করার সংখ্যাটি প্রায় 16 গুন কমেছে।

ফ্যানসিয়ার ট্রান্সফর্মেশনগুলি 2 ডি টাইলগুলিতে পরিচালিত হয়, একাধিক ক্যাশে (এল 1, এল 2, টিএলবি) এবং আরও কিছু জন্য অনুকূলিত হয়।

গুগলিং "ক্যাশে ব্লকিং" এর কিছু ফলাফল:

http://stumptown.cc.gt.atl.ga.us/cse6230-hpcta-fa11/slides/11a-matmul-goto.pdf

http://software.intel.com/en-us/articles/cache-blocking-techniques

একটি অনুকূলিতকরণ ক্যাশে ব্লক করা অ্যালগরিদমের একটি দুর্দান্ত ভিডিও অ্যানিমেশন।

http://www.youtube.com/watch?v=IFWgwGMMrh0

লুপ টাইলিং খুব ঘনিষ্ঠভাবে সম্পর্কিত:

http://en.wikipedia.org/wiki/Loop_tiling


7
যেসব লোকেরা এটি পড়েছে তারা ম্যাট্রিক্স গুণনের বিষয়ে আমার নিবন্ধে আগ্রহী হতে পারে যেখানে আমি "ক্যাশে-বান্ধব" ইকজে-অ্যালগরিদম এবং দুজনে বন্ধুত্বপূর্ণ ইজক-অ্যালগরিদম দুটি 2000x2000 ম্যাট্রিককে গুণ করে পরীক্ষা করেছি।
মার্টিন থোমা

3
k==;আমি আশা করছি এটি একটি টাইপো?
ট্রাবলডজে

13

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

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

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

ক্যাশে বন্ধুত্বপূর্ণ কোড অ্যাক্সেসগুলিকে মেমরির সাথে একত্রে রাখার চেষ্টা করে যাতে আপনি ক্যাসি মিস না করেন।

সুতরাং একটি উদাহরণ কল্পনা করা হবে যে আপনি একটি দৈত্য 2 মাত্রিক টেবিল অনুলিপি করতে চেয়েছিলেন। এটি স্মৃতিতে একটানা পৌঁছে যাওয়ার সারি দিয়ে সংগঠিত হয় এবং এক সারি পরের ডানদিকে অনুসরণ করে।

আপনি যদি বাম থেকে ডানে একসাথে উপাদানগুলিকে এক সারি অনুলিপি করেন - তবে এটি ক্যাশে বান্ধব হবে। আপনি যদি একবারে টেবিলটি একটি কলামে অনুলিপি করার সিদ্ধান্ত নেন, আপনি ঠিক একই পরিমাণ মেমরি অনুলিপি করবেন - তবে এটি বন্ধুত্বপূর্ণভাবে ক্যাশে হবে।


4

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

সাধারণত কোডটি হ্রাসকারী, এটি সংরক্ষণ করার জন্য কম ক্যাশে লাইন প্রয়োজন হবে। এর ফলে ফলাফলের জন্য আরও ক্যাশে লাইন পাওয়া যায়।

কোডটিকে সমস্ত জায়গায় ফাংশনগুলি কল করা উচিত নয় কারণ সাধারণত তাদের নিজস্ব এক বা একাধিক ক্যাশে লাইন প্রয়োজন হবে, ফলস্বরূপ ডেটার জন্য কম ক্যাশে লাইন তৈরি হবে।

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

কোডটি ঘন করার জন্য অতিরিক্ত কিছু সময় ব্যয় করুন। বিভিন্ন নির্মাণের পরীক্ষা করুন, উত্পন্ন কোডের আকার এবং প্রোফাইলটি সংকলন এবং পর্যালোচনা করুন।


2

যেমনটি @ মার্ক ক্লেসেন উল্লেখ করেছেন যে ক্যাশে ফ্রেন্ডলি কোড লেখার অন্যতম উপায় হ'ল আমাদের ডেটা সংরক্ষণ করা কাঠামোটি কাজে লাগানো। ক্যাশে বন্ধুত্বপূর্ণ কোড লেখার পাশাপাশি অন্য উপায়টি হ'ল: আমাদের ডেটা সংরক্ষণ করার পদ্ধতিটি পরিবর্তন করুন; তারপরে এই নতুন কাঠামোর মধ্যে থাকা ডেটা অ্যাক্সেস করতে নতুন কোড লিখুন।

এটি কীভাবে ডাটাবেস সিস্টেমগুলি কোনও টেবিলের টিপলগুলিকে রৈখিক করে তোলে এবং সংরক্ষণ করে sense একটি টেবিলের টিপলগুলি যেমন সারি স্টোর এবং কলাম স্টোর সংরক্ষণ করার জন্য দুটি প্রাথমিক উপায় রয়েছে। নাম হিসাবে সারি স্টোরটিতে টিপলগুলি সারি অনুযায়ী সংরক্ষণ করা হয়। ধরা যাক Productসঞ্চিত নামের একটি টেবিলটিতে 3 টি বৈশিষ্ট্য রয়েছে int32_t key, char name[56]এবং int32_t priceতাই, তাই একটি টুপলের মোট আকার 64বাইট।

আমরা Productমাপের মেমরির একটি খুব বেসিক সারি স্টোর ক্যোয়ারী এক্সিকিউশনকে সিমুলেট করতে পারি সাইজের এন দিয়ে স্ট্রাক্টের একটি অ্যারে তৈরি করে যেখানে এন টেবিলে সারিগুলির সংখ্যা। এ জাতীয় মেমরির বিন্যাসকে অ্যারে অফ স্ট্রাকসও বলা হয়। সুতরাং পণ্যের কাঠামো এর মতো হতে পারে:

struct Product
{
   int32_t key;
   char name[56];
   int32_t price'
}

/* create an array of structs */
Product* table = new Product[N];
/* now load this array of structs, from a file etc. */

একইভাবে আমরা Productটেবিলের প্রতিটি বৈশিষ্ট্যের জন্য একটি 3 টি আকারের এনআর তৈরি করে মূল মেমোরিতে একটি খুব বেসিক কলাম স্টোর ক্যোয়ারী এক্সিকিউশনটি অনুকরণ করতে পারি । এ জাতীয় মেমরি বিন্যাসকে অ্যারে স্ট্রাক্টও বলা হয়। সুতরাং পণ্যের প্রতিটি বৈশিষ্ট্যের জন্য 3 টি অ্যারে এর মতো হতে পারে:

/* create separate arrays for each attribute */
int32_t* key = new int32_t[N];
char* name = new char[56*N];
int32_t* price = new int32_t[N];
/* now load these arrays, from a file etc. */

এখন স্ট্রাক্টের অ্যারে (রো লেআউট) এবং 3 টি পৃথক অ্যারে (কলাম লেআউট) উভয় লোড করার পরে, Productআমাদের স্মৃতিতে উপস্থিত আমাদের টেবিলে সারি স্টোর এবং কলাম স্টোর রয়েছে ।

এখন আমরা ক্যাশে বন্ধুত্বপূর্ণ কোড অংশে চলেছি। মনে করুন যে আমাদের টেবিলের কাজের চাপটি এমন যে দামের গুণাবলীতে আমাদের একত্রিতকরণ কোয়েরি রয়েছে। যেমন

SELECT SUM(price)
FROM PRODUCT

সারি স্টোরের জন্য আমরা উপরের এসকিউএল কোয়েরিকে রূপান্তর করতে পারি

int sum = 0;
for (int i=0; i<N; i++)
   sum = sum + table[i].price;

কলাম স্টোরের জন্য আমরা উপরের এসকিউএল কোয়েরিকে রূপান্তর করতে পারি

int sum = 0;
for (int i=0; i<N; i++)
   sum = sum + price[i];

কলাম স্টোরের কোডটি এই ক্যোয়ারিতে সারি বিন্যাসের কোডের চেয়ে দ্রুততর হবে কারণ এটির জন্য কেবলমাত্র বৈশিষ্ট্যের একটি উপসেট প্রয়োজন এবং কলাম লেআউটে আমরা কেবল এটি করছি যা কেবল দামের কলামে অ্যাক্সেস করছে।

ধরা যাক ক্যাশে লাইনের আকার 64বাইট।

ক্যাশে লাইনটি যখন পড়বে সারি বিন্যাসের ক্ষেত্রে, কেবলমাত্র 1 ( cacheline_size/product_struct_size = 64/64 = 1) টিউপলের দামের মূল্য পড়বে, কারণ আমাদের স্ট্রাক্ট আকারটি 64 বাইট এবং এটি আমাদের পুরো ক্যাশে লাইনটি পূরণ করে, তাই প্রতিটি টুপলের জন্য একটি ক্যাশে মিস ঘটে case একটি সারি বিন্যাসের।

ক্যাশে লাইনটি যখন পড়বে তখন কলাম লেআউটের ক্ষেত্রে, 16 ( cacheline_size/price_int_size = 64/4 = 16) টিউপলসের মূল্যের মানটি পড়বে, কারণ মেমরিতে সঞ্চিত 16 টি স্বতন্ত্র মূল্যের মানগুলি ক্যাশে আনা হয়, সুতরাং প্রতি ষোড়শ টুপলের ক্ষেত্রে একটি ক্যাশে মিস ocurs হয় of কলাম লেআউট

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

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


1

সচেতন থাকুন যে ক্যাচগুলি কেবল অবিচ্ছিন্ন মেমরি ক্যাশে করে না। তাদের একাধিক লাইন রয়েছে (কমপক্ষে 4) তাই বিচ্ছিন্ন এবং ওভারল্যাপিং মেমরি প্রায়শই ঠিক দক্ষতার সাথে সঞ্চয় করা যায়।

উপরের সমস্ত উদাহরণ থেকে যা অনুপস্থিত তা হ'ল পরিমাপযোগ্য মানদণ্ড। অভিনয় সম্পর্কে অনেক কল্পকাহিনী রয়েছে। আপনি এটি পরিমাপ না করে আপনি জানেন না। আপনার কোনও পরিমাপযোগ্য উন্নতি না হলে আপনার কোডটিকে জটিল করবেন না ।

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