কাইলোটনের পরামর্শ প্রতিধ্বনি দেওয়ার মতো তবে আমি এটির পরামর্শ দেওয়ার সময় ডাটা কাঠামো স্তরে সমাধান করার পরামর্শ দিচ্ছি, আপনি যদি সহায়তা করতে পারেন তবে নিম্ন বরাদ্দ স্তরে নয়।
আপনি কীভাবে Foos
বারবার সংযুক্ত উপাদানগুলির সাথে গর্তযুক্ত একটি অ্যারে ব্যবহার করে বারবার বরাদ্দ দেওয়া এবং মুক্ত করা এড়াতে পারবেন তার একটি সাধারণ উদাহরণ ("বরাদ্দকারী" স্তরের পরিবর্তে "ধারক" স্তরে এটি সমাধান করা):
struct FooNode
{
explicit FooNode(const Foo& ielement): element(ielement), next(-1) {}
// Stores a 'Foo'.
Foo element;
// Points to the next foo available; either the
// next used foo or the next deleted foo. Can
// use SoA and hoist this out if Foo doesn't
// have 32-bit alignment.
int next;
};
struct Foos
{
// Stores all the Foo nodes.
vector<FooNode> nodes;
// Points to the first used node.
int first_node;
// Points to the first free node.
int free_node;
Foos(): first_node(-1), free_node(-1)
{
}
const FooNode& operator[](int n) const
{
return data[n];
}
void insert(const Foo& element)
{
int index = free_node;
if (index != -1)
{
// If there's a free node available,
// pop it from the free list, overwrite it,
// and push it to the used list.
free_node = data[index].next;
data[index].next = first_node;
data[index].element = element;
first_node = index;
}
else
{
// If there's no free node available, add a
// new node and push it to the used list.
FooNode new_node(element);
new_node.next = first_node;
first_node = data.size() - 1;
data.push_back(new_node);
}
}
void erase(int n)
{
// If the node being removed is the first used
// node, pop it from the used list.
if (first_node == n)
first_node = data[n].next;
// Push the node to the free list.
data[n].next = free_node;
free_node = n;
}
};
এই প্রভাবটির কিছু: একটি নিখরচায় তালিকা সহ একক-সংযুক্ত সূচক তালিকা। সূচী লিঙ্কগুলি আপনাকে মুছে ফেলা উপাদানগুলিকে ছাড়তে দেয়, ধ্রুবক সময়ে উপাদানগুলি সরিয়ে দেয় এবং ধ্রুবক-সময় সন্নিবেশ সহ ফ্রি উপাদানগুলি পুনরায় দাবি / পুনঃব্যবহার / ওভাররাইট করতে পারে। কাঠামোর মাধ্যমে পুনরাবৃত্তি করতে, আপনি এরকম কিছু করুন:
for (int index = foos.first_node; index != -1; index = foos[index].next)
// do something with foos[index]
এবং আপনি উপরের ধরণের "গর্তের সংযুক্ত অ্যারে" টেমপ্লেটগুলি ব্যবহার করে ডেটা স্ট্রাকচারকে সাধারণকরণ করতে পারেন, অনুলিপি বরাদ্দকরণের প্রয়োজনীয়তা এড়াতে নতুন বসানো এবং ম্যানুয়াল ডেটর অনুরোধ করতে পারেন, উপাদানগুলি সরিয়ে ফেলা হলে এটি ধ্বংসকারীদের ডাকতে পারেন, একটি ফরোয়ার্ড পুনরাবৃত্তি প্রদান করে I উদাহরণটি খুব সি-জাতীয় পছন্দটি ধারণাকে আরও স্পষ্টভাবে চিত্রিত করার জন্য রেখেছি এবং কারণ আমি খুব অলস।
এটি বলেছিল, আপনি মাঝখানে থেকে অনেকগুলি সরিয়ে এবং সন্নিবেশ করার পরে এই কাঠামোটি স্থানীয় অঞ্চলে হ্রাস পেতে থাকে। সেই মুহুর্তে next
লিঙ্কগুলি আপনাকে ভেক্টর ধরে সামনে এবং পিছনে হাঁটা করতে পারে, একই ক্রমবর্ধমান ট্র্যাভারসালের মধ্যে ক্যাশে লাইন থেকে পূর্বে নিষ্ক্রিয় করা ডেটা পুনরায় লোড করা যেতে পারে (এটি কোনও ডেটা স্ট্রাকচার বা বরাদ্দকারীর সাথে অনিবার্য যা পুনরায় দাবি করার সময় উপাদানগুলি পরিবর্তন না করে স্থির-সময় অপসারণের অনুমতি দেয়) ধ্রুবক-সময় সন্নিবেশ এবং সমান্তরাল বিটসেট বা removed
পতাকা হিসাবে কিছু ব্যবহার না করে মধ্য থেকে ফাঁকা স্থান । ক্যাশে-বন্ধুত্ব পুনরুদ্ধার করতে, আপনি এইভাবে একটি অনুলিপি কর্টর এবং অদলবদল প্রয়োগ করতে পারেন:
Foos(const Foos& other)
{
for (int index = other.first_node; index != -1; index = other[index].next)
insert(foos[index].element);
}
void Foos::swap(Foos& other)
{
nodes.swap(other.nodes):
std::swap(first_node, other.first_node);
std::swap(free_node, other.free_node);
}
// ... then just copy and swap:
Foos(foos).swap(foos);
এখন নতুন সংস্করণটি ক্র্যাশ করতে আবার ক্যাশে-বান্ধব। আর একটি পদ্ধতি হ'ল কাঠামোর মধ্যে সূচকের পৃথক তালিকা সঞ্চয় করে এবং পর্যায়ক্রমে সেগুলি সাজান। অন্যটি হ'ল কোন সূচকগুলি ব্যবহৃত হয় তা নির্দেশ করতে একটি বিটসেট ব্যবহার করা। এটি সর্বদা আপনার ক্রমবর্ধমান ক্রমে বিটসেটটি অতিক্রম করবে (দক্ষতার সাথে এটি করার জন্য, একবারে 64৪-বিটগুলি দেখুন যেমন এফএফএস / এফএফজেড ব্যবহার করে)। বিটসেটটি সর্বাধিক দক্ষ এবং অ-অনুপ্রবেশকারী, কোনটি ব্যবহৃত হয় এবং কোনটি 32-বিটের প্রয়োজনের পরিবর্তে অপসারণ করা হয় তা নির্দেশ করার জন্য উপাদানটির প্রতি মাত্র একটি সমান্তরাল বিটের প্রয়োজনnext
সূচকগুলির , তবে ভাল লেখার জন্য সবচেয়ে সময়সাপেক্ষ (এটি হবে না) ট্র্যাভারসালের জন্য দ্রুত হন যদি আপনি একবারে কিছুটা পরীক্ষা করে দেখেন - অধিকৃত সূচকগুলির ব্যাপ্তিগুলি দ্রুত নির্ধারণ করার জন্য আপনাকে 32+ বিটের মধ্যে অবিলম্বে একটি সেট বা আনসেট বিট খুঁজে পেতে এফএফএস / এফএফজেডের দরকার হয়)।
এই লিঙ্কযুক্ত সমাধানটি কার্যকরভাবে প্রয়োগ করা সবচেয়ে সহজ এবং অ-হস্তক্ষেপ ( Foo
কিছু removed
পতাকা সংরক্ষণের জন্য সংশোধন করার প্রয়োজন হয় না ) যা আপনি যদি 32-বিটকে কিছু মনে করেন না তবে কোনও ডাটা টাইপের সাথে কাজ করার জন্য এই ধারকটিকে সাধারণীকরণ করতে চাইলে সহায়ক helpful উপাদান প্রতি ওভারহেড
গতিশীল বরাদ্দের জন্য কি আমার কোনও মেমরি পুল তৈরি করা উচিত, বা এটি নিয়ে কোনও মাথা ঘামানোর দরকার নেই? লক্ষ্য প্ল্যাটফর্মটি যদি মোবাইল ডিভাইস হয়?
প্রয়োজন একটি শক্ত শব্দ এবং আমি রাইক্র্যাকিং, চিত্র প্রক্রিয়াকরণ, কণা সিমুলেশন এবং জাল প্রসেসিংয়ের মতো খুব কার্য সম্পাদন-সমালোচনামূলক ক্ষেত্রে কাজ করা পক্ষপাতদুষ্ট, তবে বুলেটগুলির মতো খুব হালকা প্রসেসিংয়ের জন্য ব্যবহৃত কিশোরী বস্তু বরাদ্দকরণ এবং মুক্ত করা তুলনামূলকভাবে অত্যন্ত ব্যয়বহুল is এবং পৃথকভাবে একটি সাধারণ উদ্দেশ্য, পরিবর্তনশীল আকারের মেমরি বরাদ্দকারী বিরুদ্ধে কণা। আপনি যে কোনও কিছু সংরক্ষণ করতে আপনার উপরের ডেটা স্ট্রাকচারকে সাধারণকরণ করতে সক্ষম হওয়া উচিত, আমি মনে করি প্রতিটি টিনএই জিনিসের জন্য অর্থ প্রদান থেকে সরাসরি এই জাতীয় স্তরের বরাদ্দ / নির্মূলকরণ ব্যয় নির্মূল করা সার্থক বিনিময় হতে পারে। বরাদ্দ / অবলম্বন ব্যয় হ্রাস করার শীর্ষে, আপনি ফলাফলগুলি অনুসরণ করে উল্লেখের তুলনায় আরও ভাল লোকেশন পাবেন (কম ক্যাশে মিস এবং পৃষ্ঠা ত্রুটি, অর্থাৎ)।
জোশ জিসি সম্পর্কে যা উল্লেখ করেছেন, আমি জা-এর মতো সি # এর জিসি বাস্তবায়ন খুব ঘনিষ্ঠভাবে অধ্যয়ন করি নি, তবে জিসি বরাদ্দকারীরা প্রায়শই একটি প্রাথমিক বরাদ্দ থাকেএটি খুব দ্রুত কারণ এটি একটি অনুক্রমিক বরাদ্দকারী ব্যবহার করছে যা মাঝারি থেকে স্মৃতি মুক্ত করতে পারে না (প্রায় একটি স্ট্যাকের মতো, আপনি জিনিসগুলি মাঝখানে তৈরি করতে পারবেন না)। তারপরে মেমরি অনুলিপি করে এবং সম্পূর্ণরূপে বরাদ্দ করা মেমরিটিকে সম্পূর্ণ আলাদা করে আলাদা আলাদা থ্রেডে পৃথক বস্তুগুলি সরিয়ে দেওয়ার জন্য ব্যয়বহুল ব্যয়গুলির জন্য অর্থ প্রদান করে (যেমন কোনও লিঙ্কযুক্ত কাঠামোর মতো কিছুতে ডেটা অনুলিপি করার সময় পুরো স্ট্যাকটি ধ্বংস করার মতো), এটি পৃথক থ্রেডে সম্পন্ন হওয়ার কারণে এটি অবশ্যই আপনার অ্যাপ্লিকেশনটির থ্রেডগুলি এত স্টল করে না। তবে, এটি প্রাথমিক জিসি চক্রের পরে অতিরিক্ত স্তরের ইন্ডিয়ারেশন এবং এলওআর-এর সাধারণ ক্ষতির খুব উল্লেখযোগ্য লুকানো ব্যয় বহন করে। বরাদ্দকে ত্বরান্বিত করার এটি অন্য কৌশল - এটি কলিং থ্রেডে সস্তা করুন এবং তারপরে অন্যটিতে ব্যয়বহুল কাজ করুন work তার জন্য আপনার পরিবর্তে আপনার অবজেক্টের রেফারেন্সের জন্য দুটি স্তরের ইন্ডিয়ারেশন দরকার কারণ এগুলি আপনার প্রাথমিকভাবে বরাদ্দ করা সময়ের এবং প্রথম চক্রের পরে স্মৃতিতে বদলে যাবে।
অনুরূপ শিরাতে থাকা অন্য কৌশল যা সি ++ এ প্রয়োগ করা একটু সহজ। একটি ডেটা স্ট্রাকচারের শেষে কেবল যুক্ত করা এবং যুক্ত করা যুক্ত করে রাখুন যা মাঝখানে থেকে জিনিসগুলি সরাতে দেয় না। তবে সেই বিষয়গুলি চিহ্নিত করুন যা অপসারণ করা দরকার। তারপরে একটি পৃথক থ্রেড সরানো উপাদানগুলি ছাড়াই একটি নতুন ডেটা কাঠামো তৈরির ব্যয়বহুল কাজের যত্ন নিতে পারে এবং তারপরে পরমাণুর সাথে পুরানোটির সাথে নতুনটি অদলবদল করে, উদাহরণস্বরূপ, বরাদ্দকরণ এবং তদারক উভয় মূল্যের ব্যয়ের বেশিরভাগই একটিকে দেওয়া যেতে পারে পৃথক থ্রেড যদি আপনি এমন ধারনা তৈরি করতে পারেন যে কোনও উপাদান অপসারণের জন্য অনুরোধ করা অবিলম্বে সন্তুষ্ট হওয়ার দরকার নেই। এটি কেবল আপনার থ্রেডের সাথে সম্পর্কিত হিসাবে নিখরচায়কেও কম সস্তা করে না তবে বরাদ্দকে আরও সস্তা করে তোলে, যেহেতু আপনি অনেক সহজ এবং ঘন ডেটা স্ট্রাকচার ব্যবহার করতে পারেন যা মাঝখান থেকে কখনও অপসারণের মামলাগুলি পরিচালনা করতে হয় না। এটি এমন ধারকটির মতো যা কেবল একটি প্রয়োজনpush_back
সন্নিবেশ জন্য ফাংশন, clear
সমস্ত উপাদান মুছে ফেলার জন্য একটি ফাংশন, এবং swap
মুছে ফেলা উপাদানগুলি বাদ দিয়ে একটি নতুন, কমপ্যাক্ট ধারক দিয়ে সামগ্রীগুলি অদলবদল করতে; এটাই যতদূর বদলে যায়।