2010-09-07 13 views
13

मुझे सी में एक सॉर्टिंग प्रोग्राम लिखना होगा और डिस्क स्थान को सहेजने के लिए फ़ाइल को सॉर्ट किया जा सकता है, तो यह अच्छा होगा। डेटा मूल्यवान है, इसलिए मुझे यह सुनिश्चित करने की आवश्यकता है कि अगर प्रक्रिया बाधित हो (ctrl-c) फ़ाइल दूषित नहीं है। मैं गारंटी दे सकता हूं कि मशीन पर पावर कॉर्ड यंक नहीं किया जाएगा।इंटरप्टिबल इन-प्लेस सॉर्टिंग एल्गोरिदम

अतिरिक्त विवरण: फाइल है ~ 40GB, रिकॉर्ड 128 बिट, मशीन 64-बिट, ओएस POSIX

कोई संकेत सामान्य रूप में इस या नोट्स को पूरा करने पर है कर रहे हैं?

धन्यवाद!

स्पष्टीकरण के लिए: मुझे उम्मीद है कि उपयोगकर्ता प्रक्रिया को ctrl-c करना चाहता है। इस मामले में, मैं कृपा से बाहर निकलना चाहता हूं और यह सुनिश्चित करना चाहता हूं कि डेटा सुरक्षित है। तो यह सवाल इंटरप्ट्स को संभालने और एक प्रकार का एल्गोरिदम चुनने के बारे में है जो अनुरोध किए जाने पर जल्दी से लपेट सकता है।

अनुवर्ती (2 साल बाद): सिर्फ पोस्टरिटी के लिए, मैंने सिगिनट हैंडलर स्थापित किया है और यह बहुत अच्छा काम करता है। यह बिजली की विफलता के खिलाफ मेरी रक्षा नहीं करता है, लेकिन यह एक जोखिम है जिसे मैं संभाल सकता हूं। https://code.google.com/p/pawnsbfs/source/browse/trunk/hsort.c और https://code.google.com/p/pawnsbfs/source/browse/trunk/qsort.c

+0

मुझे लगता है कि आपको पूछना है कि कौन सा महत्वपूर्ण है? अंतरिक्ष, या प्रक्रिया को बाधित किया जाना चाहिए।यदि आपको यह सुनिश्चित करने की आवश्यकता है कि फ़ाइल दूषित नहीं है, तो आपको किसी भी तरह से इसकी प्रगति और पिछले राज्यों का ट्रैक रखना होगा - यह फ़ाइल की तुलना में अधिक जगह लेगा। –

+0

सुरक्षित होने के लिए। प्रतिलिपि बनाएं और कॉपी को सॉर्ट करें। मैं नहीं कर सकता; फ़ाइल सिस्टम को 40 जीबी –

+0

@ मार्टिन के साथ परेशानी होगी: आपकी कल्पना मेरे तरीके से काम नहीं करती है। मेरे प्राथमिक ड्राइव पर वर्तमान में 36.4 जीबी मुफ्त है। –

उत्तर

5

SIGINT के लिए एक हैंडलर स्थापित करें जो केवल "प्रक्रिया को बाहर निकलना चाहिए" ध्वज सेट करता है।

अपने प्रकार में, दो रिकॉर्ड (या प्रत्येक एन स्वैप के बाद) के प्रत्येक स्वैप के बाद ध्वज की जांच करें। अगर ध्वज सेट किया गया है, तो जमानत।

+0

यह मेरे लिए सबसे अच्छा समाधान की तरह लगता है। कुछ अन्य सिफारिशें मुझे यह इंप्रेशन देती हैं कि Ctrl-C को अनदेखा किया जाना चाहिए यदि इसे सही समय पर दबाया नहीं जाता है, जो कि मेरे लिए खराब उपयोगकर्ता अनुभव जैसा लगता है। –

+0

यह विजेता की तरह दिखता है। ऐसा लगता है कि क्विकॉर्ट और हेपसोर्ट पर लागू होता है। धन्यवाद! –

+0

यह आपके डेटा को हत्या -9 या बिजली विफलता से बचाएगा हालांकि। गलत जवाब के लिए –

3

कोड स्वैप का उपयोग करें, और प्रत्येक स्वैप ऑपरेशन के दौरान बाधाओं को रोकें (उदा। ब्लॉक सिग्नल)।

+0

हाँ। सरल, और आसान। मेमोरी में बदलाव भी करें और फिर उन्हें एक साथ लिखें/फ्लश करें (इस भाग के लिए ब्लॉक सिग्नल)। –

+0

हेपसोर्ट को पूरे फाइल पर मारने की आवश्यकता है, जो कि किसी भी चीज के लिए अच्छा नहीं हो सकता है जो भौतिक स्मृति में फिट नहीं है। –

+0

दूसरी ओर, यदि फ़ाइल आपके मामले में विशाल है, तो बड़े-ओ और नहीं, io कैश मिस से निरंतर कारक हावी होने जा रहा है। हीप सॉर्ट एकमात्र इन-प्लेस सॉर्ट है जो क्वाड्रैटिक बिग-ओ से बेहतर है। –

0

बैकअप जो भी आप बदलने की योजना बना रहे हैं। एक झंडा लगाओ जो सफल प्रकार को चिह्नित करता है। अगर सबकुछ ठीक है तो परिणाम रखें, अन्यथा बैकअप को पुनर्स्थापित करें।

+0

-1 प्रश्न के इन-प्लेस मानदंड को पूरा नहीं करता है, जो स्पष्ट रूप से बताता है कि एक विशाल डेटासेट है और शायद इसे वापस करने के लिए कोई जगह नहीं है। –

+0

आर: आपको पूरी फ़ाइल को सहेजने की आवश्यकता नहीं है। बस छोटे टुकड़ों को बचाएं जो क्रम में उपयोग किए जाते हैं। मैंने कभी नहीं कहा कि पूरी फाइल का बैक अप लिया जाना चाहिए। –

12

जैरी का अधिकार, अगर यह केवल Ctrl-C है, तो आप चिंतित हैं, आप एक समय में SIGINT को अनदेखा कर सकते हैं। यदि आप सामान्य रूप से प्रक्रिया की मृत्यु के खिलाफ सबूत बनना चाहते हैं, तो आपको किसी प्रकार की न्यूनतम पत्रिका की आवश्यकता है। दो तत्वों को स्वैप करने के लिए:

1) फ़ाइल के अंत में या एक अलग फ़ाइल में नियंत्रण संरचना में एक रिकॉर्ड जोड़ें, यह दर्शाता है कि फ़ाइल के दो तत्व आप स्वैप करने जा रहे हैं, ए और बी

2) ए को स्क्रैच स्पेस पर कॉपी करें, रिकॉर्ड करें कि आपने ऐसा किया है, फ्लश करें।

3) एक से अधिक कॉपी बी, तो खरोंच अंतरिक्ष कि आपने ऐसा किया है, फ्लश

4) बी

5 खरोंच अंतरिक्ष से कॉपी) रिकॉर्ड निकालें में दर्ज करते हैं।

यह सभी व्यावहारिक उद्देश्यों के लिए ओ (1) अतिरिक्त स्थान है, इसलिए अभी भी अधिकांश परिभाषाओं के तहत जगह के रूप में गिना जाता है। सिद्धांत में रिकॉर्डिंग एक इंडेक्स ओ (लॉग एन) है यदि एन मनमाने ढंग से बड़ा हो सकता है: हकीकत में यह बहुत छोटा लॉग एन है, और उचित हार्डवेयर/चलने का समय 64 से ऊपर है।

सभी मामलों में जब मैं कहता हूं " फ्लश ", मेरा मतलब है कि" काफी दूर "परिवर्तन करें। कभी-कभी आपका मूल फ्लश ऑपरेशन केवल प्रक्रिया के भीतर बफर को फ्लश करता है, लेकिन यह वास्तव में भौतिक माध्यम को सिंक नहीं करता है, क्योंकि यह ओएस/डिवाइस ड्राइवर/हार्डवेयर स्तर के माध्यम से सभी तरह से बफर फ्लश नहीं करता है। यह पर्याप्त है जब आप चिंतित हैं, प्रक्रिया की मौत है, लेकिन यदि आप अचानक मीडिया की कमी के बारे में चिंतित हैं तो आपको ड्राइवर के पीछे फ्लश करना होगा। यदि आप बिजली की विफलता के बारे में चिंतित थे, तो आपको हार्डवेयर को सिंक करना होगा, लेकिन आप नहीं हैं। यूपीएस के साथ या यदि आपको लगता है कि बिजली कटौती इतनी दुर्लभ है तो आपको डेटा खोने में कोई फर्क नहीं पड़ता, यह ठीक है।

स्टार्टअप पर, किसी भी "स्वैप-इन-प्रोग्रेस" रिकॉर्ड्स के लिए स्क्रैच स्पेस की जांच करें।यदि आपको कोई मिलता है, तो डेटा को वापस ध्वनि स्थिति में वापस लाने के लिए वहां से कितना दूर मिल गया है और स्वैप को पूरा करें। फिर फिर से अपना सॉर्ट शुरू करें।

स्पष्ट रूप से यहां एक प्रदर्शन समस्या है, क्योंकि आप पहले से रिकॉर्ड के दो बार लिख रहे हैं, और फ्लश/सिंक आश्चर्यजनक रूप से महंगा हो सकता है। व्यावहारिक रूप से आपके इन-प्लेस सॉर्ट में कुछ कंपाउंड मूविंग-स्टफ ऑपरेशंस हो सकते हैं, जिसमें कई स्वैप शामिल होते हैं, लेकिन स्क्रैच स्पेस को मारने वाले प्रत्येक तत्व से बचने के लिए आप अनुकूलित कर सकते हैं। आपको बस यह सुनिश्चित करना होगा कि किसी भी डेटा को ओवरराइट करने से पहले, आपके पास इसकी एक प्रति कहीं सुरक्षित है और उस फ़ाइल का एक रिकॉर्ड जहां आपकी फ़ाइल को उस स्थिति में वापस लाने के लिए जाना चाहिए जहां इसमें प्रत्येक तत्व की बिल्कुल एक प्रति है।

जेरी का यह भी सही है कि सही जगह-जगह सॉर्टिंग सबसे व्यावहारिक उद्देश्यों के लिए बहुत कठिन और धीमी है। यदि आप स्क्रैच स्पेस के रूप में मूल फ़ाइल आकार के कुछ रैखिक अंश को छोड़ सकते हैं, तो आपके पास मर्ज सॉर्ट के साथ इसका बेहतर समय होगा।

आपकी स्पष्टीकरण के आधार पर, आपको इन-प्लेस प्रकार के साथ भी किसी भी फ्लश ऑपरेशन की आवश्यकता नहीं होगी। आप स्मृति में खरोंच अंतरिक्ष कि उसी तरह काम करता है, और अपने SIGINT हैंडलर बाहर निकलने के बजाय बाद एक असामान्य बाहर निकलने के स्टार्टअप पर बहाल करने से पहले आदेश सुरक्षित डेटा प्राप्त करने के लिए उपयोग कर सकते हैं कि जरूरत है, और आप उस स्मृति का उपयोग करने की आवश्यकता है सिग्नल-सुरक्षित तरीके से (जो तकनीकी रूप से sig_atomic_t का उपयोग करके ध्वजांकित करने के लिए उपयोग करता है)। फिर भी, आप शायद एक वास्तविक जगह-जगह के मुकाबले एक विलय के साथ बेहतर हो।

+0

मैं स्क्रैच स्पेस के लिए मेमोरी मैप की गई फ़ाइल का उपयोग करने के बारे में सोचूंगा। यह आपको दोनों दुनिया के सर्वश्रेष्ठ प्रदान करना चाहिए। 1) एक्सेस के लिए कम ओवरहेड क्योंकि यह कैश किया गया है और कोई एपीआई कॉलल्स 2 नहीं है) यदि प्रक्रिया मर जाती है तो ओएस को अभी भी संशोधित मेमोरी को डिस्क पर फ्लश करना चाहिए चाहे प्रक्रिया कैसे मर जाती है। – torak

+0

@ टोरक: ग्रेट न्यूज, मुझे नहीं पता था कि पॉज़िक्स ने एमएमएपी के लिए गारंटी प्रदान की है। मुझे अभी भी चिंता है कि फाइल तक पहुंच को फिर से व्यवस्थित किया जा सकता है, हालांकि, इसे पुनर्प्राप्ति के लिए अविश्वसनीय बना दिया गया है। तो सभी पॉइंटर्स को 'अस्थिर' या कुछ होना चाहिए। –

+0

आपको प्रत्येक फ्लश बिंदु पर 'MS_SYNC' के साथ' msync() 'का उपयोग करने की आवश्यकता होगी। 'msync()' को एक कंपाइलर बाधा का भी अर्थ देना चाहिए, इसलिए 'अस्थिर' आवश्यक नहीं होना चाहिए। – caf

5

ctrl-c के विरुद्ध सुरक्षा के लिए भाग बहुत आसान है: signal(SIGINT, SIG_IGN);

जहां तक ​​सॉर्टिंग स्वयं जाती है, एक मर्ज सॉर्ट आमतौर पर बाहरी सॉर्टिंग के लिए अच्छी तरह से काम करता है। मूल विचार स्मृति में जितना रिकॉर्ड हो सके उतना रिकॉर्ड पढ़ना है, उन्हें सॉर्ट करें, फिर उन्हें डिस्क पर वापस लिखें। इसे संभालने का सबसे आसान तरीका डिस्क पर एक अलग फ़ाइल में प्रत्येक रन लिखना है। फिर आप उन्हें एक साथ वापस विलय करते हैं - प्रत्येक रन से पहले रिकॉर्ड को स्मृति में पढ़ें, और उनमें से सबसे छोटे को मूल फ़ाइल में लिखें; उस रिकॉर्ड की आपूर्ति करने वाले रन से एक और रिकॉर्ड पढ़ें, और पूरा होने तक दोहराना। अंतिम चरण एकमात्र समय है जब आप मूल फ़ाइल को संशोधित कर रहे हैं, इसलिए यह केवल एकमात्र समय है जब आपको वास्तव में बाधाओं और इस तरह के आश्वासन के लिए आश्वस्त करने की आवश्यकता होती है।

एक और विकल्प चयन प्रकार का उपयोग करना है। बुरा मुद्दा यह है कि सॉर्टिंग स्वयं धीमी है। अच्छा मुद्दा यह है कि अधिक अतिरिक्त जगह का उपयोग किये बिना, लगभग कुछ भी जीवित रहने के लिए इसे लिखना बहुत आसान है। सामान्य विचार बहुत सरल है: फ़ाइल में सबसे छोटा रिकॉर्ड ढूंढें, और इसे पहले स्थान पर स्वैप करें। फिर जो कुछ बचा है उसका सबसे छोटा रिकॉर्ड ढूंढें, और इसे दूसरे स्थान पर स्वैप करें, और ऐसा करने तक। इसका अच्छा मुद्दा यह है कि जर्नलिंग तुच्छ है: स्वैप करने से पहले, आप उन दो रिकॉर्ड के मान रिकॉर्ड करते हैं जिन्हें आप स्वैप करने जा रहे हैं। चूंकि सॉर्ट पहले रिकॉर्ड से आखिरी तक चलता है, इसलिए आपको ट्रैक करने की आवश्यकता केवल एक ही चीज है कि किसी भी समय कितने रिकॉर्ड पहले ही सॉर्ट किए गए हैं।

+1

+1 - इन-प्लेस मांग में फिट नहीं है, लेकिन यह आईएमएचओ सबसे स्वच्छ दृष्टिकोण है। खंडों को सॉर्ट करते समय मास्टर फ़ाइल को संशोधित नहीं करता है, और यदि मर्ज प्रक्रिया क्रैश हो जाती है तो आपको सॉर्ट किए गए खंड-फ़ाइलों को बैकअप के रूप में मिला है। – snemarch

+1

'SIGINT' को अनदेखा करने के बजाय, आपको ** स्वैप परिचालनों के दौरान ** (और अन्य सभी सिग्नल) ब्लॉक करना चाहिए, लेकिन समय-समय पर इसे अनब्लॉक करना चाहिए ताकि अवरोधित किए गए लंबित संकेतों को संसाधित किया जा सके। –

-1

एक 64-बिट ओएस मानते हुए (आपने कहा कि यह 64 बिट मशीन है लेकिन अभी भी 32 बिट ओएस चल रहा है), आप फ़ाइल को सरणी में मैप करने के लिए एमएमएपी का उपयोग कर सकते हैं और सरणी पर qsort का उपयोग कर सकते हैं।

एसआईजीआईएनटी के लिए एक हैंडलर जोड़ें जो एमएसआईएनसी और मुनमैप को कॉल करने के लिए ऐप को डेटा खोए बिना Ctrl-C का जवाब देने की अनुमति देता है।

+1

-1। यदि कोई संकेत 'qsort' में बाधा डालता है, तो डेटा' अनिश्चित स्थिति तक समाप्त होता है जब तक कि 'qsort' समाप्त नहीं हो जाता है। ओपी की जरूरतों को पूरा करने के लिए सिस्टम के 'qsort' का उपयोग करने का बिल्कुल कोई तरीका नहीं है। –

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