পারফরম্যান্সের ভিত্তিতে সফটওয়্যারগুলির জন্য এই ওওপি কোনও অসুবিধা হতে পারে অর্থাৎ প্রোগ্রামাম কত দ্রুত চালায়?
প্রায়শই হ্যাঁ !!! কিন্তু ...
অন্য কথায়, অনেকগুলি বিভিন্ন অবজেক্টের মধ্যে অনেকগুলি রেফারেন্স, বা অনেক ক্লাসের অনেক পদ্ধতি ব্যবহার করে, "ভারী" বাস্তবায়ন হতে পারে?
অগত্যা। এটি ভাষা / সংকলকের উপর নির্ভর করে। উদাহরণস্বরূপ, একটি অনুকূল সি ++ সংকলক, আপনি যদি ভার্চুয়াল ফাংশন ব্যবহার না করেন তবে প্রায়শই আপনার অবজেক্টের ওভারহেড শূন্য হয়ে যায়। আপনি int
সেখানে কোনও মোড়ক লিখার মতো কাজ করতে পারেন বা কোনও সরল পুরানো পয়েন্টারটির উপরে স্কোপযুক্ত স্মার্ট পয়েন্টার যা সরাসরি এই সাধারণ পুরানো ডেটা টাইপগুলি সরাসরি ব্যবহার করার মতো দ্রুত সঞ্চালিত হয়।
জাভা এর মতো অন্যান্য ভাষায়, কোনও জিনিসের উপরে ওভারহেড কিছুটা থাকে (প্রায়শই বেশিরভাগ ক্ষেত্রে বেশ ছোট, তবে সত্যিকারের টিনেজ অবজেক্টগুলির সাথে কিছু বিরল ক্ষেত্রে জ্যোতির্বিদ্যাগত)। উদাহরণস্বরূপ, Integer
তুলনায় যথেষ্ট কম দক্ষ রয়েছে int
(64৪ বিটের 4 এর বিপরীতে 16 বাইট লাগে)। তবুও এটি কেবল নির্লজ্জ বর্জ্য বা এই ধরণের কিছু নয়। বিনিময়ে, জাভা প্রতিটি একক ব্যবহারকারী-সংজ্ঞায়িত টাইপের প্রতিফলনের মতো জিনিস সরবরাহ করে, পাশাপাশি চিহ্নিত কোনও ক্রিয়াকে ওভাররাইড করার ক্ষমতাও দেয় final
।
তবুও আসুন সেরা ক্ষেত্রে দেখুন: অনুকূলিতকরণ সি ++ সংকলক যা অবজেক্ট ইন্টারফেসকে শূন্য ওভারহেডে নেমে যেতে পারে । তারপরেও, ওওপি প্রায়শই কর্মক্ষমতা হ্রাস করে এবং এটিকে শীর্ষে পৌঁছাতে বাধা দেয় prevent এটি সম্পূর্ণ প্যারাডক্সের মতো শোনাতে পারে: এটি কীভাবে হতে পারে? সমস্যাটি নিহিত:
ইন্টারফেস ডিজাইন এবং এনক্যাপসুলেশন
সমস্যাটি হ'ল এমনকি যখন কোনও সংকলক কোনও অবজেক্টের কাঠামোকে শূন্য ওভারহেড পর্যন্ত স্কোয়াশ করতে পারে (যা কমপক্ষে সি ++ কম্পাইলারগুলির অনুকূলকরণের জন্য প্রায়শই সত্য) তখন জরিমানাযুক্ত জঞ্জালগুলির এনক্যাপসুলেশন এবং ইন্টারফেস ডিজাইন (এবং নির্ভরতা জমে থাকে) প্রায়শই প্রতিরোধ করে জনসাধারণকে একত্রিত করার উদ্দেশ্যে বস্তুর জন্য সর্বাধিক অনুকূল উপাত্ত উপস্থাপনা (যা প্রায়শই পারফরম্যান্স-সমালোচনামূলক সফ্টওয়্যার ক্ষেত্রে হয়)।
এই উদাহরণটি ধরুন:
class Particle
{
public:
...
private:
double birth; // 8 bytes
float x; // 4 bytes
float y; // 4 bytes
float z; // 4 bytes
/*padding*/ // 4 bytes of padding
};
Particle particles[1000000]; // 1mil particles (~24 megs)
আসুন আমাদের মেমরি অ্যাক্সেস প্যাটার্নটি হ'ল ধারাবাহিকভাবে এই কণাগুলির মধ্য দিয়ে লুপ করা এবং বারবার প্রতিটি ফ্রেমের চারদিকে ঘুরিয়ে দেওয়া, সেগুলি পর্দার কোণে সরিয়ে এবং তারপরে ফলাফলটি সরবরাহ করা nd
ইতিমধ্যে আমরা দেখতে পাচ্ছি যে 4 টি বাইট প্যাডিং ওভারহেড birth
সদস্যকে সঠিকভাবে সারিবদ্ধ করার জন্য প্রয়োজনীয় যখন কণাগুলি একত্রিত হয়ে যায়। ইতিমধ্যে। 16.7% মেমরির প্রান্তিককরণের জন্য ব্যবহৃত মৃত স্থানের সাথে নষ্ট হয়ে গেছে।
এটি মোটা মনে হতে পারে কারণ আজকাল আমাদের কাছে ডিআরএএম এর গিগাবাইট রয়েছে। তবুও আমাদের কাছে বর্তমানে সবচেয়ে প্রাণবন্ত মেশিনগুলি প্রায়শই কেবলমাত্র 8 মেগাবাইট থাকে যখন এটি সিপিইউ ক্যাশে (এল 3) এর সবচেয়ে ধীর এবং বৃহত্তম অঞ্চলে আসে । সেখানে আমরা যত কম ফিট করতে পারি, বারবার ডিআরএএম অ্যাক্সেসের ক্ষেত্রে আমরা এর জন্য তত বেশি অর্থ প্রদান করব এবং ধীর জিনিসগুলি পাওয়া যায়। হঠাৎ, 16.7% মেমরির অপচয় করা আর তুচ্ছ চুক্তির মতো মনে হয় না।
মাঠের সারিবদ্ধকরণের উপর কোনও প্রভাব ছাড়াই আমরা সহজেই এই ওভারহেডটি নির্মূল করতে পারি:
class Particle
{
public:
...
private:
float x; // 4 bytes
float y; // 4 bytes
float z; // 4 bytes
};
Particle particles[1000000]; // 1mil particles (~12 megs)
double particle_birth[1000000]; // 1mil particle births (~8 bytes)
এখন আমরা মেমোরিটি 24 মেগা থেকে 20 মেগ্রে হ্রাস করেছি। অনুক্রমের অ্যাক্সেস প্যাটার্ন সহ, মেশিনটি এখন এই ডেটাটি বেশ খানিকটা দ্রুত গ্রাস করবে।
তবে আসুন এই birth
ক্ষেত্রটি আরও কিছুটা কাছ থেকে দেখুন look ধরা যাক এটি কণার জন্মের সময় (তৈরি করা) শুরু হওয়ার সময়টি রেকর্ড করে। কল্পনা করুন ক্ষেত্রটি কেবল তখনই অ্যাক্সেস করা যায় যখন কোনও কণা প্রথম তৈরি করা হয় এবং প্রতি 10 সেকেন্ডে কোনও কণা মারা যায় এবং স্ক্রিনের এলোমেলো স্থানে পুনর্জন্ম হয় কিনা তা দেখার জন্য। সেক্ষেত্রে, birth
একটি ঠান্ডা ক্ষেত্র। এটি আমাদের কর্মক্ষমতা-সমালোচনামূলক লুপগুলিতে অ্যাক্সেস করা হয়নি।
ফলস্বরূপ, আসল পারফরম্যান্স-সমালোচনামূলক ডেটা 20 মেগাবাইট নয় তবে আসলে একটি 12-মেগাবাইট সংঘবদ্ধ ব্লক। আমরা প্রায়শই আসল উত্তপ্ত মেমরিটি অর্ধ আকারে সঙ্কুচিত হয়েছি ! আমাদের আসল, 24-মেগাবাইট সমাধানের তুলনায় উল্লেখযোগ্য গতি বাড়ানোর প্রত্যাশা করুন (এটি পরিমাপ করার দরকার নেই - ইতিমধ্যে এই ধরণের জিনিসটি হাজারবার সম্পন্ন করেছেন, তবে সন্দেহ হলে নিঃসঙ্কোচে)।
তবুও আমরা এখানে কি লক্ষ্য করুন। আমরা এই কণা বস্তুর এনক্যাপসুলেশনটি পুরোপুরি ভেঙে দিয়েছি। এর রাজ্যটি এখন কোনও Particle
প্রকারের ব্যক্তিগত ক্ষেত্র এবং পৃথক, সমান্তরাল অ্যারের মধ্যে বিভক্ত । এবং সেইদিকেই দানাদার অবজেক্ট-ওরিয়েন্টেড ডিজাইনটি পায়।
কোনও একক কণা, একক পিক্সেল, এমনকি একটি একক 4-উপাদান ভেক্টর, সম্ভবত এমনকি কোনও একক "প্রাণী" অবজেক্ট যেমন কোনও গেমের মধ্যে কোনও একক, খুব দানাদার বস্তুর ইন্টারফেস ডিজাইনের মধ্যে সীমাবদ্ধ থাকাকালীন আমরা সর্বোত্তম উপাত্তের উপস্থাপনাটি প্রকাশ করতে পারি না poss , ইত্যাদি ইত্যাদি যদি একটি চিতা গতি নষ্ট হয়ে যায় যদি এটি একটি দু: খিত দ্বীপে 2 বর্গ মিটার দূরে দাঁড়িয়ে থাকে এবং এটি খুব দানাদার বস্তু-ভিত্তিক নকশা প্রায়শই পারফরম্যান্সের ক্ষেত্রে করে। এটি উপ-অনুকূল প্রকৃতির সাথে ডেটা উপস্থাপনাকে সীমাবদ্ধ করে।
এটিকে আরও এগিয়ে নিতে, আসুন আমরা বলি যেহেতু আমরা কেবল কণাগুলি ঘুরিয়ে নিচ্ছি, আমরা আসলে তাদের এক্স / ওয়াই / জেড ক্ষেত্রটি তিনটি পৃথক লুপগুলিতে অ্যাক্সেস করতে পারি। সেক্ষেত্রে আমরা AVX রেজিস্টারগুলির সাথে সমান্তরালভাবে 8 এসপিএফপি অপারেশনগুলিকে ভেক্টরাইজ করতে পারি এমন এসএএ স্টাইলের সিমডি ইন্টারসিনিকগুলি থেকে উপকৃত হতে পারি। তবে এটি করার জন্য, আমাদের অবশ্যই এখন এই উপস্থাপনাটি ব্যবহার করতে হবে:
float particle_x[1000000]; // 1mil particle X positions (~4 megs)
float particle_y[1000000]; // 1mil particle Y positions (~4 megs)
float particle_z[1000000]; // 1mil particle Z positions (~4 megs)
double particle_birth[1000000]; // 1mil particle births (~8 bytes)
এখন আমরা কণা সিমুলেশন দিয়ে উড়ে চলেছি, তবে দেখুন আমাদের কণার নকশার কী হয়েছে। এটি সম্পূর্ণরূপে ধ্বংস করা হয়েছে, এবং আমরা এখন 4 টি সমান্তরাল অ্যারে খুঁজছি এবং এগুলি যা কিছু একটি করে সংগ্রহ করার কোনও বিষয় নেই। আমাদের অবজেক্ট অরিয়েন্টেড Particle
ডিজাইন চলে গেছে সাইওনারাতে।
পারফরম্যান্স-সমালোচনামূলক ক্ষেত্রগুলিতে কাজ করার এটি আমার সাথে অনেক সময় ঘটেছিল যেখানে ব্যবহারকারীরা কেবলমাত্র তার চেয়ে বেশি দাবি করার কারণে কেবল নির্ভুলতার সাথে গতি চায়। এই ছোট্ট টিনজি অবজেক্ট-ভিত্তিক ডিজাইনগুলি ভেঙে ফেলতে হয়েছিল এবং ক্যাসকেডিং ব্রেকগুলি প্রায়শই প্রয়োজন হত যে আমরা দ্রুত নকশার দিকে ধীর অবনতির কৌশলটি ব্যবহার করি।
সমাধান
উপরের দৃশ্যটি কেবল দানাদার অবজেক্ট-ওরিয়েন্টেড ডিজাইনগুলির সাথে একটি সমস্যা উপস্থাপন করে। সেক্ষেত্রে, আমরা প্রায়শই SoA reps, গরম / ঠান্ডা ক্ষেত্র বিভাজন, অনুক্রমিক অ্যাক্সেস নিদর্শনগুলির জন্য প্যাডিং হ্রাস ফলস্বরূপ আরও দক্ষ উপস্থাপনা প্রকাশ করার জন্য কাঠামোটি ভেঙে ফেলতে পারি (প্যাডিং কখনও কখনও এলোমেলো অ্যাক্সেসের সাথে পারফরম্যান্সের জন্য সহায়ক) এওএস ক্ষেত্রে নিদর্শনগুলি, তবে প্রায় সবসময় ক্রমযুক্ত প্রবেশাধিকারের জন্য বাধা) ইত্যাদি
তবুও আমরা সেই চূড়ান্ত উপস্থাপনাটি নিতে পারি যা আমরা স্থির করেছিলাম এবং এখনও একটি অবজেক্ট-ভিত্তিক ইন্টারফেসের মডেল করি:
// Represents a collection of particles.
class ParticleSystem
{
public:
...
private:
double particle_birth[1000000]; // 1mil particle births (~8 bytes)
float particle_x[1000000]; // 1mil particle X positions (~4 megs)
float particle_y[1000000]; // 1mil particle Y positions (~4 megs)
float particle_z[1000000]; // 1mil particle Z positions (~4 megs)
};
এখন আমরা ভাল। আমরা আমাদের পছন্দ মতো সমস্ত অবজেক্ট-ভিত্তিক গুডিজ পেতে পারি। চিতায় যত দ্রুত সম্ভব পারের পুরো দেশ জুড়ে রয়েছে। আমাদের ইন্টারফেস ডিজাইনগুলি আর আমাদেরকে কোনও বাধা কোণে আটকে রাখে না।
ParticleSystem
সম্ভাব্য এমনকি বিমূর্ত হতে পারে এবং ভার্চুয়াল ফাংশন ব্যবহার করতে পারে। এটি এখন গতিশীল, আমরা প্রতি-কণা স্তরের পরিবর্তে কণা স্তরের সংগ্রহের জন্য ওভারহেডের জন্য অর্থ প্রদান করছি । ওভারহেডটি 1 / 1,000,000 তম হ'ল যদি তা না হয় যদি আমরা স্বতন্ত্র কণা স্তরে বস্তুর মডেলিং করতাম।
সুতরাং এটি সত্যিকারের পারফরম্যান্স-সমালোচনামূলক ক্ষেত্রগুলির সমাধান যা একটি ভারী বোঝা পরিচালনা করে এবং সমস্ত ধরণের প্রোগ্রামিং ভাষার জন্য (এই কৌশলটি সি, সি ++, পাইথন, জাভা, জাভাস্ক্রিপ্ট, লুয়া, সুইফট ইত্যাদি সুবিধা দেয়)। এবং এটি সহজেই "অকাল অপ্টিমাইজেশন" হিসাবে লেবেল করা যায় না, কারণ এটি ইন্টারফেস ডিজাইন এবং আর্কিটেকচারের সাথে সম্পর্কিত । আমরা ক্লায়েন্টের উপর নির্ভরশীলতার একটি বোতল বোঝার সাথে একটি বস্তু হিসাবে একটি একক কণাকে মডেলিং করে একটি কোডবেস লিখতে পারি নাParticle's
সর্বজনীন ইন্টারফেস এবং তারপরে আমাদের মন পরিবর্তন করুন। উত্তরাধিকার কোডবেসগুলির অনুকূলকরণের জন্য ডাকা হওয়ার সময় আমি এটি অনেক করেছি এবং বাল্কিয়ার ডিজাইনটি সাবধানে কয়েক হাজার লাইনের কোডের পুনর্লিখন করতে কয়েক মাস সময় নিতে পারে। এটি আদর্শভাবে প্রভাবিত করে যাতে আমরা কীভাবে ভারী বোঝার প্রত্যাশা করতে পারি তা সামনে কীভাবে ডিজাইন করা হয়।
আমি এই উত্তরটি কোনও কোনও আকারে বা অন্য কোনও পারফরম্যান্স প্রশ্নে এবং বিশেষত যেগুলি অবজেক্ট-ওরিয়েন্টেড ডিজাইনের সাথে সম্পর্কিত সেগুলি প্রতিধ্বনি করে চলেছি। অবজেক্ট-ওরিয়েন্টেড ডিজাইন এখনও সর্বোচ্চ-চাহিদা কর্মক্ষমতা প্রয়োজনের সাথে সামঞ্জস্যপূর্ণ হতে পারে তবে এটি সম্পর্কে আমাদের কিছুটা চিন্তা করার উপায়টি পরিবর্তন করতে হবে। আমাদের সেই চিতাটিকে যত দ্রুত সম্ভব চালানোর জন্য কিছু জায়গা দিতে হবে, এবং আমরা যদি টিনি ছোট ছোট জিনিসগুলি সবেমাত্র যে কোনও রাজ্যের সঞ্চয় করে থাকি তবে এটি অসম্ভব।