2009-05-11 14 views
11

इस अजगर कार्यक्रम पर विचार करें:क्या पाइथन IO को तेज़ करना संभव है?

import sys 

lc = 0 
for line in open(sys.argv[1]): 
    lc = lc + 1 

print lc, sys.argv[1] 

मेरी 6GB पाठ फ़ाइल पर यह चल रहा है, यह ~ 2minutes में पूरा करता है।

प्रश्न: यह संभव है तेजी से जाने के लिए?

ध्यान दें कि एक ही समय के लिए आवश्यक है:

wc -l myfile.txt 

हां, तो मुझे लगता है मेरी quesion को anwer सिर्फ एक सादे "नहीं" है।

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

(फ़ाइल में एक पंक्ति गिनती मेटाडाटा रखने की तरह) दे कृपया

पीएस: मैंने इस सवाल को "लिनक्स" टैग किया है, क्योंकि मुझे केवल लिनक्स-विशिष्ट उत्तरों में दिलचस्पी है। यदि आपके पास है तो ओएस-अज्ञेयवादी, या यहां तक ​​कि अन्य ओएस उत्तरों देने के लिए स्वतंत्र महसूस करें।

भी देखें follow-up question

+3

यहाँ एक बहुत ही इसी तरह की चर्चा के लिए एक नजर है: http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python – SilentGhost

+3

संभावना समय के थोक यहां डिस्क पर इंतजार किया गया है। –

+0

मुझे पार्टी के लिए देर हो चुकी है, लेकिन बड़ी फाइलों के लिए "sed -n '$ =' filename" "wc -l" – philshem

उत्तर

3

आप किसी भी अधिक से अधिक डिस्क पढ़ने गति से भी तेज नहीं मिल सकता है।

अधिकतम डिस्क गति आपको निम्न दो युक्तियों का उपयोग कर सकते हैं तक पहुंचने के लिए:

  1. एक बड़ा बफर के साथ में फ़ाइल पढ़ें। इसे या तो io.BufferedReader (python2.6 + में उपलब्ध) का उपयोग करके "मैन्युअल" या बस कोड किया जा सकता है।
  2. समानांतर में, किसी अन्य थ्रेड में नई लाइन गिनती करें।
+2

-1 देखें नहीं कि किसी अन्य धागे में नई लाइन गिनती कैसे हो सकती है। यह सिर्फ चीजों को धीमा कर देगा। धागे की प्रतीक्षा करने से आप तेजी से इंतजार नहीं कर सकते हैं। – nosklo

+4

आम तौर पर आप सही होंगे। हालांकि, इस मामले में फ़ाइल से थ्रेड पढ़ने से I/O की प्रतीक्षा होगी जबकि अन्य थ्रेड न्यूलाइन को पार कर जाएगा। इस तरह - पाठक धागा परिणामस्वरूप पढ़ने के बीच न्यूलाइन को पार्स करने के लिए पार्सर थ्रेड के लिए इंतजार नहीं करेगा। – Barakando

+0

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

5

सादे "नहीं"।

आप काफी अधिकतम डिस्क गति पहुँच गए हैं।

मेरा मतलब है, आप फ़ाइल को mmap फ़ाइल कर सकते हैं, या इसे बाइनरी भागों में पढ़ सकते हैं, और .count('\n') या कुछ का उपयोग कर सकते हैं। लेकिन यह बड़े सुधार देने की संभावना नहीं है।

4

आप मान यदि यह एक डिस्क 60MB पढ़ सकते हैं/s आप 6000/60 = 100 सेकंड है, जो 1 मिनट 40 सेकंड है आवश्यकता होगी। मुझे नहीं लगता कि आप तेजी से प्राप्त कर सकते हैं क्योंकि डिस्क बाधा है।

+1

आपकी गणना में 20 कहां से आया है? क्या आपका मतलब 6000/60 = 100 था? 60 नहीं 20, है ना? –

+0

मैं पहली बार 20 एमबी/एस के साथ इसकी गणना करना चाहता था, लेकिन फिर मैंने सोचा कि यह बहुत धीमी है। –

1

के रूप में अन्य लोगों ने कहा - "नहीं"

लगभग अपने समय के सभी आईओ के लिए इंतज़ार कर खर्च किया जाता है। यह कुछ ऐसा है कि आप एक बार से अधिक करने की ज़रूरत है, तो और आप राम की टन के साथ एक मशीन है, तो आप स्मृति में फ़ाइल रख सकता है। यदि आपकी मशीन में 16 जीबी रैम है, तो आपके पास खेलने के लिए/dev/shm पर 8GB उपलब्ध होगा।

एक अन्य विकल्प: आप एक से अधिक मशीन है , तो इस समस्या parallelize करने तुच्छ है। इसे कई मशीनों के बीच विभाजित करें, उनमें से प्रत्येक अपनी नई लाइनों को गिनती है, और परिणाम जोड़ती है।

1

ध्यान दें कि पायथन I/O सी में लागू किया गया है, इसलिए आगे बढ़ने में बहुत भाग्य नहीं है।

+2

आप पूरी तरह से खराब और धीमी सी कोड लिख सकते हैं, इस प्रकार यदि सी में लिखा गया है तो यह गारंटी नहीं देता है कि यह तेज़ होगा। और वहां ओवरहेड्स हो सकते हैं (उदाहरण के लिए बाइटकोड की व्याख्या करना, पंक्तियों और पुनरावृत्तियों द्वारा पढ़ने के लिए) जो इसे धीमा कर सकते हैं। – Davide

12

समस्या पर हार्डवेयर फेंको।

जैसा कि जीएस ने बताया, आपकी बाधा हार्ड डिस्क स्थानांतरण दर है। इसलिए, आप अपना समय सुधारने के लिए बेहतर एल्गोरिदम का उपयोग नहीं कर सकते हैं, लेकिन आप एक तेज हार्ड ड्राइव खरीद सकते हैं।

संपादित करें: जीएस द्वारा एक और अच्छा बिंदु; आप अपनी गति को बेहतर बनाने के लिए RAID कॉन्फ़िगरेशन का भी उपयोग कर सकते हैं। यह या तो hardware या सॉफ़्टवेयर (उदाहरण के लिए OS X, Linux, Windows Server, आदि के साथ किया जा सकता है)।


शासी समीकरण

(Amount to transfer)/(transfer rate) = (time to transfer)

(6000 MB)/(60 MB/s) = 100 seconds

(6000 MB)/(125 MB/s) = 48 seconds


हार्डवेयर समाधान

The ioDrive Duo माना जाता है कि कॉर्पोरेट सेटिंग के लिए सबसे तेज़ समाधान है, और "अप्रैल 200 9 में उपलब्ध होगा"।

या आप डब्ल्यूडी वेलोसिराप्टर हार्ड ड्राइव (10,000 आरपीएम) देख सकते हैं।

इसके अलावा, मुझे लगता है कि सीगेट Cheetah एक अच्छा विकल्प है (125 एमबी/एस स्थानांतरण दर के साथ 15,000 आरपीएम)।

+3

RAID बहुत तेज हो सकता है। –

7

चाल इलेक्ट्रान को तेज़ी से आगे बढ़ाना नहीं है (यह करना मुश्किल है) लेकिन समय की प्रति इकाई अधिक काम करने के लिए।

सबसे पहले, सुनिश्चित करें कि आपकी 6 जीबी फ़ाइल पढ़ी गई है I/O बाध्य है, सीपीयू बाध्य नहीं है।

यदि यह I/O बाध्य है, तो "फैन-आउट" डिज़ाइन पैटर्न पर विचार करें।

  • एक मूल प्रक्रिया बच्चों का एक समूह spawns।

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

    एक पाइप संचार के लिए एक इन-मेमोरी चैनल है। यह एक पाठक और एक लेखक के साथ एक साझा बफर है।

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

+0

शायद (तीसरे बुलेट पर) का मतलब है कि सभी बच्चों को स्मृति में एक दूसरे से बात करनी चाहिए, क्योंकि डिस्क पहले से ही बहुत व्यस्त है – Davide

+0

पाइप्स * इन-मेमोरी संचार चैनल हैं। –

+0

हां, लेकिन आपके तीसरे बुलेट में आपने लिखा था: "प्रत्येक बच्चे को शायद एक साधारण डिस्क फ़ाइल लिखनी चाहिए।" – Davide

1

2 मिनट पूरे 6 जीबी फ़ाइल को पढ़ने के अधिकार के बारे में लगता है। चीजों को गति देने के लिए एल्गोरिदम या ओएस में आप वास्तव में बहुत कुछ नहीं कर सकते हैं।मुझे लगता है कि आपके पास दो विकल्प हैं:

  1. समस्या पर पैसे फेंको और बेहतर हार्डवेयर प्राप्त करें। यदि यह परियोजना आपके काम के लिए है तो शायद सबसे अच्छा विकल्प।

  2. पूरी फ़ाइल को न पढ़ें। मुझे नहीं पता कि आप डेटा के साथ क्या करने की कोशिश कर रहे हैं, तो हो सकता है कि आपके पास पूरी चीज़ को पढ़ने के अलावा कोई विकल्प न हो। दूसरी तरफ यदि आप एक विशेष चीज़ के लिए पूरी फाइल स्कैन कर रहे हैं, तो हो सकता है कि शुरुआत में कुछ मेटाडेटा डालने में मददगार होगा।

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