ইন-প্লেস রেডিক্স বাছাই করুন


200

এটি একটি দীর্ঘ পাঠ্য। আমার সাথে সহ্য করুন। সিদ্ধ হয়ে, প্রশ্নটি হল: কোনও কার্যক্ষম স্থানে র‌্যাডিক্স সাজানোর অ্যালগরিদম আছে ?


প্রারম্ভিক

আমি একটি বিশাল সংখ্যক স্থির দৈর্ঘ্যের স্ট্রিং পেয়েছি যা কেবলমাত্র "এ", "সি", "জি" এবং "টি" অক্ষর ব্যবহার করে (হ্যাঁ, আপনি এটি অনুমান করেছেন: ডিএনএ ) যা আমি বাছাই করতে চাই।

এই মুহুর্তে, আমি ব্যবহার করি std::sortযা এসটিএল এর সমস্ত সাধারণ বাস্তবায়নে অন্তঃকরণ ব্যবহার করে । এটি বেশ ভাল কাজ করে। যাইহোক, আমি নিশ্চিত যে রেডিক্স বাছাই আমার সমস্যাটি পুরোপুরি ঠিক করে দেয় এবং অনুশীলনে আরও ভালভাবে কাজ করা উচিত ।

বিস্তারিত

আমি এই অনুমানটিকে খুব নিখুঁত বাস্তবায়নের সাথে পরীক্ষা করেছি এবং তুলনামূলকভাবে ছোট ইনপুটগুলির জন্য (10,000 এর আদেশে) এটি সত্য ছিল (ভাল, কমপক্ষে দ্বিগুণের চেয়ে দ্রুত হিসাবে)। তবে সমস্যাটির আকার বড় হয়ে গেলে রানটাইম অত্যন্ত অস্বাভাবিকভাবে হ্রাস পায় ( এন > 5,000,000)।

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

ব্যবহারের ক্ষেত্রে

আদর্শভাবে, এই অ্যালগরিদম ডিএনএ সেইসাথে DNA5, অথবা এমনকি ডিএনএ (যা একটি অতিরিক্ত ওয়াইল্ডকার্ড অক্ষর "N" মানে মঞ্জুর করে), 2 এবং 100 এর মধ্যে কোন স্ট্রিং দৈর্ঘ্য সঙ্গে কাজ করা উচিত IUPAC অস্পষ্টতা কোড (16 স্বতন্ত্র মান ফলে)। যাইহোক, আমি বুঝতে পারি যে এই সমস্ত ক্ষেত্রে আচ্ছাদন করা যায় না, তাই আমি যে কোনও গতির উন্নতি পেয়ে খুশি। কোডটি অ্যালগরিদম কোনটি প্রেরণ করবে তা গতিময় সিদ্ধান্ত নিতে পারে।

গবেষণা

দুর্ভাগ্যক্রমে, রেডিক্স সাজানোর উইকিপিডিয়া নিবন্ধটি অকেজো। ইন-প্লেস ভেরিয়েন্ট সম্পর্কে বিভাগটি সম্পূর্ণ আবর্জনা। র্যাডিক্স উপর, NIST-পিতাকেও অধ্যায় সাজানোর অবাস্তব পরবর্তী। দক্ষ অ্যাডাপটিভ ইন-প্লেস রেডিক্স বাছাই করা নামে একটি প্রতিশ্রুতিশীল-সাউন্ডিং পেপার রয়েছে যা "এমএসএল" অ্যালগরিদমকে বর্ণনা করে। দুর্ভাগ্যক্রমে, এই কাগজটিও হতাশ।

বিশেষত, নিম্নলিখিত জিনিস আছে।

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

সর্বশেষে তবে অন্ততপক্ষে, অ্যালগরিদম ইনপুট অ্যারের অভ্যন্তরের উপাদানগুলির সাথে অ্যারে সূচকগুলি অদলবদল করে স্থান-নেস অর্জন করে। এটি স্পষ্টতই কেবল সংখ্যাসূচক অ্যারেগুলিতে কাজ করে। আমার এটি স্ট্রিংয়ে ব্যবহার করা দরকার। অবশ্যই, আমি কেবল দৃ strong় টাইপিংয়ের স্ক্রু করতে পারি এবং ধরেই নিতে পারি যে স্মৃতিটি আমার কোনও সূচক যেখানে এটি সম্পর্কিত নয় সেগুলি সঞ্চয় করে সহ্য করবে। তবে এটি কেবল ততক্ষণ কাজ করে যতক্ষণ না আমি আমার স্ট্রিংগুলি 32 বিট মেমরির (32 বিট পূর্ণসংখ্যা ধরে) মেশাতে পারি। এটি কেবলমাত্র 16 টি অক্ষর (এই মুহুর্তের জন্য উপেক্ষা করুন যে 16> লগ (5,000,000))।

লেখকের একজনের অন্য একটি কাগজ মোটেই কোনও সঠিক বিবরণ দেয় না, তবে এটি এমএসএলের রানটাইমকে সাব-লিনিয়ার হিসাবে দেয় যা ভুল বলে ভুল।

পুনরুদ্ধার করার জন্য : ডিএনএ স্ট্রিংয়ের সাথে কাজ করে এমন কোনও কার্যত রেফারেন্স বাস্তবায়ন বা কমপক্ষে একটি ভাল সিউডোকোড / ওয়ার্কিং ইন-প্লেস র‌্যাডিক্স সাজানোর বর্ণনা পাওয়া যাবে কি?


65
এটি একটি চমত্কারভাবে লিখিত প্রশ্ন।
জাস্টিনটি

1
ছোট নির্দিষ্ট দৈর্ঘ্যের স্ট্রিং কত ছোট?
এভিলটিচ

1
@ এভিলটিচ: আমি ব্যবহারের কেস যুক্ত করেছি।
কনরাড রুডল্ফ

2
@ স্টেফান: এটি সব ঠিক আছে এবং ঠিক আছে। তবে অনুলিপি / ক্যাশে মিস করার ক্ষেত্রে আমি কেবল একটি বিলম্ব পাই। স্মৃতির ক্ষেত্রে আমি একটি ফিকিকাল সীমাতে আঘাত করি। এটি কেবল অবাধ্য able এই সমস্ত অভিনব কৌশলগুলি ডিস্কে ডেটার অংশগুলি সঞ্চয় করার জন্য বর্তমান কুইকোর্টের সমাধানের চেয়ে অবশ্যই ধীর।
কনরাড রুডল্ফ

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

উত্তর:


61

ঠিক আছে, এখানে ডিএনএর জন্য একটি এমএসডি রেডিক্স সাজানোর একটি সহজ বাস্তবায়ন। এটি ডি তে লিখিত কারণ এটি আমি যে ভাষাটি সবচেয়ে বেশি ব্যবহার করি এবং তাই এর মধ্যে নির্বোধ ভুল হওয়ার সম্ভাবনা কম তবে এটি সহজেই অন্য কোনও ভাষায় অনুবাদ করা যেতে পারে। এটি জায়গায় রয়েছে তবে 2 * seq.lengthঅ্যারের মধ্য দিয়ে যেতে হবে।

void radixSort(string[] seqs, size_t base = 0) {
    if(seqs.length == 0)
        return;

    size_t TPos = seqs.length, APos = 0;
    size_t i = 0;
    while(i < TPos) {
        if(seqs[i][base] == 'A') {
             swap(seqs[i], seqs[APos++]);
             i++;
        }
        else if(seqs[i][base] == 'T') {
            swap(seqs[i], seqs[--TPos]);
        } else i++;
    }

    i = APos;
    size_t CPos = APos;
    while(i < TPos) {
        if(seqs[i][base] == 'C') {
            swap(seqs[i], seqs[CPos++]);
        }
        i++;
    }
    if(base < seqs[0].length - 1) {
        radixSort(seqs[0..APos], base + 1);
        radixSort(seqs[APos..CPos], base + 1);
        radixSort(seqs[CPos..TPos], base + 1);
        radixSort(seqs[TPos..seqs.length], base + 1);
   }
}

স্পষ্টতই, এটি ডিএনএ-তে নির্দিষ্ট ধরনের, সাধারণ হওয়ার বিপরীতে, তবে এটি দ্রুত হওয়া উচিত।

সম্পাদনা:

এই কোডটি আসলে কাজ করে কিনা তা নিয়ে আমি কৌতূহল পেয়েছি, তাই আমার নিজের বায়োইনফরম্যাটিক কোডটি চালানোর অপেক্ষায় আমি এটি পরীক্ষা / ডিবাগ করেছি। উপরের সংস্করণটি আসলে পরীক্ষিত এবং কাজ করেছে। প্রতিটি 5 টি বেসের 10 মিলিয়ন সিকোয়েন্সগুলির জন্য, এটি একটি অপটিমাইজড ইনট্রোসোর্টের চেয়ে প্রায় 3x গতিযুক্ত।


9
আপনি যদি 2x পাসের পদ্ধতির সাথে বেঁচে থাকতে পারেন তবে এটি রেডিক্স-এন পর্যন্ত প্রসারিত: পাস 1 = কেবল গিয়ে দেখুন এবং প্রতিটি এন সংখ্যাগুলির মধ্যে কতগুলি রয়েছে তা গণনা করুন। তারপরে আপনি যদি অ্যারের পার্টিশন করছেন তবে এটি আপনাকে জানায় যে প্রতিটি অঙ্কটি কোথায় শুরু হয়। পাস 2 অ্যারে উপযুক্ত অবস্থানে অদলবদল করে।
জেসন এস

(উদাহরণস্বরূপ এন = 4 এর জন্য যদি 90000 এ, 80000 জি, 100 সি, 100000 টি থাকে, তবে আপনার ক্রমবর্ধমান অঙ্কগুলি = [0, 90000, 170000, 170100] দিয়ে একটি অ্যারে শুরু করুন যা আপনার এপোসের স্থানে ব্যবহৃত হয়, সিপোস, ইত্যাদির জন্য কার্সার হিসাবে যেখানে প্রতিটি সংখ্যার পরবর্তী উপাদানটি পরিবর্তন করা উচিত))
জেসন এস

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

দীর্ঘ সিকোয়েন্স সহ গতিটি কেমন? 5 দৈর্ঘ্যের দৈর্ঘ্য সহ আপনার পর্যাপ্ত আলাদা আলাদা কোনও নেই
স্টিফান এগগারমন্ট

4
এই রেডিক্স বাছাইটি আমেরিকান পতাকা বাছাইয়ের একটি বিশেষ কেস বলে মনে হচ্ছে - একটি স্থানের মধ্যে পরিচিত রেডিক্স সাজানোর বৈকল্পিক।
এডওয়ার্ড কেএমইটিটি

21

আমি কখনও কোনও ইন-প্লেস র‌্যাডিক্স বাছাই করতে দেখিনি এবং মূলসূত্র-সাজানোর প্রকৃতি থেকে আমি সন্দেহ করি যে অস্থায়ী অ্যারে স্মৃতিতে যতক্ষণ ফিট যায় ততক্ষণ এটি স্থানের আউটপুট ধরণের চেয়ে অনেক বেশি দ্রুত।

কারণ:

বাছাই করা ইনপুট অ্যারেতে লিনিয়ার পড়তে পারে তবে সমস্ত লেখাগুলি প্রায় এলোমেলো হবে। একটি নির্দিষ্ট এন থেকে উপরের দিকে এই লেখার জন্য একটি ক্যাশে মিস মিস করে। এই ক্যাশে মিসটি হ'ল যা আপনার অ্যালগরিদমকে ধীর করে দেয়। যদি এটি জায়গায় থাকে বা না হয় তবে এই প্রভাবটি পরিবর্তন করবে না।

আমি জানি যে এটি সরাসরি আপনার প্রশ্নের উত্তর দেবে না, তবে বাছাই যদি বাধা হয়ে থাকে তবে আপনি প্রিপ্রোসেসিং পদক্ষেপ হিসাবে অ্যালগরিদমকে বাছাই করার কাছাকাছি যেতে চান ( নরম-apগলের উইকি-পৃষ্ঠাটি আপনাকে শুরু করতে পারে)।

এটি একটি খুব সুন্দর ক্যাশে লোকাল বাড়িয়ে দিতে পারে। স্থানের বাইরে পাঠ্য-বুকের রেডিক্স সাজানোর পরে আরও ভাল সঞ্চালন করা হবে। লেখাগুলি এখনও প্রায় এলোমেলো হবে তবে কমপক্ষে তারা একই মেমরির অংশকে ঘিরে থাকবে এবং এর ফলে ক্যাশে হিট অনুপাত বাড়বে।

যদিও বাস্তবে এটি কার্যকর হয় কিনা আমার কোনও ধারণা নেই।

বিটিডব্লিউ: আপনি যদি কেবল ডিএনএ স্ট্রিং নিয়েই ডিল করছেন: আপনি একটি চরকে দুটি বিটের মধ্যে সংকোচিত করতে পারেন এবং আপনার ডেটাটি বেশ প্যাক করতে পারেন। এটি কোনও মজাদার প্রতিনিধিত্বের উপর ফ্যাক্টর চার দ্বারা মেমরির প্রয়োজনীয়তা হ্রাস করবে। সম্বোধন আরও জটিল হয়ে ওঠে, তবে আপনার সিপিইউর ALU- তে যাইহোক সমস্ত ক্যাশে-মিস করার সময় ব্যয় করতে প্রচুর সময় রয়েছে।


2
দুটি ভাল পয়েন্ট; কাছাকাছি বাছাই করা আমার কাছে একটি নতুন ধারণা, আমাকে সে সম্পর্কে পড়তে হবে। ক্যাশে মিস করা অন্য বিবেচনা যা আমার স্বপ্নগুলিকে হান্ট করে। ;-) আমি এই সম্পর্কে দেখতে হবে।
কনরাড রুডলফ

এটি আমার জন্যও বেশ কয়েক মাস (কয়েক মাস), তবে ধারণাটি পেয়ে গেলে আপনি পারফরম্যান্সের উন্নতির সুযোগগুলি দেখতে শুরু করেন।
নীল পিপেনব্রিংক

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

8

আপনি অবশ্যই বিটগুলিতে ক্রমটি এনকোড করে মেমরির প্রয়োজনীয়তাগুলি ফেলে দিতে পারেন। আপনি 16 টি রাজ্য বা 4 বিট হিসাবে "এসিজিটি" দিয়ে দৈর্ঘ্য 2 এর জন্য নির্গমনগুলির দিকে তাকিয়ে আছেন। 3 দৈর্ঘ্যের জন্য, এটি 64 টি রাজ্য, যা 6 টি বিটে এনকোড করা যায়। সুতরাং এটি ক্রমের প্রতিটি অক্ষরের জন্য 2 বিট বা আপনার মতো 16 অক্ষরের জন্য প্রায় 32 বিটের মতো দেখাচ্ছে।

বৈধ 'শব্দ' এর সংখ্যা হ্রাস করার কোনও উপায় থাকলে, আরও সংক্ষেপণ সম্ভব হতে পারে।

সুতরাং দৈর্ঘ্য 3 এর ক্রমগুলির জন্য, কেউ 64৪ টি বালতি তৈরি করতে পারে, সম্ভবত আকারের uint32 বা uint64 তৈরি করতে পারে। এগুলি শূন্যে শুরু করুন। আপনার 3 চরের সিকোয়েন্সগুলির খুব খুব বড় তালিকার মধ্য দিয়ে আইট্রেট করুন এবং উপরে হিসাবে এগুলি এনকোড করুন। এটি সাবস্ক্রিপ্ট হিসাবে ব্যবহার করুন এবং সেই বালতিটি বৃদ্ধি করুন।
আপনার সমস্ত ক্রমগুলি প্রক্রিয়া না করা পর্যন্ত এটি পুনরাবৃত্তি করুন।

এরপরে, আপনার তালিকাটি পুনরায় তৈরি করুন।

সেই বালতিতে পাওয়া গণনাটির জন্য ক্রম অনুসারে b৪ টি বালতিতে আইট্রেট করুন, সেই বালতিটি উপস্থাপিত ক্রমের অনেকগুলি উদাহরণ তৈরি করুন।
যখন সমস্ত বালতি পুনরাবৃত্তি করা হবে, আপনি আপনার সাজানো অ্যারে রাখবেন।

4 এর ক্রম 2 বিট যুক্ত করে, তাই 256 বালতি থাকবে। 5 এর ক্রম 2 বিট যোগ করে, তাই 1024 বালতি থাকবে।

এক পর্যায়ে বালতির সংখ্যা আপনার সীমাতে পৌঁছে যাবে। আপনি যদি কোনও ফাইল থেকে ক্রমগুলি পড়েন তবে সেগুলিকে মেমরিতে রাখার পরিবর্তে, বালতিগুলির জন্য আরও মেমরি পাওয়া যায়।

আমি মনে করি এটি পরিস্থিতি অনুসারে বাছাইয়ের চেয়ে আরও দ্রুত হবে কারণ বালতিগুলি আপনার কার্যকরী সেটের মধ্যে ফিট করতে পারে।

এখানে একটি হ্যাক যা কৌশলটি দেখায়

#include <iostream>
#include <iomanip>

#include <math.h>

using namespace std;

const int width = 3;
const int bucketCount = exp(width * log(4)) + 1;
      int *bucket = NULL;

const char charMap[4] = {'A', 'C', 'G', 'T'};

void setup
(
    void
)
{
    bucket = new int[bucketCount];
    memset(bucket, '\0', bucketCount * sizeof(bucket[0]));
}

void teardown
(
    void
)
{
    delete[] bucket;
}

void show
(
    int encoded
)
{
    int z;
    int y;
    int j;
    for (z = width - 1; z >= 0; z--)
    {
        int n = 1;
        for (y = 0; y < z; y++)
            n *= 4;

        j = encoded % n;
        encoded -= j;
        encoded /= n;
        cout << charMap[encoded];
        encoded = j;
    }

    cout << endl;
}

int main(void)
{
    // Sort this sequence
    const char *testSequence = "CAGCCCAAAGGGTTTAGACTTGGTGCGCAGCAGTTAAGATTGTTT";

    size_t testSequenceLength = strlen(testSequence);

    setup();


    // load the sequences into the buckets
    size_t z;
    for (z = 0; z < testSequenceLength; z += width)
    {
        int encoding = 0;

        size_t y;
        for (y = 0; y < width; y++)
        {
            encoding *= 4;

            switch (*(testSequence + z + y))
            {
                case 'A' : encoding += 0; break;
                case 'C' : encoding += 1; break;
                case 'G' : encoding += 2; break;
                case 'T' : encoding += 3; break;
                default  : abort();
            };
        }

        bucket[encoding]++;
    }

    /* show the sorted sequences */ 
    for (z = 0; z < bucketCount; z++)
    {
        while (bucket[z] > 0)
        {
            show(z);
            bucket[z]--;
        }
    }

    teardown();

    return 0;
}

আপনি যখন হ্যাশ করতে পারেন তখন তুলনা করবেন কেন?
Westest

1
পুব়োপুরি সোজা. পারফরম্যান্স সাধারণত কোনও ডিএনএ প্রসেসিংয়ের সমস্যা।
এভিলটিচ

6

যদি আপনার ডেটা সেটটি এত বড় হয় তবে আমি মনে করব যে ডিস্ক-ভিত্তিক বাফার পদ্ধতির সেরা হবে:

sort(List<string> elements, int prefix)
    if (elements.Count < THRESHOLD)
         return InMemoryRadixSort(elements, prefix)
    else
         return DiskBackedRadixSort(elements, prefix)

DiskBackedRadixSort(elements, prefix)
    DiskBackedBuffer<string>[] buckets
    foreach (element in elements)
        buckets[element.MSB(prefix)].Add(element);

    List<string> ret
    foreach (bucket in buckets)
        ret.Add(sort(bucket, prefix + 1))

    return ret

আমি উদাহরণস্বরূপ, যদি আপনার স্ট্রিংটি ছিল: বালতিগুলির একটি বৃহত সংখ্যায় গ্রুপিং পরীক্ষা করতাম:

GATTACA

প্রথম এমএসবি কল জিএটিটি (256 মোট বালতি) এর জন্য বালতিটি ফিরিয়ে দেবে, এইভাবে আপনি ডিস্ক ভিত্তিক বাফারের কম শাখা তৈরি করেন। এটি পারফরম্যান্সের উন্নতি করতে বা নাও পারে, তাই এটি নিয়ে পরীক্ষা করুন।


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

6

আমি একটি অঙ্গে যেতে যাচ্ছি এবং আপনাকে একটি হিপ / হিপসোর্ট বাস্তবায়নে স্যুইচ করার পরামর্শ দিচ্ছি । এই পরামর্শটি কিছু অনুমান নিয়ে আসে:

  1. আপনি ডেটা পড়া নিয়ন্ত্রণ করুন
  2. বাছাই করা ডেটার সাথে আপনি সাজানোর সাথে সাথে আপনি অর্থসূচক কিছু করতে পারেন।

হিপ / হিপ-সাজানোর সৌন্দর্য হ'ল আপনি ডেটা পড়ার সময় গাদাটি তৈরি করতে পারবেন এবং আপনি গাদাটি তৈরি করার মুহুর্তে ফলাফল পেতে শুরু করতে পারেন।

পিছনে সরে যাক। আপনি যদি এত ভাগ্যবান হন যে আপনি ডেটা অবিচ্ছিন্নভাবে পড়তে পারেন (অর্থাত আপনি কিছু প্রকারের পড়ার অনুরোধ পোস্ট করতে পারেন এবং কিছু ডেটা প্রস্তুত হওয়ার পরে আপনাকে অবহিত করা যেতে পারে), এবং তারপরে অপেক্ষা করার সময় আপনি স্তূপের একটি অংশ তৈরি করতে পারেন পরবর্তী অংশে আসতে হবে - এমনকি ডিস্ক থেকে। প্রায়শই, এই পদ্ধতির ডেটা পেতে ব্যয় করা সময়ের পিছনে আপনার বাছাইয়ের অর্ধেক ব্যয়কে সমাহিত করতে পারে।

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

এটি বলেছিল - ডেটা কীভাবে পড়া হয় তার উপরে যদি আপনার কোনও নিয়ন্ত্রণ না থাকে এবং এটি সিঙ্ক্রোনজিকভাবে পড়া হয় এবং সম্পূর্ণরূপে লিখিত না হওয়া পর্যন্ত বাছাই করা ডেটার জন্য আপনার কোনও ব্যবহার নেই - এই সমস্ত উপেক্ষা করুন। :(

উইকিপিডিয়া নিবন্ধগুলি দেখুন:


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

5

" অতিরিক্ত স্থান ছাড়াই রেডিক্স বাছাই করা " আপনার সমস্যার সমাধান করার জন্য একটি কাগজ।


প্রতিশ্রুতিবদ্ধ মনে হচ্ছে, যদিও সমস্যাটি ইতিমধ্যে সমাধান হয়ে গেছে। তবুও, এটি আমার রেফারেন্স লাইব্রেরিতে যায়।
কনরাড রুডলফ

4

পারফরম্যান্স-ভিত্তিতে আপনি আরও সাধারণ স্ট্রিং-তুলনা বাছাইকরণ অ্যালগরিদমগুলি দেখতে চাইতে পারেন।

বর্তমানে আপনি প্রতিটি স্ট্রিংয়ের প্রতিটি উপাদানকে স্পর্শ করে শেষ করেছেন তবে আপনি আরও ভাল করতে পারেন!

বিশেষত, একটি বিস্ফোরণ বাছাই এই ক্ষেত্রে জন্য খুব ভাল ফিট। একটি বোনাস হিসাবে, যেহেতু বার্স্টর্ট চেষ্টাগুলির উপর ভিত্তি করে, এটি ডিএনএ / আরএনএতে ব্যবহৃত ছোট ছোট বর্ণমালাগুলির জন্য হাস্যকরভাবে ভাল কাজ করে, যেহেতু আপনাকে কোনও ধরণের টর্নারি সার্চ নোড, হ্যাশ বা অন্যান্য ট্রাই নোড সংক্ষেপণ স্কিম তৈরি করার দরকার নেই the ত্রি বাস্তবায়ন চেষ্টাগুলি আপনার প্রত্যয়-অ্যারের মতো চূড়ান্ত লক্ষ্যের জন্যও কার্যকর হতে পারে।

বার্সোর্টের একটি সাধারণ সাধারণ উদ্দেশ্য বাস্তবায়ন http://sourceforge.net/projects/burstsort/ এ উত্স ফোর্জে উপলব্ধ - তবে এটি স্থান নয়।

তুলনা করার উদ্দেশ্যে, সি-বার্স্টর্ট বাস্তবায়নটি http://www.cs.mu.oz.au/~rsinha/papers/SinhaRingZobel-2006.pdf বেঞ্চমার্কগুলিতে কিছু সাধারণ কাজের চাপের জন্য কুইকোর্ট এবং রেডিক্সের ধরণের চেয়ে 4-5x দ্রুত covered


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

4

আপনি ডিআরএস দ্বারা লার্জ-স্কেল জিনোম সিকোয়েন্স প্রসেসিংটি একবার দেখে নিতে চাইবেন । কাসাহারা ও মরিশিটা।

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


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

3

আপনি একটি ট্রাই ব্যবহার করার চেষ্টা করতে পারেন । ডেটা বাছাই করা কেবল ডেটাসেটের মাধ্যমে পুনরাবৃত্তি হয় এবং এটি সন্নিবেশ করা হয়; কাঠামোটি প্রাকৃতিকভাবে বাছাই করা হয় এবং আপনি এটিকে বি-গাছের সমান হিসাবে ভাবতে পারেন (তুলনা করার পরিবর্তে আপনি সর্বদা পয়েন্টার ইন্ডিয়ারিকেশন ব্যবহার করেন)।

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


ট্রাইতে আমার নির্বিকার প্রয়োগের মতো একই সমস্যা রয়েছে: এটির জন্য ও (এন) অতিরিক্ত মেমরি প্রয়োজন যা কেবল খুব বেশি।
কনরাড রুদল্ফ

3

আমি স্ট্রিংগুলির একটি প্যাক-বিট উপস্থাপনাটি ছড়িয়ে দেব । ক্লাসিকাল ট্রায়ালের পরিবর্তে অতিরিক্ত স্থানের ব্যবহারকে ফাটানোর চেষ্টা করে রেডিক্সের চেয়ে আরও ভাল স্থানীয় এলাকা বলে দাবি করা হচ্ছে বার্সোর্টের। মূল কাগজটির পরিমাপ রয়েছে।


2

রেডিক্স-বাছাই ক্যাশে সচেতন নয় এবং বড় সেটের জন্য দ্রুততম সাজানোর অ্যালগরিদম নয়। আপনি দেখতে পারেন:

এছাড়াও আপনি সংক্ষেপণ ব্যবহার করতে পারেন এবং সাজানোর অ্যারেতে সঞ্চয় করার আগে আপনার ডিএনএর প্রতিটি অক্ষর 2 বিটের মধ্যে এনকোড করতে পারেন।


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

আমি সি ++ ব্যবহার করছি না, তবে আমার পরীক্ষায় ইনডলাইন কিউএসআরটি stdlib এর Qsort এর চেয়ে 3 গুণ বেশি দ্রুত হতে পারে। Ti7qsort হল পূর্ণসংখ্যার জন্য দ্রুততম বাছাই (ইনলাইন QSORT এর চেয়ে দ্রুত)। আপনি এটি ছোট স্থির আকারের ডেটা বাছাই করতেও ব্যবহার করতে পারেন। আপনাকে অবশ্যই আপনার ডেটা দিয়ে পরীক্ষাগুলি করতে হবে।
বিল

1

সিমচা এর এমএসবি রেডিক্সের সাজান দেখতে দুর্দান্ত লাগছে, তবে নীলস পর্যবেক্ষণ করে সমস্যার হৃদয়ের কাছাকাছি পৌঁছেছে যে ক্যাশে লোকালাই হ'ল আপনাকে বড় সমস্যার আকারে হত্যা করছে।

আমি খুব সহজ পদ্ধতির পরামর্শ দিই:

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

মার্জোর্টটি সর্বাধিক ক্যাশে-বান্ধব বাছাই করা অ্যালগরিদম যা সম্পর্কে আমি সচেতন: "অ্যারে A বা B এর পরের আইটেমটি পড়ুন, তারপরে আউটপুট বাফারটিতে একটি আইটেম লিখুন।" এটি টেপ ড্রাইভে দক্ষতার সাথে চলে । আইটেমগুলি 2nবাছাই করার জন্য এটির জন্য জায়গার প্রয়োজন নেই n, তবে আমার বাজিটি হ'ল আপনি যে বহুল উন্নত ক্যাশের লোকালটি দেখবেন সেটি সেই গুরুত্বহীন করে তুলবে - এবং আপনি যদি কোনও জায়গা না-করে রাখার রেডিক্স সারণি ব্যবহার করে থাকেন তবে যাইহোক আপনার অতিরিক্ত স্থানটির প্রয়োজন ছিল।

দয়া করে নোট করুন অবশেষে মার্জোর্টটি পুনরাবৃত্তি ছাড়াই প্রয়োগ করা যেতে পারে এবং বাস্তবে এটি করা সত্যিকারের রৈখিক মেমরি অ্যাক্সেসের ধরণকে পরিষ্কার করে দেয়।


1

দেখে মনে হচ্ছে আপনি সমস্যার সমাধান করেছেন, তবে রেকর্ডের জন্য, মনে হয় যে কার্যক্ষম স্থানে থাকা রডিক্স সাজানোর একটি সংস্করণ হ'ল "আমেরিকান ফ্ল্যাগ সাজান"। এটি এখানে বর্ণিত হয়েছে: ইঞ্জিনিয়ারিং রেডিক্স বাছাই করুন । সাধারণ ধারণাটি প্রতিটি চরিত্রের জন্য 2 টি করতে হয় - প্রথমে আপনার প্রতিটি কয়টি রয়েছে তা গণনা করুন, যাতে আপনি ইনপুট অ্যারেটিকে বিভক্ত করতে পারেন। তারপরে প্রতিটি উপাদানকে সঠিক বিনের মধ্যে অদলবদল করে আবার যেতে হবে। এখন প্রতিটি অক্ষরকে পরের অক্ষরের অবস্থান অনুসারে পুনরাবৃত্তভাবে সাজান।


আসলে, আমি যে সমাধানটি ব্যবহার করি এটি ফ্ল্যাগ বাছাইকরণ অ্যালগরিদমের সাথে খুব ঘনিষ্ঠভাবে সম্পর্কিত। কোনও প্রাসঙ্গিক পার্থক্য আছে কিনা তা আমি জানি না।
কনরাড রুডল্ফ

2
আমেরিকান পতাকা বাছাইয়ের কথা কখনও শুনেনি, তবে আমি যা কোডিং করেছি তা আগ্রহীভাবেই হয়েছে : coliru.stacked-crooked.com/a/94eb75fbecc39066 এটি বর্তমানে কার্যকর নয় std::sort, এবং আমি নিশ্চিত যে একটি মাল্টিডিজিট ডিজিটাইজার আরও দ্রুত যেতে পারে তবে আমার পরীক্ষার স্যুটে স্মৃতি রয়েছে সমস্যাগুলি (অ্যালগোরিদম নয়, নিজেই পরীক্ষার
স্যুটই

@ কনরাডরুডল্ফ: পতাকা বাছাই এবং অন্যান্য রেডিক্সের ধরণের মধ্যে বড় পার্থক্য হল গণনা পাস। আপনি ঠিক বলেছেন যে সমস্ত রেডিক্সের প্রকারগুলি খুব ঘনিষ্ঠভাবে সম্পর্কিত, তবে আমি আপনাকে একটি পতাকা বাছাই হিসাবে বিবেচনা করব না।
মাকিং হাঁস

@ মুভিংডাক: সেখানে আপনার নমুনা থেকে কিছুটা অনুপ্রেরণা নিয়েছেন - আমি আমার নিজস্ব স্বাধীন প্রয়োগে আটকে গিয়েছি এবং আপনারা আমাকে ট্র্যাকটিতে ফিরে আসতে সহায়তা করেছেন। ধন্যবাদ! একটি সম্ভাব্য অপ্টিমাইজেশন - এটি এখনও সার্থক কিনা তা আমি এখানে এখনও অর্জন করতে পারি নি: আপনি যে অবস্থানে স্যুপ করছেন সেই উপাদানটি যদি সেখানে হওয়া উচিত হয় তবে আপনি সেই জায়গাটি এড়িয়ে যেতে পারেন এবং এটির দিকে এগিয়ে যেতে পারেন নয়। এটি সনাক্তকরণে অবশ্যই অতিরিক্ত যুক্তি প্রয়োজন, পাশাপাশি সম্ভাব্য অতিরিক্ত সঞ্চয়স্থানও প্রয়োজন, তবে যেহেতু অদলবদর তুলনার তুলনায় ব্যয়বহুল, তাই এটি করা উপযুক্ত হতে পারে।
500 -

1

প্রথমে আপনার সমস্যার কোডিং সম্পর্কে ভাবুন। স্ট্রিংগুলি থেকে মুক্তি পান, বাইনারি উপস্থাপনার মাধ্যমে তাদের প্রতিস্থাপন করুন। দৈর্ঘ্য + এনকোডিং নির্দেশ করতে প্রথম বাইট ব্যবহার করুন। বিকল্পভাবে, চার-বাইট সীমানায় একটি নির্দিষ্ট দৈর্ঘ্যের প্রতিনিধিত্ব ব্যবহার করুন। তারপরে র‌্যাডিক্স সাজানো অনেক সহজ হয়ে যায়। একটি রেডিক্স সাজানোর জন্য, সর্বাধিক গুরুত্বপূর্ণ বিষয়টি হল অভ্যন্তরীণ লুপের গরম জায়গায় ব্যতিক্রম হ্যান্ডলিং না করা।

ঠিক আছে, আমি 4-ন্যারি সমস্যাটি সম্পর্কে আরও কিছু ভেবেছি। আপনি এর জন্য জুডি গাছের মতো সমাধান চান । পরবর্তী সমাধান পরিবর্তনশীল দৈর্ঘ্যের স্ট্রিং পরিচালনা করতে পারে; নির্দিষ্ট দৈর্ঘ্যের জন্য দৈর্ঘ্যের বিটগুলি সরিয়ে ফেলুন, এটি আসলে এটি আরও সহজ করে তোলে।

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

  • পরিবর্তনশীল-দৈর্ঘ্যের স্ট্রিংগুলির 7 দৈর্ঘ্যের বিট সহ এনকোডিং। এগুলি পূরণ করার সাথে সাথে আপনি তাদের দ্বারা প্রতিস্থাপন করুন:
  • অবস্থানটি পরবর্তী দুটি অক্ষরকে এনকোড করে, আপনার পরবর্তী ব্লকে 16 পয়েন্টার রয়েছে, এটি দিয়ে শেষ হবে:
  • একটি স্ট্রিংয়ের শেষ তিনটি অক্ষরের বিটম্যাপ এনকোডিং।

প্রতিটি ধরণের ব্লকের জন্য আপনাকে এলএসবিতে বিভিন্ন তথ্য সংরক্ষণ করতে হবে। আপনার যেমন পরিবর্তনশীল দৈর্ঘ্যের স্ট্রিং রয়েছে আপনার এন্ড-অফ-স্ট্রিংও সংরক্ষণ করতে হবে এবং শেষ প্রকারের ব্লকটি কেবল দীর্ঘতম স্ট্রিংয়ের জন্যই ব্যবহার করা যেতে পারে। কাঠামোর গভীরে যাওয়ার সাথে সাথে 7 দৈর্ঘ্যের বিটগুলি কম দ্বারা প্রতিস্থাপন করা উচিত।

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

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

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

আপনি ডাবলস পরিচালনা করতে আগ্রহী? সংক্ষিপ্ত ক্রম সহ, সেখানে হতে চলেছে। গণনাগুলি পরিচালনা করতে ব্লকগুলি মানিয়ে নেওয়া জটিল, তবে এটি খুব স্পেস-দক্ষ হতে পারে।


আমি যদি দেখি না যে আমি কিছুটা প্যাকযুক্ত উপস্থাপনা ব্যবহার করি তবে আমার ক্ষেত্রে কীভাবে রেডিক্স সাজানো সহজ হয়ে যায়। যাইহোক, আমি যে কাঠামোটি ব্যবহার করি তা প্রকৃতপক্ষে বিট-প্যাক উপস্থাপনা ব্যবহারের সম্ভাবনা সরবরাহ করে তবে ইন্টারফেসের ব্যবহারকারী হিসাবে এটি আমার পক্ষে সম্পূর্ণ স্বচ্ছ।
কনরাড রুডলফ

আপনি যখন আপনার স্টপওয়াচের দিকে তাকাবেন না :)
স্টিফান এগারমন্ট

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