কোনও সত্তা উপাদান সিস্টেম গেম ইঞ্জিনে সিপিইউ ক্যাশে থেকে কীভাবে উপকার পাবেন?


15

আমি প্রায়শই ইসিএস গেম ইঞ্জিন ডকুমেন্টেশনগুলিতে পড়ি যে সিপু ক্যাশে বুদ্ধিমানের সাথে ব্যবহারের জন্য একটি ভাল আর্কিটেকচার।

তবে আমি বুঝতে পারি না যে আমরা সিপিইউ ক্যাশে থেকে কীভাবে উপকৃত হতে পারি।

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

যখন আমরা সিস্টেমগুলি ব্যবহার করি, তখন তাদের সত্তা তালিকা দরকার যা সুনির্দিষ্ট ধরণের উপাদানযুক্ত উপাদানগুলির তালিকা।

তবে এই তালিকাগুলি অনুক্রমিকভাবে নয়, উপাদানগুলিকে এলোমেলো উপায়ে দেয়।

তাহলে ক্যাশে হিট সর্বাধিকীকরণের জন্য কীভাবে একটি ইসিএস ডিজাইন করবেন?

সম্পাদনা:

উদাহরণস্বরূপ, একটি ফিজিক সিস্টেমের সত্ত্বার জন্য সত্তার তালিকা দরকার যাতে রিগিডবডি এবং ট্রান্সফর্ম উপাদান রয়েছে (রিগিডবডি এর জন্য একটি পুল এবং ট্রান্সফর্ম উপাদানগুলির জন্য একটি পুল রয়েছে)।

সত্তা আপডেট করার জন্য এটির লুপটি এরকম হবে:

for (Entity eid in entitiesList) {
    // Get rigid body component
    RigidBody *rigidBody = entityManager.getComponentFromEntity<RigidBody>(eid);

    // Get transform component
    Transform *transform = entityManager.getComponentFromEntity<Transform>(eid);

    // Do something with rigid body and transform component
}

সমস্যাটি হ'ল ইন্টিটি 1 এর igগিডবডি উপাদানটি তার পুলের সূচী 2 এবং তার পুলের সূচী 0 তে ইন্টিটি 1 এর ট্রান্সফর্ম উপাদান হতে পারে (কারণ কিছু সংস্থার কিছু উপাদান থাকতে পারে এবং অন্যটি নাও থাকতে পারে এবং সত্তা যুক্ত / মোছার কারণে) / উপাদানগুলি এলোমেলোভাবে)

সুতরাং উপাদানগুলি মেমোরিতে সামঞ্জস্যপূর্ণ হলেও এগুলি এলোমেলোভাবে পড়া হয় এবং তাই এতে আরও ক্যাশে মিস থাকবে, না?

লুপের পরবর্তী উপাদানগুলি উপস্থাপনের উপায় না থাকলে?


আপনি কী আমাদের প্রতিটি উপাদান বরাদ্দ করতে পারেন তা আমাদের প্রদর্শন করতে পারেন?
ধারণা

পুলের উপাদানগুলি স্থানান্তরিতকরণের জন্য উপাদানগুলির রেফারেন্স থাকার জন্য একটি সাধারণ পুল বরাদ্দকারী এবং একটি হ্যান্ডেল ম্যানেজার সহ (উপাদানগুলিকে স্মৃতিতে ধারাবাহিক রাখতে)
জনফ

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

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

নিশ্চিত না যে এটিও প্রাসঙ্গিক হতে পারে? gamasutra.com/view/feature/6345/…
ডিএমগ্রিগরি

উত্তর:


13

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

ক্যাশে অপ্টিমাইজেশনের ক্ষেত্রে আরও নির্দিষ্ট, সি এবং সি ++ এর জন্য ক্রিসিটার এরিকসনের স্লাইড

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

যদি আপনার উপাদান (ডেটা) এর মধ্যে আন্তঃনির্ভরতা থাকে তবে এর সাথে সম্পর্কিত ডেটা থেকে আপনার কিছু ডেটা আলাদাভাবে ধারণ করার সামর্থ্য নেই (যেমন, ট্রান্সফর্ম + ফিজিক্স, ট্রান্সফর্ম + রেন্ডারার) তবে আপনি পদার্থবিজ্ঞান এবং রেন্ডারারের উভয় অ্যারে ট্রান্সফর্ম ডেটার প্রতিলিপি করতে বেছে নিতে পারেন , আশ্বাস দিয়ে যে সমস্ত প্রাসঙ্গিক ডেটা প্রতিটি কার্য সম্পাদন-সমালোচনামূলক ক্রিয়াকলাপের জন্য ক্যাশে লাইন প্রস্থের সাথে ফিট করে।

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

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


1
সি ++ এর ক্ষেত্রে নতুন হতে পারে এমন ব্যক্তির জন্য কেবল একটি নোট: std::vectorমূলত একটি গতিশীল-পুনঃআসাপযোগ্য অ্যারে এবং তাই এটিও সুসংহত (পুরানো সি ++ সংস্করণে ডি জ্যোটার এবং নতুন সি ++ সংস্করণে ডি জুরে)। এর কিছু বাস্তবায়ন std::deque"যথেষ্ট পরিমাণে" (যদিও মাইক্রোসফ্টের নয়)।
শান মিডলডিচ

2
@ জোহনফ্ফ সহজভাবে: আপনার কাছে স্থানীয় রেফারেন্স না থাকলে আপনার কাছে কিছুই নেই। যদি ডেটার দুটি টুকরো ঘনিষ্ঠভাবে সম্পর্কিত হয় (যেমন স্থানিক এবং পদার্থবিজ্ঞানের তথ্য), অর্থাৎ এগুলি একসাথে প্রক্রিয়াজাত করা হয়, তবে আপনাকে সেগুলি আন্তঃবিহীনভাবে একক উপাদান হিসাবে কমপ্যাক্ট করতে হতে পারে। তবে মনে রাখবেন যে অন্য যে কোনও যুক্তি (যেমন, এআই) যা স্থানিক ডেটার সাথে উপস্থাপিত হয় তার পরে স্থানিক ডেটা পাশাপাশি যুক্ত না হওয়ার ফলে ভুগতে পারে । সুতরাং এটি সর্বাধিক পারফরম্যান্সের প্রয়োজন হয় তার উপর নির্ভর করে (সম্ভবত আপনার ক্ষেত্রে পদার্থবিজ্ঞান)। যে জানার জন্য?
ইঞ্জিনিয়ার

1
@ জনম্ফ হ্যাঁ, আমি নিকের সাথে সম্পূর্ণরূপে একমত যে এগুলি কীভাবে মেমরিতে সঞ্চয় করা হয়, যদি আপনার কাছে স্থানীয় অঞ্চল নেই মেমোরিতে দূরে থাকা দুটি উপাদানগুলির পয়েন্টার সহ সত্তা থাকে তবে তাদের ক্যাশে লাইনে ফিট করতে হবে।
ধারণা

2
@ জনম্ফ: প্রকৃতপক্ষে, মিক ওয়েস্টের নিবন্ধটি ন্যূনতম আন্তঃনির্ভরতা ধরে নিয়েছে। সুতরাং: নির্ভরতা হ্রাস করুন; ক্যাশে লাইনগুলিতে ডেটা প্রতিলিপি করুন যেখানে আপনি সেই নির্ভরতা হ্রাস করতে পারবেন না ... যেমন রিগডবডি এবং রেন্ডার উভয়ের পাশাপাশি রূপান্তর অন্তর্ভুক্ত ; এবং ক্যাশে লাইনে ফিট করার জন্য, আপনার ডেটা অ্যাটমগুলি যথাসম্ভব কমিয়ে আনতে হবে ... এটি দশমিক পয়েন্টের মান প্রতি ভাসমান পয়েন্ট থেকে স্থির বিন্দু (4 বাইট বনাম 2 বাইট) এ অংশ অর্জিত হতে পারে। তবে এক উপায় বা অন্য কোনওভাবেই, আপনি এটি কীভাবেই করেন না কেন, সর্বাধিক কার্যকারিতার জন্য আপনার ডেটাটিকে ধারণাগুলি 3 ডি হিসাবে উল্লিখিত হিসাবে ক্যাশে লাইন প্রস্থের সাথে ফিট করতে হবে।
ইঞ্জিনিয়ার 21

2
@Johnmph। না। আপনি যখনই ট্রান্সফর্ম ডেটা লিখেন, আপনি কেবল এটি উভয় অ্যারেতে লিখুন। এটি আপনার লেখার জন্য উদ্বিগ্ন হওয়ার দরকার নেই। একবার আপনি কোনও লেখা পাঠিয়ে দিলে, এটি শেষের মতোই ভাল। এটি পদক্ষেপগুলি পরে রয়েছে, যখন আপনি পদার্থবিজ্ঞান এবং রেন্ডারার চালান, তখন অবশ্যই সিপিইউতে একক ক্যাশে লাইনের একক ক্যাশে লাইনে সমস্ত প্রাসঙ্গিক ডেটা অ্যাক্সেস থাকতে হবে। এছাড়াও, যদি আপনার সত্যিই এটির সমস্ত প্রয়োজন হয়, তবে আপনি হয় আরও প্রতিলিপিগুলি তৈরি করুন বা আপনি নিশ্চিত করেছেন যে পদার্থবিজ্ঞান, একটি একক ক্যাশে লাইনে রূপান্তর এবং রেন্ডার করুন ... by৪ বাইট সাধারণ এবং আসলে বেশ অনেকগুলি ডেটা! ...
প্রকৌশলী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.