আমার প্রশ্নটি, যেহেতু আমি এই ক্ষেত্রেগুলিতে একবারে রৈখিকভাবে একটি স্বতন্ত্র অ্যারের পুনরাবৃত্তি করি না, তাই আমি কি অবিলম্বে এইভাবে উপাদানগুলি বরাদ্দ করা থেকে কর্মক্ষমতা লাভের ত্যাগ করছি?
সম্ভাবনাগুলি হ'ল আপনি "অনুভূমিক" ভেরিয়েবল-সাইজের ব্লকের কোনও সত্তার সাথে সংযুক্ত উপাদানগুলি ইন্টারলেভ করার চেয়ে কমপ্লেক্স টাইপ আলাদা আলাদা "উল্লম্ব" অ্যারে দিয়ে সামগ্রিকভাবে কম ক্যাশে মিস করবেন so
কারণটি হ'ল, প্রথমে "উল্লম্ব" প্রতিনিধিত্ব কম স্মৃতি ব্যবহার করার প্রবণতা রাখে। স্বতঃস্ফূর্তভাবে বরাদ্দযুক্ত সমজাত অ্যারেগুলির জন্য প্রান্তিককরণ সম্পর্কে আপনাকে চিন্তা করার দরকার নেই। মেমরি পুলে অ-সমজাতীয় ধরণের বরাদ্দের সাথে আপনাকে অ্যালাইমেন্ট সম্পর্কে চিন্তা করতে হবে কারণ অ্যারেতে প্রথম উপাদানটির দ্বিতীয় থেকে সম্পূর্ণ ভিন্ন আকার এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে পারে। ফলস্বরূপ আপনাকে প্রায়শই প্যাডিং যুক্ত করতে হবে, যেমন একটি সাধারণ উদাহরণ হিসাবে:
// Assuming 8-bit chars and 64-bit doubles.
struct Foo
{
// 1 byte
char a;
// 1 byte
char b;
};
struct Bar
{
// 8 bytes
double opacity;
// 8 bytes
double radius;
};
আসুন আমরা বইয়ের পাতার মাঝে মাঝে করতে চান Foo
এবং Bar
তাদের মেমরির সঠিক পরবর্তী প্রতিটি অন্যান্য দোকান:
// Assuming 8-bit chars and 64-bit doubles.
struct FooBar
{
// 1 byte
char a;
// 1 byte
char b;
// 6 bytes padding for 64-bit alignment of 'opacity'
// 8 bytes
double opacity;
// 8 bytes
double radius;
};
এখন পৃথক মেমরি অঞ্চলে ফু এবং বার সঞ্চয় করতে 18 বাইট নেওয়ার পরিবর্তে এগুলিকে ফিউজ করতে 24 বাইট লাগবে। আপনি অর্ডারটি অদলবদল করুন তা বিবেচ্য নয়:
// Assuming 8-bit chars and 64-bit doubles.
struct BarFoo
{
// 8 bytes
double opacity;
// 8 bytes
double radius;
// 1 byte
char a;
// 1 byte
char b;
// 6 bytes padding for 64-bit alignment of 'opacity'
};
আপনি যদি অ্যাক্সেসের ধরণগুলিতে উল্লেখযোগ্যভাবে উন্নতি না করে ক্রমিক অ্যাক্সেস প্রসঙ্গে আরও মেমরি গ্রহণ করেন, তবে সাধারণত আপনাকে আরও ক্যাশে মিস করবেন। একের সত্তা থেকে পরবর্তী বৃদ্ধি এবং একটি পরিবর্তনশীল আকারে পৌঁছানোর জন্য শীর্ষে, আপনাকে একটি সত্তা থেকে পরের দিকে যেতে মেমরিতে ভেরিয়েবল-সাইজের লাফগুলি নিতে হবে কেবল কোনটিতে আপনার উপাদান রয়েছে তা দেখতে ' আগ্রহী।
সুতরাং উপাদান উপাদান সংরক্ষণের জন্য "উল্লম্ব" প্রতিনিধিত্ব ব্যবহার করা আসলে "অনুভূমিক" বিকল্পগুলির চেয়ে অনুকূল হওয়ার সম্ভাবনা বেশি। এটি বলেছিল, উল্লম্ব উপস্থাপনের সাথে ক্যাশে মিস করা সমস্যাটি এখানে উদাহরণ দেওয়া যেতে পারে:
যেখানে তীরগুলি কেবল ইঙ্গিত দেয় যে সত্তা কোনও উপাদানটির "মালিকানাধীন"। আমরা দেখতে পাচ্ছি যে আমরা যদি উভয় সত্তার সমস্ত গতি এবং রেন্ডারিং উপাদানগুলিতে অ্যাক্সেস করার চেষ্টা করি তবে আমরা স্মৃতিতে সমস্ত স্থান জুড়ে শেষ করি। এই ধরণের বিক্ষিপ্ত অ্যাক্সেস প্যাটার্নটিতে আপনি কোনও গতি উপাদানকে অ্যাক্সেস করতে, বলতে, কোনও গতি উপাদানকে অ্যাক্সেস করতে, ক্যাশ লাইনে ডেটা লোড করতে পারেন এবং তারপরে আরও আগের উপাদানগুলি অকার্যকর করতে পারেন, কেবল একই মেমরি অঞ্চলটি আবার লোড করার জন্য যা ইতিমধ্যে অন্য গতির জন্য উচ্ছেদ করা হয়েছিল load উপাদান. সুতরাং যে একই মেমরি অঞ্চলগুলি একাধিকবার ক্যাশে লাইনে কেবল লুপটি লুপ এবং উপাদানগুলির তালিকার অ্যাক্সেসে লোড করা খুব অপব্যয়কর হতে পারে।
আসুন সেই জগাখিটি কিছুটা পরিষ্কার করুন যাতে আমরা আরও পরিষ্কারভাবে দেখতে পারি:
মনে রাখবেন যে আপনি যদি এই ধরণের দৃশ্যের মুখোমুখি হন তবে গেমটি চালানো শুরু হওয়ার অনেক পরে, অনেকগুলি উপাদান এবং সত্তা যুক্ত হয়ে সরিয়ে দেওয়ার পরে। সাধারণত যখন গেমটি শুরু হয়, আপনি সমস্ত সত্তা এবং প্রাসঙ্গিক উপাদানগুলি একসাথে যুক্ত করতে পারেন, যার পর্যায়ে তাদের কাছে খুব স্থানিক লোকাল সহ একটি খুব সুশৃঙ্খল, অনুক্রমিক অ্যাক্সেস প্যাটার্ন থাকতে পারে। যদিও অপসারণ এবং সন্নিবেশ প্রচুর পরে, আপনি উপরের জগাখিচুড়ি মত কিছু পেয়ে শেষ হতে পারে।
পরিস্থিতি উন্নতির একটি খুব সহজ উপায় হ'ল আপনার উপাদানগুলির মালিকানাধীন আইডি / সূচকগুলির উপর ভিত্তি করে আপনার উপাদানগুলি কেবল রেডিক্স করা। এই মুহুর্তে আপনি এই জাতীয় কিছু পান:
এবং এটি অনেক বেশি ক্যাশে-বান্ধব অ্যাক্সেস প্যাটার্ন। এটি নিখুঁত নয় যেহেতু আমরা দেখতে পাচ্ছি যে আমাদের সিস্টেমটি এখানে এবং সেখানে কিছু রেন্ডারিং এবং গতির উপাদানগুলি ছাড়তে হবে যেহেতু আমাদের সিস্টেমটি কেবলমাত্র উভয় ক্ষেত্রেই সত্ত্বায় আগ্রহী , এবং কিছু সংস্থার কেবল একটি গতি উপাদান রয়েছে এবং কিছুটির কেবল একটি রেন্ডারিং উপাদান রয়েছে , তবে আপনি অন্তত কিছু সংক্ষিপ্ত উপাদানগুলি প্রক্রিয়া করতে সক্ষম হবেন (সাধারণত অনুশীলনে সাধারণত, যেহেতু আপনি প্রায়শই আগ্রহের প্রাসঙ্গিক উপাদানগুলি সংযুক্ত করেন যেমন আপনার সিস্টেমে আরও সত্তা যেমন একটি গতি উপাদান রয়েছে তার তুলনায় একটি রেন্ডারিং উপাদান থাকবে) না).
সর্বাধিক গুরুত্বপূর্ণ, একবার এই বাছাই করা হয়ে গেলে, আপনি কেবল একটি লুপে পুনরায় লোড করতে কেবল কোনও মেমরি অঞ্চলকে ক্যাশে লাইনে ডেটা লোড করবেন না।
এবং এর জন্য খুব জটিল ডিজাইনের দরকার নেই, কেবলমাত্র একটি রৈখিক-সময় রেডিক্স সাজ্ট পাস এবং এখন, সম্ভবত আপনি কোনও নির্দিষ্ট উপাদান ধরণের জন্য একটি গুচ্ছ উপাদান সন্নিবেশ করিয়েছেন এবং সরিয়ে দেওয়ার পরে, আপনি এটিকে হিসাবে চিহ্নিত করতে পারেন বাছাই করা প্রয়োজন। যুক্তিযুক্ত-বাস্তবায়িত র্যাডিক্স সাজান (আপনি এটির সাথে সমান্তরাল করতে পারেন, যা আমি করি) আমার কোয়াড-কোর আই 7-তে প্রায় 6 মিলিয়ন মিলিয়ন উপাদানকে বাছাই করতে পারে, উদাহরণ হিসাবে এখানে:
Sorting 1000000 elements 32 times...
mt_sort_int: {0.203000 secs}
-- small result: [ 22 48 59 77 79 80 84 84 93 98 ]
mt_sort: {1.248000 secs}
-- small result: [ 22 48 59 77 79 80 84 84 93 98 ]
mt_radix_sort: {0.202000 secs}
-- small result: [ 22 48 59 77 79 80 84 84 93 98 ]
std::sort: {1.810000 secs}
-- small result: [ 22 48 59 77 79 80 84 84 93 98 ]
qsort: {2.777000 secs}
-- small result: [ 22 48 59 77 79 80 84 84 93 98 ]
উপরেরটি হ'ল একটি মিলিয়ন উপাদানগুলিকে 32 বার বাছাই করা হয়েছে ( memcpy
বাছাইয়ের আগে এবং পরে ফলাফলের সময় সহ )। এবং আমি ধরে নিচ্ছি যে বেশিরভাগ সময় আপনার কাছে বাছাই করার জন্য কোনও মিলিয়ন + উপাদান থাকবে না, সুতরাং আপনার খুব সহজেই এটিকে এখনই ও সেখানে লুকিয়ে রাখতে সক্ষম হওয়া উচিত যাতে কোনও লক্ষণীয় ফ্রেম রেট স্টাটার তৈরি না করে।