2009-07-29 16 views
11

मैं करता है कि निम्नलिखित एक आवेदन बनाया है:कई छोटी फाइलें या एक बड़ी फाइल? (या, खोलने की ओवरहेड और समापन फ़ाइल हैंडल) (C++)

  1. एक फाइल करने के लिए कुछ गणना, लिखने गणना किए गए डेटा बनाओ - 500,000 बार के लिए दोहराएँ (कुल मिलाकर, 500,000 फाइलें एक के बाद एक लिखें) - दो बार दोहराएं (कुल मिलाकर, 1.5 मिलियन फाइलें लिखी गईं)। एक फ़ाइल से
  2. पढ़ें डेटा, फ़ाइल से डेटा के साथ कुछ तीव्र गणना करने - 1500000 पुनरावृत्तियों के लिए दोहराएँ 200 पुनरावृत्तियों के लिए
  3. दोहराएँ चरण 2 (भर में चरण 1 में लिखा फ़ाइलों पुनरावृति)।

प्रत्येक फ़ाइल ~ 212k है, इसलिए मेरे पास ~ 300Gb डेटा है। ऐसा लगता है कि पूरी प्रक्रिया कोर 2 डुओ सीपीयू पर 2.8 गीगा के साथ ~ 40 दिन लगती है।

मेरी समस्या है (जैसा कि आप शायद अनुमान लगा सकते हैं) वह समय है जो पूरी प्रक्रिया को पूरा करने में लगती है। सभी गणना धारावाहिक हैं (प्रत्येक गणना पहले एक पर निर्भर है), इसलिए मैं इस प्रक्रिया को अलग-अलग CPUs या पीसी पर समानांतर नहीं कर सकता। मैं यह सोचने की कोशिश कर रहा हूं कि प्रक्रिया को और अधिक कुशल बनाने के लिए और मुझे पूरा यकीन है कि अधिकतर ओवरहेड फाइल सिस्टम एक्सेस (डुह ...) में जाता है। हर बार जब मैं एक फ़ाइल तक पहुंचता हूं तो मैं इसे एक हैंडल खोलता हूं और फिर डेटा पढ़ने के बाद इसे बंद कर देता हूं।

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

एक और विचार था कि फ़ाइलों को बड़ी ~ 100 एमबी फाइलों में बदलने और समूह करने के लिए था और फिर मैं 212k पढ़ने के बजाए हर बार 100 एमबी पढ़ता था, लेकिन उपरोक्त विचार से लागू करने के लिए यह बहुत जटिल है।

वैसे भी, अगर कोई मुझे इस पर कुछ सलाह दे सकता है या कोई विचार है कि रन टाइम में सुधार कैसे किया जाए तो मैं इसकी सराहना करता हूं!

धन्यवाद।

प्रोफाइलर अद्यतन:

मैं प्रक्रिया पर एक प्रोफाइलर भाग गया, ऐसा लगता है कि गणना क्रम का 62% लेने के लिए और फ़ाइल पढ़ने 34% लेता है। मतलब यह है कि अगर मैं चमत्कारी रूप से 34 के कारक द्वारा फ़ाइल I/o लागत को काटता हूं, तो भी मुझे 24 दिनों के साथ छोड़ दिया जाता है, जो काफी सुधार है, लेकिन अभी भी एक लंबा समय है :)

+0

क्या आपने इसे डेटाबेस में संग्रहीत करने पर विचार किया है? –

+1

मैंने इसे माना है, लेकिन क्या डेटा निष्कर्षण तेजी से कर देगा? – dudico

+0

आपने कहा कि आप निश्चित रूप से सुनिश्चित हैं कि फ़ाइलों का खुला/बंद होना एक बाधा है। क्या यह कार्यक्रम को प्रोफाइल करने के आधार पर एक झुकाव है या यह एक सामान्य झुकाव से अधिक है? यदि यह उत्तरार्द्ध है तो मैं गंभीरता से आपके कोड को प्रोफाइल करने का सुझाव दूंगा। –

उत्तर

9

फ़ाइल हैंडल खोलना isn ' बाधा होने की संभावना नहीं है; वास्तविक डिस्क आईओ है। यदि आप डिस्क एक्सेस को समानांतर कर सकते हैं (उदाहरण के लिए एकाधिक डिस्क, तेज डिस्क, एक रैम डिस्क, ...) का उपयोग करके आप और अधिक लाभ उठा सकते हैं। साथ ही, सुनिश्चित करें कि IO एप्लिकेशन को अवरुद्ध न करें: डिस्क से पढ़ें, और आईओ की प्रतीक्षा करते समय प्रक्रिया करें। जैसे एक पाठक और एक प्रोसेसर थ्रेड के साथ।

एक और बात: यदि अगला चरण वर्तमान गणना पर निर्भर करता है, तो इसे डिस्क पर सहेजने के प्रयास के माध्यम से क्यों जाएं? शायद प्रक्रिया 'निर्भरताओं पर एक और विचार के साथ आप डेटा प्रवाह को फिर से काम कर सकते हैं और बहुत से आईओ से छुटकारा पा सकते हैं।

अरे हाँ, और उपाय यह :)

+0

मैं केवल पहले चरण पर डेटा सहेजता हूं, और इसे दूसरे चरण पर उपयोग करता हूं, मुझे फ़ाइलों को डेटा सहेजना होगा। वास्तव में डिस्क से पढ़ने के लिए एक और थ्रेड का उपयोग करने की सलाह एक अच्छा विचार की तरह लगता है। – dudico

+0

"इसे डिस्क पर सहेजने के प्रयास के माध्यम से क्यों जाना है?" सबसे अधिक संभावना है कि उसके पास 300 जीबी रैम नहीं है। –

+0

@onebyone: लेकिन वह * कहता है * वह पिछले चरण की गणना करने के लिए पिछले चरण के परिणाम पर निर्भर करता है, और 1 कदम लगभग 212 केबी है, इसलिए ... – xtofl

2

का उपयोग करते हुए स्मृति मैप किए गए के रूप में यह प्रणाली कॉल की संख्या कम हो जाएगा फ़ाइलों जांच की जानी चाहिए।

+0

स्मृति में मैप किए गए एक बड़ी फ़ाइल का उपयोग करने के रूप में? – dudico

+0

बिल्कुल नहीं, यह छोटी और बड़ी फ़ाइलों के लिए किया जा सकता है, लेकिन अधिकतम प्रक्रिया पता स्थान (32 बिट के आसपास 32 बिट पर) तक सीमित है। आपको ओएस से मेमोरी मैप की गई फ़ाइलों के लिए समर्थन की आवश्यकता है। मूल रूप से वर्चुअल मेमोरी मैनेजर प्रक्रिया पता स्थान पर फ़ाइलों को मैप करने का ख्याल रखता है। यूनिक्स में यह mmap कॉल और windowsfilemapping कॉल द्वारा विंडो में प्रदान किया जाता है। – steve

+0

एक 64 बिट ओएस 300 एमबी सभी को एक संगत पता सीमा में मैप करने में सक्षम होना चाहिए। –

9

प्रत्येक फ़ाइल ~ 212k है, इसलिए मेरे पास ~ 300Gb डेटा है। ऐसा लगता है कि पूरी प्रक्रिया में ~ 40 दिन लगते हैं ... गणना सीरियल (प्रत्येक गणना पहले पर निर्भर है), इसलिए मैं प्रक्रिया को विभिन्न CPUs या पीसी पर समानांतर नहीं कर सकता। ... सुंदर सुनिश्चित करें कि अधिकतर ओवरहेड फ़ाइल सिस्टम पहुंच पर जाता है ... प्रत्येक समय मैं एक फ़ाइल तक पहुंचता हूं, मैं इसे पर एक हैंडल खोलता हूं और फिर डेटा पढ़ने के बाद इसे बंद करता हूं।

डेटा लिखने के 300 जीबी डेटा में 40 मिनट लग सकते हैं, केवल 40 दिनों का एक छोटा सा अंश। डिस्क लिखने का प्रदर्शन यहां कोई मुद्दा नहीं होना चाहिए।

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

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

+0

40 जीबी के लिए 300 जीबी 5 एमबी प्रति मिनट तक काम करता है। – Pacerier

4

कोई भी बदलाव करने से पहले यह पता लगाने के लिए एक प्रोफाइलर ट्रेस चलाने के लिए उपयोगी हो सकता है कि वास्तव में वास्तविक समस्या को अनुकूलित करने के लिए अधिकांश समय व्यतीत किया जाता है।

4

SQLite का उपयोग करने के बारे में क्या? मुझे लगता है कि आप एक ही टेबल से दूर हो सकते हैं।

+1

मैंने इसे माना है, लेकिन क्या यह डेटा निष्कर्षण तेज़ी से कर देगा? – dudico

+0

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

+1

मुझे अनुक्रमण की आवश्यकता नहीं है क्योंकि मुझे फ़ाइल की शुरुआत से सटीक ऑफ़सेट पता चलेगा। कैशिंग मदद कर सकता है, लेकिन यह कैश कार्यान्वयन पर निर्भर करता है। – dudico

3

आपकी संक्षिप्त व्याख्या से यह लगता है कि धागे के xtofl सुझाव जाने का सही तरीका है। मैं आपको यह सुनिश्चित करने के लिए पहले अपना आवेदन प्रोफाइल करने की सलाह दूंगा कि समय आईओ को एक सीपीयू के बीच बांटा गया है।

तब मैं तीन कतारों में तीन धागे से जुड़ने पर विचार करता हूं।

  1. थ्रेड 1 फाइलें पढ़ता है और उन्हें रैम में लोड करता है, फिर कतार में डेटा/पॉइंटर्स रखता है। यदि कतार एक निश्चित आकार से अधिक हो जाती है तो थ्रेड सो जाता है, अगर यह फिर से शुरू होने पर एक निश्चित आकार से नीचे चला जाता है।
  2. थ्रेड 2 कतार बंद डेटा पढ़ता है और करता गणना तो दूसरी कतार में डेटा लिखता है
  3. थ्रेड 3 दूसरी पंक्ति पढ़ता है और डिस्क

में डेटा लिखता है आप धागा 1 विलय पर विचार कर सकते और 3, यह डिस्क पर विवाद को कम कर सकता है क्योंकि आपका ऐप एक समय में केवल एक डिस्क ऑप करेगा।

ऑपरेटिंग सिस्टम सभी फ़ाइलों को कैसे संभालता है? क्या वे सभी एक निर्देशिका में हैं? जब आप निर्देशिका ब्राउज़ करते हैं तो प्रदर्शन क्या होता है (gui filemanager/dir/ls)? यदि यह प्रदर्शन खराब है तो आप अपने फाइल सिस्टम आराम क्षेत्र के बाहर काम कर रहे हैं। यद्यपि आप इसे यूनिक्स पर ही बदल सकते हैं, कुछ फाइल सिस्टम विभिन्न प्रकार के फ़ाइल उपयोग के लिए ऑप्टिमाइज़ किए जाते हैं, उदाहरण के लिए बड़ी फाइलें, बहुत सी छोटी फाइलें आदि। आप विभिन्न निर्देशिकाओं में फ़ाइलों को विभाजित करने पर भी विचार कर सकते हैं।

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