ডেটা ওরিয়েন্টেড মাইন্ডসেট
ডেটা-ওরিয়েন্টেড ডিজাইনের অর্থ এই নয় যে সমস্ত জায়গায় SoA প্রয়োগ করুন। এর অর্থ হ'ল ডেটা উপস্থাপনের উপর প্রধানত ফোকাস সহ আর্কিটেকচার ডিজাইন করা - বিশেষত দক্ষ মেমরি লেআউট এবং মেমরি অ্যাক্সেসের উপর ফোকাস সহ।
এটি যথাযথভাবে উপযুক্ত হলে সম্ভবত এসএএর প্রতিনিধিত্ব করতে পারে:
struct BallSoa
{
vector<float> x; // size n
vector<float> y; // size n
vector<float> z; // size n
vector<float> r; // size n
};
... এটি প্রায়শই উল্লম্ব লুপী যুক্তিগুলির জন্য উপযুক্ত যা কোনও গোলক কেন্দ্রের ভেক্টর উপাদানগুলি এবং একসাথে ব্যাসার্ধের প্রক্রিয়া করে না (চারটি ক্ষেত্র একযোগে গরম হয় না), তবে পরিবর্তে একবারে (ব্যাসার্ধের মধ্য দিয়ে একটি লুপ, অন্য 3 টি লুপ) গোলক কেন্দ্রগুলির পৃথক উপাদানগুলির মাধ্যমে)।
অন্যান্য ক্ষেত্রে ক্ষেত্রগুলি ঘন ঘন একসাথে অ্যাক্সেস করা থাকলে (যদি আপনার লুপী যুক্তিটি পৃথকভাবে বলের পরিবর্তে বলের সমস্ত ক্ষেত্রের মধ্য দিয়ে ঘুরতে থাকে) এবং / অথবা যদি কোনও বলের এলোমেলো অ্যাক্সেস প্রয়োজন হয় তবে এওএস ব্যবহার করা আরও উপযুক্ত হবে:
struct BallAoS
{
float x;
float y;
float z;
float r;
};
vector<BallAoS> balls; // size n
... অন্যান্য ক্ষেত্রে এটি একটি হাইব্রিড ব্যবহার করা উপযুক্ত হতে পারে যা উভয় সুবিধার ভারসাম্য বজায় রাখে:
struct BallAoSoA
{
float x[8];
float y[8];
float z[8];
float r[8];
};
vector<BallAoSoA> balls; // size n/8
... আপনি আরও একটি বলের ক্ষেত্রটিকে ক্যাশে লাইন / পৃষ্ঠায় ফিট করতে অর্ধ-ফ্লোটগুলি ব্যবহার করে একটি বলের আকার অর্ধেক সঙ্কুচিত করতে পারেন।
struct BallAoSoA16
{
Float16 x2[16];
Float16 y2[16];
Float16 z2[16];
Float16 r2[16];
};
vector<BallAoSoA16> balls; // size n/16
... সম্ভবত এমনকি ব্যাসার্ধটি প্রায় গোলাকেন্দ্র হিসাবে প্রায় অ্যাক্সেস করা হয় না (সম্ভবত আপনার কোডবেস প্রায়শই পয়েন্টগুলির মতো আচরণ করে এবং কেবল বিরল ক্ষেত্র হিসাবে খুব কমই দেখা যায়)। সেক্ষেত্রে আপনি সম্ভবত একটি গরম / ঠান্ডা ফিল্ড বিভাজন কৌশল প্রয়োগ করতে পারেন।
struct BallAoSoA16Hot
{
Float16 x2[16];
Float16 y2[16];
Float16 z2[16];
};
vector<BallAoSoA16Hot> balls; // size n/16: hot fields
vector<Float16> ball_radiuses; // size n: cold fields
ডেটা-ওরিয়েন্টেড ডিজাইনের চাবিকাঠিটি হ'ল আপনার নকশার সিদ্ধান্ত নেওয়ার আগে এই ধরণের সমস্ত উপস্থাপনা বিবেচনা করা, এর পিছনে একটি সার্বজনীন ইন্টারফেস সহ নিজেকে উপ-অনুকূল প্রতিনিধিত্বের মধ্যে আটকা না করা।
এটি মেমোরি অ্যাক্সেসের ধরণগুলি এবং তার সাথে থাকা লেআউটগুলিতে স্পটলাইট রাখে যা এটিকে স্বাভাবিকের চেয়ে উল্লেখযোগ্যভাবে দৃ stronger় উদ্বেগ তৈরি করে। এক অর্থে এটি কিছুটা বিমূর্ততা ছিন্ন করতে পারে। আমি এই মানসিকতাকে আরও প্রয়োগ করে খুঁজে পেয়েছি যে আমি আর std::deque
এর অ্যালগোরিদমিক প্রয়োজনীয়তার দিক থেকে দেখতে পাচ্ছি না যতটা এটির সংযুক্ত কাঠের ব্লক প্রতিনিধিত্ব এবং মেমোরি স্তরে এর এলোমেলোভাবে অ্যাক্সেস কীভাবে কাজ করে। এটি কিছুটা বাস্তবায়নের বিশদগুলিতে ফোকাস দিচ্ছে, তবে বাস্তবায়ন বিশদ যা স্কেলিবিলিটি বর্ণনা করার কারণে অ্যালগোরিদমিক জটিলতার সাথে পারফরম্যান্সে ঠিক তত বেশি প্রভাব ফেলবে।
অকাল অপটিমাইজেশন
ডেটা-ওরিয়েন্টেড ডিজাইনের প্রচুর মূল লক্ষ্যটি প্রদর্শিত হবে, অন্তত এক নজরে, বিপজ্জনকভাবে অকাল অপটিমাইজেশনের কাছাকাছি। অভিজ্ঞতা প্রায়শই আমাদের শেখায় যে এই জাতীয় মাইক্রো-অপ্টিমাইজেশানগুলি হিন্দ্দৃষ্টিতে সর্বোত্তমভাবে প্রয়োগ করা হয় এবং একটি প্রোফাইলার হাতে রয়েছে।
তবুও সম্ভবত ডেটা-ওরিয়েন্টেড ডিজাইনের কাছ থেকে নেওয়া শক্তিশালী বার্তা হ'ল এই জাতীয়করণের জন্য জায়গা ছেড়ে যাওয়া। ডেটা-ভিত্তিক মানসিকতা এটিকে সহায়তা করতে পারে:
ডেটা-ওরিয়েন্টেড ডিজাইন আরও কার্যকর উপস্থাপনাগুলি অন্বেষণ করতে শ্বাস প্রশ্বাসের ঘর ছেড়ে যেতে পারে। এটি একসাথে মেমরি বিন্যাসের নিখুঁততা অর্জন সম্পর্কে নয়, ক্রমবর্ধমান-অনুকূল উপস্থাপনার অনুমতি দেওয়ার জন্য যথাযথ বিবেচনা করা আগে থেকেই করা more
গ্রানুলার অবজেক্ট-ওরিয়েন্টেড ডিজাইন
প্রচুর ডেটা-ওরিয়েন্টেড ডিজাইন আলোচনাগুলি অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ের শাস্ত্রীয় ধারণার বিরুদ্ধে দাঁড়াবে। তবুও আমি এটি দেখার একটি উপায় দেব যা পুরোপুরিভাবে ওওপি খারিজ করার মতো কঠিন নয়।
অবজেক্ট-ওরিয়েন্টেড ডিজাইনের সমস্যাটি হ'ল এটি আমাদের প্রায়শই খুব দানাদার স্তরে ইন্টারফেসগুলি মডেল করতে প্ররোচিত করে, আমাদের সমান্তরাল বাল্ক মানসিকতার পরিবর্তে স্কেলার, এক-সময়ে-সময়ে মানসিকতার সাথে আটকে রাখে।
অতিরঞ্জিত উদাহরণ হিসাবে, ভাবুন কোনও চিত্রের একক পিক্সেলের জন্য কোনও অবজেক্ট-ওরিয়েন্টেড ডিজাইন মানসিকতা প্রয়োগ করা হয়েছে।
class Pixel
{
public:
// Pixel operations to blend, multiply, add, blur, etc.
private:
Image* image; // back pointer to access adjacent pixels
unsigned char rgba[4];
};
আশা করি আসলে কেউই এটি করে না। উদাহরণটিকে সত্যই গুরুতর করার জন্য, আমি পিক্সেলযুক্ত চিত্রটিতে একটি ব্যাক পয়েন্টার সংরক্ষণ করেছি যাতে এটি অস্পষ্টতার মতো চিত্র প্রসেসিং অ্যালগরিদমের জন্য প্রতিবেশী পিক্সেলগুলিতে অ্যাক্সেস করতে পারে।
চিত্রের ব্যাক পয়েন্টারটি তাত্ক্ষণিকভাবে একটি চমকপ্রদ ওভারহেড যুক্ত করে, তবে আমরা এটিকে বাদ দিলেও (কেবল পিক্সেলের জনসাধারণের ইন্টারফেসকে একক পিক্সেলের সাথে প্রযোজ্য ক্রিয়াকলাপ সরবরাহ করে), আমরা কেবল একটি পিক্সেল উপস্থাপনের জন্য একটি ক্লাস দিয়ে শেষ করি।
এখন এই ব্যাক পয়েন্টার ব্যতীত C ++ প্রসঙ্গে তাত্ক্ষণিকভাবে ওভারহেড অর্থে কোনও শ্রেণীর সাথে কিছুই নেই। অপ্টিমাইজ করা সি ++ সংকলকগুলি আমাদের নির্মিত সমস্ত কাঠামো গ্রহণ করে এবং এটিকে স্মিথেনেন্সে নামিয়ে দেওয়ার ক্ষেত্রে দুর্দান্ত।
এখানে অসুবিধাটি হ'ল আমরা একটি পিক্সেল স্তরের খুব দানাদার একটি এনপ্যাপুলেটেড ইন্টারফেস মডেলিং করছি। এটি আমাদের এই ধরণের গ্রানুলার ডিজাইন এবং ডেটাতে আটকে রেখেছে, সম্ভাব্য সংখ্যক ক্লায়েন্ট নির্ভরতা তাদের এই Pixel
ইন্টারফেসে সংযুক্ত করে।
সমাধান: গ্রানুলার পিক্সেলের অবজেক্ট-ভিত্তিক কাঠামোটি বিলুপ্ত করুন এবং মোটা স্তরের পিক্সেলের (চিত্রের স্তরের) সাথে লেনদেন করার জন্য আপনার ইন্টারফেসগুলির মডেলিং শুরু করুন ing
বাল্ক ইমেজ স্তরে মডেলিংয়ের মাধ্যমে, আমাদের অনুকূলকরণের জন্য উল্লেখযোগ্যভাবে আরও জায়গা রয়েছে। আমরা উদাহরণস্বরূপ, বড় আকারের চিত্রগুলিকে 16x16 পিক্সেলের কোলেসড টাইল হিসাবে উপস্থাপন করতে পারি যা পুরোপুরি একটি 64-বাইট ক্যাশে লাইনের সাথে ফিট করে তবে একটি সাধারণ-ছোট স্ট্রাইড সহ পিক্সেলের দক্ষ প্রতিবেশী উল্লম্ব অ্যাক্সেসের অনুমতি দিতে পারে (যদি আমাদের বেশ কয়েকটি চিত্র প্রক্রিয়াকরণ অ্যালগরিদম থাকে তবে শক্তিশালী ডেটা-ভিত্তিক উদাহরণ হিসাবে প্রতিবেশী পিক্সেলগুলিকে উল্লম্ব ফ্যাশনে অ্যাক্সেস করা দরকার।
একটি মোটা স্তরে ডিজাইন করা
চিত্রের স্তরে মডেলিং ইন্টারফেসগুলির উপরের উদাহরণটি কোনও মস্তিষ্কের উদাহরণ নয় কারণ চিত্র প্রক্রিয়াকরণ একটি খুব পরিপক্ক ক্ষেত্র যা অধ্যয়ন করা হয়েছে এবং মৃত্যুর জন্য অনুকূলিত। তবুও কম স্পষ্টত কণা নির্গমনকারী একটি কণা হতে পারে, একটি স্প্রাইট বনাম স্প্রাইটের সংগ্রহ, প্রান্তের গ্রাফের একটি প্রান্ত, এমনকি কোনও ব্যক্তি বনাম কোনও লোকের সংগ্রহও হতে পারে।
ডেটা-ওরিয়েন্টেড অপ্টিমাইজেশনের (দূরদর্শিতা বা হ্যান্ডসাইটে) অনুমতি দেওয়ার মূল কীটি প্রায়শই প্রচুর পরিমাণে মোটা স্তরে ইন্টারফেসগুলি ডিজাইন করতে সিদ্ধ হতে চলেছে। একক সত্তার জন্য ইন্টারফেস ডিজাইনের ধারণাটি বড় ক্রিয়াকলাপের সাথে সত্তা সংগ্রহের জন্য নকশার মাধ্যমে প্রতিস্থাপিত হয় যা তাদের প্রচুর পরিমাণে প্রক্রিয়া করে। এটি বিশেষত এবং তাত্ক্ষণিকভাবে ক্রমযুক্ত অ্যাক্সেস লুপগুলিকে লক্ষ্য করে যেগুলিতে সমস্ত কিছু অ্যাক্সেস করা দরকার এবং লিনিয়ার জটিলতা থাকতে পারে না।
ডেটা-ওরিয়েন্টেড ডিজাইনটি প্রায়শই বিপুল পরিমাণে মডেলিংয়ের ডেটা তৈরির জন্য ডেটা কোলেসিংয়ের ধারণা দিয়ে শুরু হয়। অনুরূপ মানসিকতা ইন্টারফেস ডিজাইনের প্রতিধ্বনি করে যা এর সাথে থাকে।
ডেটা-ওরিয়েন্টড ডিজাইন থেকে নেওয়া এটিই সর্বাধিক মূল্যবান পাঠ, যেহেতু আমি কম্পিউটার আর্কিটেকচার-বুদ্ধিমান না হয়ে প্রায়শই আমার প্রথম চেষ্টাতে কোনও কিছুর জন্য সর্বাধিক অনুকূল মেমরির বিন্যাস খুঁজে পাই। এটি এমন একটি হয়ে ওঠে যা আমি হাতে প্রফেসর (এবং মাঝে মাঝে কিছুটা মিস করে যেখানে জিনিসগুলিকে গতিতে ব্যর্থ করেছিলাম সেদিকে ঝুঁকির সাথে) towards তবুও ডেটা-ওরিয়েন্টেড ডিজাইনের ইন্টারফেস ডিজাইনের দিকটি হ'ল যা আমাকে আরও এবং আরও দক্ষ ডেটা উপস্থাপনের জন্য জায়গা করে দেয় room
কীটি হ'ল আমাদের সাধারণত প্রলুব্ধ করার চেয়ে মোটা স্তরে ইন্টারফেসগুলি ডিজাইন করা। ভার্চুয়াল ফাংশন, ফাংশন পয়েন্টার কলস, ডাইলিব কল এবং তাদের অন্তর্ভুক্ত হওয়ার অক্ষমতার সাথে যুক্ত ডায়নামিক প্রেরণা ওভারহেড প্রশমিত করার মতো পার্শ্ব সুবিধাও এর প্রায়শই রয়েছে। এই সমস্ত কিছু বের করার মূল ধারণাটি হ'ল বাল্ক ফ্যাশনে প্রসেসিং করা (যখন প্রযোজ্য হয়)।
ball->do_something();
বনামball_table.do_something(ball)
) ব্যবহার করা কৃপণ হয়ে ওঠে(&ball_table, index)
।