2010-11-27 8 views
6

मान लीजिए कि हमें 50 000 000 नंबरों को सॉर्ट करने की आवश्यकता है। मान लीजिए कि संख्या फाइल में संग्रहीत है। इस समस्या को हल करने के लिए सबसे कुशल एल्गोरिदम क्या है? क्रमबद्ध करने के लिए समांतर एल्गोरिदम ...सॉर्टिंग 50 000 000 संख्या

यह कैसे करें? हो सकता है कि उपयोगी लिंक) मानक एल्गोरिथ्म

मैं उपयोग नहीं कर सकते

इसलिए मैं आपको ऐसी विधियों और एल्गोरिदम :)

ठीक है के बारे में पूछने .. मैं समानांतर mergesort के बारे में पढ़ा ... लेकिन यह मेरे लिए स्पष्ट नहीं है ।

समाधान, पहले संस्करण

code is located here

+0

:) आप क्या कहना चाहते हैं? –

+0

@ पॉल वह सिर्फ मैट्रिक्स से है - उसका उपनाम देखें :) –

+3

आप मानक एल्गोरिदम का उपयोग क्यों नहीं कर सकते? क्या यह एक होमवर्क समस्या है? –

उत्तर

8

मेरे सिर के ऊपर से, merge sort सबसे अच्छा विकल्प है जब यह, parallelisation और वितरण की बात आती है के रूप में यह का उपयोग करता है लगता है डिवाइड-और -कॉकर दृष्टिकोण। अधिक जानकारी के लिए, "समांतर विलय सॉर्ट" और "वितरित विलय सॉर्ट" के लिए Google के लिए Google।

एकल मशीन, एकाधिक कोर उदाहरण के लिए, Correctly multithreaded quicksort or mergesort algo in Java? देखें। यदि आप जावा 7 कांटा/जॉइन का उपयोग कर सकते हैं तो देखें: "Java 7: more concurrency" और "Parallelism with Fork/Join in Java 7"। MergeSort और MergeSorter देखें:

कई मशीनों अधिक से वितरित करने के लिए, Hadoop देखते हैं, यह एक वितरित मर्ज तरह क्रियान्वयन है। इसके अलावा ब्याज: Hadoop Sorts a Petabyte in 16.25 Hours and a Terabyte in 62 Seconds

+0

निश्चित रूप से यदि आपके पास सॉर्ट करने के लिए डेटा के टेराबाइट हैं तो मैं इसके लिए जाऊंगा। – Uberto

+0

:) बहु-कोर सिस्टम के लिए सटीक एल्गोरिदम नहीं मिल रहा है। शायद आप कुछ लिंक या पेपर दे सकते हैं? –

+0

मैंने अपना उत्तर –

4

कई तत्वों से छँटाई के लिए, अपने सबसे अच्छे शॉट Merge Sort है। यह आमतौर पर डेटाबेस द्वारा उपयोग किए जाने वाले एल्गोरिदम होता है। हालांकि Quick Sort जितना तेज़ नहीं है, यह इंटरमीडिएट स्टोरेज का उपयोग करता है ताकि आपको सॉर्ट करने के लिए बड़ी मात्रा में मेमोरी की आवश्यकता न हो।

इसके अलावा, जैसा कि टिप्पणियों में sje397 और स्कॉट द्वारा इंगित किया गया है, मर्ज सॉर्ट अत्यधिक समानांतर है।

+1

और मर्जोर्ट आसानी से समानांतर है। – sje397

+0

मर्ज सॉर्ट भी बेहद समानांतर है। – Scott

+1

... और sje397 और मैं बिल्कुल वही तरंग दैर्ध्य पर हैं। :-) – Scott

3

यह समस्या डोमेन पर बहुत निर्भर करता है। उदाहरण के लिए, यदि सभी संख्याएं सकारात्मक इन्ट्स हैं, तो 0-MAX_INT की सरणी बनाने का सबसे अच्छा तरीका हो सकता है और फिर यह गणना करें कि फ़ाइल को पढ़ने के बाद प्रत्येक संख्या कितनी बार होती है, और उसके बाद प्रत्येक int को गैर- शून्य गणना हालांकि कई बार हुई। यह ओ (एन) "सॉर्ट" है। उस तरह के लिए एक आधिकारिक नाम है, लेकिन मैं भूल जाता हूं कि यह क्या है।

वैसे, मैंने इस प्रश्न को Google साक्षात्कार में पूछा। समस्या की बाधाओं से मैं इस समाधान के साथ आया, और ऐसा लगता है कि वे जिस जवाब की तलाश में थे। (मैं काम ठुकरा दिया क्योंकि मैं ले जाने के लिए नहीं करना चाहता था।)

+1

इसे गिनती सॉर्ट कहा जाता है। http://en.wikipedia.org/wiki/Counting_sort –

+0

नहीं, सरणी में नकारात्मक संख्याएं हो सकती हैं। –

2

वे इतने सारे नहीं हैं। यदि वे 10 बाइट लंबे समय तक विस्तारित हैं उदाहरण के लिए यह 500 एमबाइट्स की एक सरणी होगी, यह लगभग मेरे फोन पर रह सकती है! ;) तो मैं कहूंगा कि क्विक्सोर्ट के लिए जाना है अगर यह केवल यही है।

19

50 मिलियन विशेष रूप से बड़ा नहीं है। मैं उन्हें स्मृति में पढ़ूंगा। उन्हें क्रमबद्ध करें और उन्हें लिखें। इसमें कुछ ही सेकंड लग सकते हैं। आपको इसकी कितनी तेज़ी से आवश्यकता है? आपको इसकी आवश्यकता कितनी जटिल है?

मेरी पुरानी प्रयोगशाला में 28 सेकंड लग गए। अगर मेरे पास अधिक प्रोसेसर थे, तो यह थोड़ा तेज़ हो सकता है लेकिन फ़ाइल को पढ़ने और लिखने में अधिक समय लगता है (15 सेकंड) जो कि तेज़ नहीं होगा।

महत्वपूर्ण कारकों में से एक आपके कैश का आकार है। तुलना स्वयं बहुत ही सस्ता है बशर्ते डेटा कैश में हो। चूंकि एल 3 कैश साझा किया जाता है, इसलिए एक थ्रेड आपको इसका पूर्ण उपयोग करने की आवश्यकता होती है।

public static void main(String...args) throws IOException { 
    generateFile(); 

    long start = System.currentTimeMillis(); 
    int[] nums = readFile("numbers.bin"); 
    Arrays.sort(nums); 
    writeFile("numbers2.bin", nums); 
    long time = System.currentTimeMillis() - start; 
    System.out.println("Took "+time+" secs to sort "+nums.length+" numbers."); 
} 

private static void generateFile() throws IOException { 
    Random rand = new Random(); 
    int[] ints = new int[50*1000*1000]; 
    for(int i= 0;i<ints.length;i++) 
     ints[i] = rand.nextInt(); 
    writeFile("numbers.bin", ints); 
} 

private static int[] readFile(String filename) throws IOException { 
    DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(filename), 64*1024)); 
    int len = dis.readInt(); 
    int[] ints = new int[len]; 
    for(int i=0;i<len;i++) 
     ints[i] = dis.readInt(); 
    return ints; 
} 

private static void writeFile(String name, int[] numbers) throws IOException { 
    DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(name), 64*1024)); 
    dos.writeInt(numbers.length); 
    for (int number : numbers) 
     dos.writeInt(number); 
    dos.close(); 
} 
+0

संपादित किया "जैसा कि एल 3 कैश साझा किया जाता है, एक धागा आपको इसका पूर्ण उपयोग करने की आवश्यकता है।" फिर भी, मेरे सी ++ कोड में एक थ्रेड में 50 एम पूर्णांक को क्रमबद्ध करने के लिए 6 एस (घड़ी और सीपीयू) लगता है, और 3.7 एस घड़ी/6.5 सीपीयू पहले और नीचे INT_MAX के पूर्णांक को विभाजित करने के लिए, फिर निचले भाग को एक थ्रेड और ऊपरी भाग में क्रमबद्ध करें दूसरे में हिस्सा। पता नहीं कि जावा अलग होगा, लेकिन यह सुझाव देता है कि एल 3 कैश इसके लिए सब कुछ नहीं है। यह समान रूप से वितरित मूल्यों के साथ है। –

+0

बस इस तरह के समय, मेरे लैपटॉप पर 13 सेकंड एक थ्रेड और 7 सेकंड के साथ लिया। जबकि यह 6 सेकंड (कुल में से 22%) बचाता है, यह कोड की जटिलता में काफी वृद्धि करता है (पोस्ट नहीं किया गया;) 6 कोर के साथ नोट, मैं संभावित रूप से 5 सेकंड बचा सकता हूं लेकिन लोड और सेव करने में यह 18 सेकंड लग जाएगा 15 सेकंड –

+0

वास्तव में बहुत कुछ इस बात पर निर्भर करता है कि कुछ सेकंड को सहेजना कितना महत्वपूर्ण है। कोड लिखने में मुझे कई मिनट लग गए, अगर मैंने वास्तव में इसका परीक्षण किया। ;) ज्यादातर मामलों में यह आईएमएचओ के प्रयास के लायक नहीं होगा। –

2

बड़ी संख्या से डरो मत। वास्तव में, 50 000 000 संख्या इतनी बड़ी नहीं है। इसलिए यदि संख्या पूर्णांक थी तो प्रत्येक संख्या आकार में 4bytes है, इसलिए इस सरणी के लिए आवंटित होने वाली समग्र मेमोरी 50 000 000 * 4/1024/1024 = 190.7 मेगा बाइट्स अपेक्षाकृत छोटी है। गणित करने के बाद, आप QuickSort करने के लिए आगे बढ़ सकते हैं जो O (nLogn) में चलता है। ध्यान दें कि .NET arrays में बिल्टिन सॉर्ट विधि QuickSort का उपयोग करती है, मुझे यकीन नहीं है कि यह जावा में भी मामला है।

छँटाई मेरी मशीन पर 250 000 000 पूर्णांक के बारे में 2 मिनट लग गए तो इसके लिए जाना :)

+0

50 000 000 * 4 (couse sizeof (item) == 4) == 200 000 000 –

+0

200 000 000/1024/1024 ~ 200 एमबी ... –

+1

उम। आपको 4 से गुणा होना चाहिए, विभाजित नहीं होना चाहिए। 4 बाइट्स पर 50 एम मान प्रत्येक 200 एमबी (द्विआधारी कर के बाद 190 एमबी) लेता है। –

0

50e6 संख्या आजकल बहुत छोटा है, चीजों को और अधिक जटिल की तुलना में वे होने की जरूरत नहीं बनाते हैं ...

bash$ sort <file> sorted.file

संबंधित मुद्दे