2010-01-31 12 views
7

मैं एक विशिष्ट फ़िल्टर से मेल खाने वाली सूची में आइटमों की संख्या को गिनने का सबसे तेज़ तरीका ढूंढने का प्रयास कर रहा था। इस मामले में, एक सूची में कितनी विषम संख्याएं हैं, यह पता लगाना।यह जीनएक्सपी एक सूची समझ से भी बदतर क्यों है?

जबकि यह कर रहा है, मैं बनाम बराबर जनरेटर अभिव्यक्ति एक सूची समझ की तुलना के परिणाम से आश्चर्यचकित था:

python -m timeit -s "L = xrange(1000000)" "sum([1 for i in L if i & 1])" 
10 loops, best of 3: 109 msec per loop 

python -m timeit -s "L = xrange(1000000)" "sum(1 for i in L if i & 1)" 
10 loops, best of 3: 125 msec per loop 

मैं भी एल एक नियमित रूप से सूची होने के साथ की कोशिश की है, और विभिन्न आकारों, लेकिन सभी में मामलों की समझ जीतने के मामले।

जीनएक्सपी क्या कर रहा है जो सूची सूची की तुलना में धीमी हो जाती है जो 1 मिलियन वस्तुओं के साथ एक नई सूची बनाता है ...?

(Btw, सबसे तेज़ तरीका मैंने पाया था: x = 1; len(filter(x.__and__, L)) और उस तरह कोड हाँ, मैं लिख पता बिल्ली के बच्चे को मारता है, मैं इसके बारे में मनोरंजन के लिए यह कर रहा हूँ।) जब अनिवार्य रूप से असीमित स्मृति उपलब्ध है

उत्तर

15

(जो हमेशा छोटे मानकों में मामला होगा, हालांकि अक्सर वास्तविक दुनिया की समस्याओं में नहीं! -), सूचियां जनरेटर को बेहतर प्रदर्शन करती हैं क्योंकि उन्हें एक बार "बड़े गुच्छा" (कोई स्मृति विखंडन, आदि) में आवंटित नहीं किया जा सकता है, जबकि जेनरेटर को निष्पादन की बहाली की अनुमति देने के लिए स्टैक-फ्रेम स्थिति को संरक्षित करके "बड़े गुच्छा" दृष्टिकोण से बचने के लिए (आंतरिक रूप से) अतिरिक्त प्रयास की आवश्यकता होती है।

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

+0

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

3

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

अद्यतन: परीक्षण के बाद, यह रिवर्स

~% python -m timeit -s "L = xrange(1000000);oint=type('intEx', (int,),{})" "sum([oint(1) for i in L if i & 1])" 
10 loops, best of 3: 414 msec per loop 

~% python -m timeit -s "L = xrange(1000000);oint=type('intEx', (int,),{})" "sum(oint(1) for i in L if i & 1)" 
10 loops, best of 3: 392 msec per loop 
संबंधित मुद्दे