বিশাল অ্যারে পূরণ না করে একটি বড় সমস্যা উত্পাদন করার পেশাদার উপায়: সি ++, অ্যারের অংশ থেকে বিনামূল্যে মেমরি


20

আমি একটি পদার্থবিজ্ঞানের সিমুলেশন বিকাশ করছি এবং আমি প্রোগ্রামিংয়ের পরিবর্তে নতুন হয়ে থাকি, বড় প্রোগ্রামগুলি তৈরি করার সময় আমি সমস্যার মধ্যে পড়ে যাই (মূলত স্মৃতি বিষয়গুলি)। আমি ডায়নামিক মেমোরি বরাদ্দ এবং মুছে ফেলার (নতুন / মুছে ফেলা ইত্যাদি) সম্পর্কে জানি, তবে আমি কীভাবে প্রোগ্রামটি কাঠামোগত করি তার জন্য আমার আরও ভাল পদ্ধতির প্রয়োজন।

ধরা যাক, আমি একটি পরীক্ষার নমুনা দিচ্ছি যা বেশ কয়েকটি বড় নমুনা হারের সাথে কয়েক দিনের জন্য চলছে। আমার এক বিলিয়ন নমুনা অনুকরণ করতে হবে এবং সেগুলি দিয়ে চালানো দরকার।

একটি অতি-সরল সংস্করণ হিসাবে, আমরা বলব যে একটি প্রোগ্রাম ভোল্টেজ ভি [i] নেয়, এবং তাদের যোগফলকে পাঁচ দশকে:

যেমন নিউভিউ [0] = ভি [0] + ভি [1] + ভি [2] + ভি [3] + ভি [৪]

তারপরে NewV [1] = ভি [1] + ভি [2] + ভি [3] + ভি [4] + ভি [5]

তারপরে NewV [2] = ভি [2] + ভি [3] + ভি [4] + ভি [5] + ভি [6] ... এবং এটি এক বিলিয়ন নমুনায় চলেছে।

শেষ অবধি, আমার কাছে ভি [0], ভি [1], ..., ভি [1000000000] থাকতে হবে, যখন কেবলমাত্র পরবর্তী পদক্ষেপের জন্য আমার সংরক্ষণ করতে হবে কেবলমাত্র শেষ 5 ভি [i] গুলি।

আমি অ্যারের অংশটি কীভাবে মুছে ফেলব / ডিলোকল্ট করব যাতে মেমরিটি আবার ব্যবহারের জন্য নিখরচায় থাকে (উদাহরণের প্রথম অংশের পরে ভি [0] বলুন যেখানে এটির আর প্রয়োজন নেই)? কীভাবে এই জাতীয় প্রোগ্রাম গঠনের বিকল্প রয়েছে?

আমি ম্যালোক / ফ্রি সম্পর্কে শুনেছি, তবে শুনেছি সেগুলি সি ++ এ ব্যবহার করা উচিত নয় এবং এর চেয়ে আরও ভাল বিকল্প রয়েছে।

অনেক ধন্যবাদ!

tldr; অ্যারের অংশগুলি (স্বতন্ত্র উপাদান) দিয়ে কী করব আমার আর দরকার নেই যা বিপুল পরিমাণ স্মৃতি গ্রহণ করছে?


2
আপনি কোনও অ্যারের অংশটি অপসারণ করতে পারবেন না। আপনি এটিকে অন্য কোথাও একটি ছোট অ্যারেতে পুনরায় বরাদ্দ করতে পারেন তবে এটি ব্যয়বহুল প্রমাণিত হতে পারে। পরিবর্তে আপনি সম্ভবত কোনও লিঙ্কযুক্ত তালিকার মতো একটি আলাদা ডেটা কাঠামো ব্যবহার করতে পারেন। হতে পারে আপনি পদক্ষেপগুলিকে Vনতুন অ্যারের পরিবর্তে সংরক্ষণ করতে পারেন । মৌলিকভাবে, যদিও আমি মনে করি আপনার সমস্যাটি হয় আপনার অ্যালগরিদমে বা আপনার ডেটা স্ট্রাকচারে রয়েছে এবং যেহেতু আমাদের কোনও বিবরণ নেই তাই এটি কীভাবে দক্ষতার সাথে করা যায় তা জানা শক্ত।
ভিনসেন্ট সাভার্ড

4
পার্শ্ব দ্রষ্টব্য: স্বেচ্ছাসেবী দৈর্ঘ্যের এসএমএ'র এই পুনরাবৃত্ত সম্পর্কের সাথে বিশেষ করে দ্রুত গণনা করা যেতে পারে: নিউভি [এন] = নিউভি [এন-1] - ভি [এন -1] + ভি [এন + 4] (আপনার স্বরলিপি)। তবে মনে রাখবেন যে এগুলি বিশেষভাবে কার্যকর ফিল্টার নয়। তাদের ফ্রিকোয়েন্সি প্রতিক্রিয়া একটি সিনক, যা আপনি যা চান তা খুব বেশি নয় (সত্যই উচ্চ সিডেলোবস)।
স্টিভ কক্স

2
SMA = সহজ চলমান গড়, যে কারও জন্য অবাক হচ্ছেন।
চার্লস

3
@ স্টিভকক্স, তিনি যেভাবে লিখেছেন, তিনি একটি এফআইআর ফিল্টার পেয়েছেন। আপনার পুনরাবৃত্তি সমতুল্য আইআইআর ফর্ম। যেভাবেই হোক, আপনি সর্বশেষ এন রিডিংয়ের একটি বিজ্ঞপ্তি বাফার বজায় রাখতে পারেন।
জন আর স্ট্রোহম

@ জনআর.স্ট্রোহম অনুপ্রেরণার প্রতিক্রিয়াটি অভিন্ন এবং সসীম
স্টিভ কক্স

উত্তর:


58

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

আপনি আপনার সংগৃহীত ডেটাটি ডিস্কে রেখে দিতে পারেন unch

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


6
একটি বিজ্ঞপ্তি বাফারটি মনে হচ্ছে যা আমি খুঁজছি! আমি এখন বুস্ট সি ++ লাইব্রেরি ইনস্টল করেছি এবং বুস্ট / সার্কুলার_ব্ফার.ইচপি অন্তর্ভুক্ত করেছি এবং প্রত্যাশা অনুযায়ী কাজ করছি। ধন্যবাদ, @John
Drummermean

2
কেবলমাত্র খুব সংক্ষিপ্ত এফআইআর ফিল্টারগুলি সফ্টওয়্যারটিতে সরাসরি আকারে প্রয়োগ করা হয় এবং এসএমএ এর প্রায় কখনও হয় না।
স্টিভ কক্স

@ স্টিভকক্স: আপনি যে উইন্ডো উইন্ডো সূত্রটি ব্যবহার করেছেন এটি পূর্ণসংখ্যা এবং স্থির-পয়েন্ট ফিল্টারগুলির জন্য বেশ কার্যকর, তবে এটি ভাসমান-পয়েন্টের জন্য ভুল, যেখানে ক্রিয়াকলাপগুলি পরিবহণযোগ্য নয়।
বেন ভয়েগট

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

আপনি ব্যবহারের জন্য বৃত্তাকার বাফারের জন্য সত্যই আপনার দরকার নেই আপনি প্রয়োজনের তুলনায় অনেক বেশি মেমরি ব্যবহার করবেন।
গেম ডেভেলপার

13

প্রতিটি সমস্যা ইন্ডিয়ারেশনের একটি অতিরিক্ত স্তর যুক্ত করে সমাধান করা যেতে পারে। সুতরাং যে।

আপনি C ++ এ অ্যারের অংশ মুছতে পারবেন না। তবে আপনি যে ডেটা রাখতে চান কেবল তা ধারণ করে আপনি একটি নতুন অ্যারে তৈরি করতে পারেন, তারপরে পুরানোটি মুছুন। সুতরাং আপনি এমন একটি ডেটা স্ট্রাকচার তৈরি করতে পারেন যা আপনাকে সামনে থেকে চান না এমন উপাদানগুলিকে "অপসারণ" করতে দেয়। এটি আসলে যা করবে তা হ'ল একটি নতুন অ্যারে তৈরি করা এবং অবিক্রিত উপাদানগুলিকে নতুনটিতে অনুলিপি করা, তারপরে পুরানোটি মুছুন।

অথবা আপনি কেবল ব্যবহার করতে পারেন std::deque, যা কার্যকরভাবে এটি ইতিমধ্যে করতে পারে। deque, বা "ডাবল-এন্ড ক্যু" হ'ল এমন একটি ডাটা স্ট্রাকচার যা আপনি যখন অন্য প্রান্তে উপাদান যুক্ত করার সময় এক প্রান্ত থেকে উপাদানগুলি মুছছেন।


30
প্রতিটি স্তরের ইন্ডিরিশনের অতিরিক্ত স্তর বাদে অতিরিক্ত স্তরের ইন্ডিয়ারেশান যুক্ত করে সমাধান করা যেতে পারে
ওয়াইএসসি

17
@ ওয়াইএসসি: এবং বানান :)
মনিকার সাথে লাইটনেস রেস

1
এই বিশেষ সমস্যার std::dequeজন্য যাওয়ার উপায়
ডেভিডবাক

7
@ ডেভিডবাক - কি? মেমরির ক্রমাগত বরাদ্দ এবং প্রকাশ করার দরকার নেই। আরম্ভের সময় একবারে বরাদ্দ করা একটি স্থির আকারের বিজ্ঞপ্তি বাফার এই সমস্যার তুলনায় আরও ভাল ফিট।
ডেভিড হামেন

2
@ ডেভিডহ্যামেন: সম্ভবত, তবে 1) স্ট্যান্ডার্ড লাইব্রেরির টুলকিটে একটি "স্থির আকারের বিজ্ঞপ্তি বাফার" নেই। 2) আপনার যদি সত্যিই এইরকম অপটিমাইজেশন প্রয়োজন হয় তবে আপনি কিছু বরাদ্দকারী স্টাফের মাধ্যমে পুনঃনির্ধারণগুলি হ্রাস করতে পারেন deque। অর্থাৎ অনুরোধ অনুসারে বরাদ্দ সংরক্ষণ এবং পুনরায় ব্যবহার- সুতরাং dequeসমস্যার পুরোপুরি পর্যাপ্ত সমাধান বলে মনে হচ্ছে।
নিকল বোলাস 25'17

4

আপনার কাছে পাওয়া এফআইআর এবং এসএমএ উত্তরগুলি আপনার ক্ষেত্রে ভাল, তবে আমি আরও জেনেরিক পদ্ধতির দিকে এগিয়ে যাওয়ার সুযোগটি নিতে চাই।

আপনার কাছে যা আছে তা উপাত্তের স্ট্রিম : আপনার প্রোগ্রামটি 3 টি বড় ধাপে স্ট্রাকচার করার পরিবর্তে (ডেটা, গণনা, আউটপুট ফলাফল পান) যা মেমরিতে একবারে সমস্ত ডেটা লোড করা প্রয়োজন, আপনি পরিবর্তে এটি পাইপলাইন হিসাবে কাঠামো করতে পারেন ।

একটি পাইপলাইন একটি স্রোতের সাথে শুরু হয়, এটিকে রূপান্তর করে এবং এটি একটি ডোবাতে ঠেলে দেয়।

আপনার ক্ষেত্রে, পাইপলাইনটি দেখে মনে হচ্ছে:

  1. ডিস্ক থেকে আইটেমগুলি পড়ুন, একবারে আইটেমগুলি নির্গত করুন
  2. একবারে একটি করে আইটেম গ্রহণ করুন, প্রাপ্ত প্রতিটি আইটেমের জন্য প্রাপ্ত সর্বশেষ 5 টি নির্গত হয় (যেখানে আপনার বিজ্ঞপ্তি বাফার আসে)
  3. প্রতিটি গ্রুপের ফলাফলের গণনা করার জন্য একবারে 5 টি আইটেম গ্রহণ করুন
  4. ফলাফল গ্রহণ করুন, এটি ডিস্কে লিখুন

সি ++ স্ট্রিমের পরিবর্তে পুনরাবৃত্তকারী ব্যবহার করে, তবে সত্যিকারের স্ট্রিমগুলি মডেল করা সহজতর ( রেঞ্জগুলির জন্য একটি প্রস্তাব রয়েছে যা স্রোতের সাথে সমান হবে):

template <typename T>
class Stream {
public:
    virtual boost::optional<T> next() = 0;
    virtual ~Stream() {}
};

class ReaderStream: public Stream<Item> {
public:
    boost::optional<Item> next() override final;

private:
    std::ifstream file;
};

class WindowStream: public Stream<Window> {
public:
    boost::optional<Window> next() override final;

private:
    Window window;
    Stream<Item>& items;
};

class ResultStream: public Stream<Result> {
public:
    boost::optional<Result> next() override final;

private:
    Stream<Window>& windows;
};

এবং তারপরে, পাইপলাইনটি দেখতে দেখতে:

ReaderStream itemStream("input.txt");
WindowStream windowStream(itemsStream, 5);
ResultStream resultStream(windowStream);
std::ofstream results("output.txt", std::ios::binary);

while (boost::optional<Result> result = resultStream.next()) {
    results << *result << "\n";
}

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


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

যদি সিপিইউ হ'ল বাধা (এবং আমি / ও নয়), তবে আপনি প্রায় সমান পরিমাণে ফাইলগুলি বিভক্ত করার পরে আপনার কাছে প্রতি একক প্রক্রিয়া চালু করে এটির গতি বাড়িয়ে তুলতে পারবেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.