2012-04-30 5 views
20

मेरे पास एक बहुत बड़ी टेक्स्ट फ़ाइलें (+ 10 जीबी) है जो मैं कुछ डेटा खनन तकनीकों के लिए पढ़ना चाहता हूं। ऐसा करने के लिए, मैं एमपीआई के साथ समांतर तकनीकी का उपयोग करता हूं, इसलिए कई प्रक्रियाएं एक ही फ़ाइल में एक साथ पहुंच सकती हैं।
असल में, मैं चाहता हूं कि प्रत्येक प्रक्रिया एन लाइनों की संख्या पढ़ें। चूंकि फ़ाइल संरचित नहीं है (फ़ील्ड की एक ही संख्या है लेकिन प्रत्येक फ़ील्ड में वर्णों की अलग-अलग संख्या हो सकती है), मैं फ़ाइल को पार्स करने के दायित्व में हूं और यह समानांतर नहीं है और इसमें काफी समय लगता है। क्या लाइन की एक विशिष्ट संख्या को सीधे पार्सिंग और लाइनों की गिनती करने का कोई तरीका है? आपकी मदद के लिए धन्यवाद।बहुत बड़ी टेक्स्ट फ़ाइल पर सीधे और कुशलता से कैसे पहुंचे?

उत्तर

21

यदि आपकी फ़ाइल अन्यथा अनुक्रमित नहीं है, तो कोई प्रत्यक्ष तरीका नहीं है।

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

अन्यथा, यदि आपको बिल्कुल की सभी संख्याओं की आवश्यकता नहीं है, तो आप लाइनों/वस्तुओं की एक ही संख्या में, आप इसे केवल खराब कर सकते हैं।
किसी दिए गए ऑफसेट (1 जी कहें) की तलाश करें, और निकटतम लाइन विभाजक की तलाश करें। ऑफ़सेट 2 जी, आदि पर दोहराएं जब तक आपको पर्याप्त ब्रेक पॉइंट नहीं मिल जाते।

फिर आप अपने द्वारा पहचाने गए प्रत्येक भाग पर अपने समांतर कार्यों को बंद कर सकते हैं।

+0

आपके उत्तर के लिए धन्यवाद। मुझे लगता है कि दूसरा विचार बेहतर है क्योंकि मैं आमतौर पर समय पर फाइल को पार्स करता हूं। तो इस समाधान पर विचार करते हुए, मैं प्रत्येक प्रक्रिया को एक विशिष्ट ऑफ़सेट से एक्सेस कर दूंगा (फ़ाइल_साइज/process_number * process_rank) तो मैं एक नई लाइन की शुरुआत की तलाश करता हूं। तो मैं बदतर संख्या_of_process लाइनों पर ढीला होगा? – ezzakrem

+0

+1 लाइन ब्रेक खोजने और अन्य प्रक्रियाओं में इंडेक्स को सौंपने के लिए एक बार स्कैनिंग किसी और चीज के लिए पूरी तरह से पसंद है, क्योंकि किसी भी यादृच्छिक खोज के अनुसार कुछ भी फ़ील्ड की पार्सिंग को समानांतर करने से आप जो कुछ भी खरीद सकते हैं उससे अधिक महंगा परिमाण के कई आदेश होंगे एक पाठ फ़ाइल। बफर कैश से अनुक्रमिक पढ़ता है और खींच रहा है, बाकी सब कुछ अनुकूलन को हरा देता है। – Damon

+0

@ ezzakrem: यदि आप कुछ लाइनों को पार्स नहीं कर सकते हैं, तो मुझे लगता है कि आप ऐसा कर सकते हैं। लेकिन मैं नहीं करूँगा। अपने मुख्य "थ्रेड" में श्रमिकों को उखाड़ फेंकने से पहले, आपको आवश्यक सभी ब्रेक पॉइंट मिलते हैं। आप उन्हें शुरू करने से पहले प्रत्येक श्रमिक को प्रारंभ/समाप्ति ऑफ़सेट देते हैं। – Mat

4

कोई नहीं है: जब तक कि आप अपने अज्ञात डेटा को नहीं पढ़ते, कोई भी नहीं जानता कि कितने नए लाइन वर्ण हैं। यह समस्या जटिलता ओ (एन) है जिसका अर्थ है कि कम से कम एक बार आपको पूरी फ़ाइल को पढ़ना होगा। फिर आप एक इंडेक्स टेबल बनाना चाहेंगे जहां आप रिकॉर्ड करते हैं कि आपकी फाइल में नए लाइन अक्षर कहां हैं: इसका उपयोग सभी प्रक्रियाओं द्वारा किया जा सकता है और fseek के साथ आप नाटकीय रूप से आगे की पहुंच बढ़ा सकते हैं।

+0

प्रतिक्रिया के लिए धन्यवाद, यह एक अच्छा समाधान लगता है। मैं ऐसा करूँगा और देख सकता हूं कि सीरियल मोड में यह मूल्यवान है, मैंने एक फ़ाइल पढ़ी है, फिर प्रत्येक पंक्ति के लिए मैं कई सीपीयू कंप्यूटिंग करता हूं। अब तक मेरे पास दो समाधान हैं: मैं एक अनुक्रमणिका फ़ाइल बनाने के लिए फ़ाइल पार्स करता हूं तो सभी प्रक्रियाएं इसका उपयोग कर सकती हैं। या मैं फ़ाइल से एक प्रक्रिया पढ़ता हूं और अन्य प्रक्रियाओं को गणना करता हूं। – ezzakrem

+0

ओ (एन) के साथ मैंने इस नोटेशन को संदर्भित किया: http://en.wikipedia.org/wiki/Time_complexity#Linear_time वैसे, इंडेक्सिंग को पैराल निष्पादित करना बहुत आसान है। यदि आपके पास कई प्रक्रियाएं हैं, तो आप indexing_ के लिए फ़ाइल _also को विभाजित कर सकते हैं, तो मान लें कि पहली प्रक्रिया पहली जीबी, द्वितीय 2, आदि के माध्यम से पढ़ती है और सभी नए साझा वर्णों की स्थिति को उसी साझा संसाधन में सहेजते हैं । यह इंडेक्सिंग भी तेज कर सकता है। हालांकि भूलें कि आपके द्वारा उपयोग किए जाने वाले स्टोरेज हार्डवेयर के आधार पर, अनुक्रमिक पढ़ने बहुत तेज हो सकता है। – MrTJ

+0

तो यह दो चरणों मिश्रण करने के बारे में है 1- एन प्रक्रियाओं को इंडेक्स प्राप्त करने के रूप में आपने कहा है। 2- सीपीयू कंप्यूटिंग के लिए, प्रत्येक प्रक्रिया विशिष्ट ऑफसेट पर सीधे fseek() के साथ पहुंच जाती है। यह कोशिश करने के लिए अच्छा लग रहा है। वैकल्पिक सोच के लिए – ezzakrem

10

यहाँ क्या उल्लेख किया गया है परे कुछ अन्य विकल्प है कि पूरी फ़ाइल को स्कैन की जरूरत नहीं होगी:

  1. एक मास्टर प्रक्रिया है कि बच्चे प्रक्रियाओं है कि वास्तविक प्रसंस्करण करने के लिए पाइप/FIFOs के माध्यम से लाइनों को धक्का कर सकते हैं। यह थोड़ा धीमा हो सकता है लेकिन यदि उपप्रोसेस में बिताए गए 9 0% समय ग्रंथों की वास्तविक क्रंचिंग है, तो यह ठीक होना चाहिए।

  2. एक बेवकूफ लेकिन प्रभावी चाल: कहें कि आपके पास एन प्रक्रियाएं हैं, और आप प्रत्येक प्रक्रिया को argv या कुछ "सीरियल नंबर" के रूप में बता सकते हैं। processor -serial_number [1|2|3...N] -num_procs N, वे सभी एक ही डेटा को पढ़ सकते हैं, लेकिन केवल 0 लाइनों को संसाधित करते हैं जिनमें lineno % num_procs == serial_number है। यह थोड़ा कम कुशल है क्योंकि वे सभी पूरे डेटा को पढ़ेंगे, लेकिन फिर, अगर वे केवल प्रत्येक एनथ लाइन पर काम करते हैं, और यही वह समय है जो आपको अधिकतर खाता है, तो आपको ठीक होना चाहिए।

+1

+1 धन्यवाद। कभी-कभी जीतने का सबसे अच्छा तरीका नियमों को बदलना है। –

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