आप इसे क्यों अनुकूलित कर रहे हैं? क्या आपने काम किया है, परीक्षण कोड लिखा है, फिर अपने एल्गोरिदम profiled को अपने कोड की जांच की और पाया कि इसका अनुकूलन प्रभाव पड़ेगा? क्या आप इसे एक गहरे आंतरिक लूप में कर रहे हैं जहां आपने पाया कि आप अपना समय व्यतीत कर रहे हैं? यदि नहीं, परेशान मत करो।
आपको केवल यह पता चलेगा कि आपके समय के लिए कौन सा सबसे तेज़ काम करता है। इसे एक उपयोगी तरीके से करने के लिए, आपको इसे अपने वास्तविक उपयोग के मामले में विशेषज्ञ बनाना होगा। उदाहरण के लिए, आप एक इनलाइन अभिव्यक्ति बनाम सूची समझ में फ़ंक्शन कॉल के बीच ध्यान देने योग्य प्रदर्शन अंतर प्राप्त कर सकते हैं; यह स्पष्ट नहीं है कि आप वास्तव में पूर्व चाहते थे या यदि आप इसे अपने मामलों को समान बनाने के लिए कम कर देते हैं।
आप कहते हैं कि इससे कोई फर्क नहीं पड़ता कि आप एक numpy सरणी या एक list
साथ खत्म हो, लेकिन आप सूक्ष्म अनुकूलन इस तरह का कार्य कर रहे हैं अगर यह फर्क पड़ता है, उन के बाद से जब आप अलग तरह से प्रदर्शन करेंगे बाद में उनका इस्तेमाल करें। उस पर अपनी उंगली डालना मुश्किल हो सकता है, इसलिए उम्मीद है कि यह पूरी समस्या को समय से पहले मूक कर देगा।
स्पष्टता, पठनीयता, और आगे के लिए नौकरी के लिए सही उपकरण का उपयोग करना आम तौर पर बेहतर होता है। यह दुर्लभ है कि मुझे इन चीजों के बीच निर्णय लेने में कठिनाई होगी।
- यदि मुझे numpy arrays की आवश्यकता है, तो मैं उनका उपयोग करूंगा। मैं इन्हें बड़े सजातीय सरणी या बहुआयामी डेटा संग्रहित करने के लिए उपयोग करता हूं। मैं उनका बहुत उपयोग करता हूं, लेकिन शायद ही कभी मुझे लगता है कि मैं एक सूची का उपयोग करना चाहता हूं।
- अगर मैं इन उपयोग कर रहा था, मैं अपने कार्यों लिखने के लिए मेरा सबसे अच्छा होता पहले से ही vectorized तो मैं
numpy.vectorize
उपयोग करने के लिए नहीं था। उदाहरण के लिए, नीचे times_five
कोई सजावट के साथ एक numpy सरणी पर इस्तेमाल किया जा सकता है।
- अगर मैं numpy का उपयोग करने के कारण नहीं था, कि अगर मैं संख्यात्मक गणित की समस्याओं को सुलझाने या विशेष numpy सुविधाओं बहुआयामी सरणियों या जो कुछ भी उपयोग कर या भंडारण नहीं किया गया था कहने के लिए ...
- तो है मेरे पास पहले से मौजूद फ़ंक्शन था, मैं
map
का उपयोग करूंगा। यही वह है।
- यदि मेरे पास एक ऑपरेशन था जो एक छोटी अभिव्यक्ति के अंदर फिट था और मुझे फ़ंक्शन की आवश्यकता नहीं थी, तो मैं एक सूची समझ का उपयोग करता था।
- अगर मैं सिर्फ सभी मामलों के लिए ऑपरेशन करना चाहता था लेकिन वास्तव में परिणाम को स्टोर करने की आवश्यकता नहीं थी, तो मैं लूप के लिए एक सादा उपयोग करता था।
- कई मामलों में, मैं वास्तव में
map
का उपयोग करता हूं और समझता हूं 'आलसी समकक्षों की सूची: itertools.imap
और जनरेटर अभिव्यक्तियां। ये कुछ मामलों में n
के कारक द्वारा स्मृति उपयोग को कम कर सकते हैं और कभी-कभी अनावश्यक संचालन करने से बच सकते हैं।
यदि यह स्पष्ट हो बारी है इस जहां प्रदर्शन की समस्याओं, झूठ हो रही बात इस तरह की सही मुश्किल है। यह बहुत आम है कि लोगों को उनकी वास्तविक समस्याओं के लिए गलत खिलौना का मामला है। इससे भी बदतर, यह बेहद आम लोगों के आधार पर गूंगा सामान्य नियम बनाते हैं।
निम्नलिखित मामलों (timeme.py नीचे पोस्ट किया जाता है)
python -m timeit "from timeme import x, times_five; from numpy import vectorize" "vectorize(times_five)(x)"
1000 loops, best of 3: 924 usec per loop
python -m timeit "from timeme import x, times_five" "[times_five(item) for item in x]"
1000 loops, best of 3: 510 usec per loop
python -m timeit "from timeme import x, times_five" "map(times_five, x)"
1000 loops, best of 3: 484 usec per loop
एक भोली obsever निष्कर्ष निकालना होगा कि नक्शा इन विकल्पों में से सबसे अच्छा प्रदर्शन है पर विचार करें, लेकिन इस सवाल का जवाब अभी भी है "यह निर्भर करता है"। आपके द्वारा उपयोग किए जा रहे टूल के लाभों का उपयोग करने की शक्ति पर विचार करें: सूची की समझ आपको सरल कार्यों को परिभाषित करने से बचने देती है; यदि आप सही चीजें कर रहे हैं तो numpy आपको सी में चीजों को सदिश करने देता है।
python -m timeit "from timeme import x, times_five" "[item + item + item + item + item for item in x]"
1000 loops, best of 3: 285 usec per loop
python -m timeit "import numpy; x = numpy.arange(1000)" "x + x + x + x + x"
10000 loops, best of 3: 39.5 usec per loop
लेकिन यह सब कुछ नहीं है। एक एल्गोरिदम परिवर्तन की शक्ति पर विचार करें। यह और भी नाटकीय हो सकता है।
python -m timeit "from timeme import x, times_five" "[5 * item for item in x]"
10000 loops, best of 3: 147 usec per loop
python -m timeit "import numpy; x = numpy.arange(1000)" "5 * x"
100000 loops, best of 3: 16.6 usec per loop
कभी-कभी एक एल्गोरिदम परिवर्तन और भी प्रभावी हो सकता है। यह अधिक से अधिक प्रभावी होगा क्योंकि संख्याएं बड़ी हो जाती हैं।
python -m timeit "from timeme import square, x" "map(square, x)"
10 loops, best of 3: 41.8 msec per loop
python -m timeit "from timeme import good_square, x" "map(good_square, x)"
1000 loops, best of 3: 370 usec per loop
और अब भी, यह सब आपकी वास्तविक समस्या पर थोड़ा असर डाल सकता है। ऐसा लगता है कि अगर आप इसे सही तरीके से उपयोग कर सकते हैं तो numpy बहुत अच्छा है, लेकिन इसकी सीमाएं हैं: इन numpy उदाहरणों में से कोई भी सरणी में वास्तविक पायथन वस्तुओं का उपयोग नहीं किया। यह जटिल है कि क्या किया जाना चाहिए; बहुत कुछ भी और क्या होगा यदि हम सी डेटाटाइप का उपयोग करते हैं? ये पाइथन वस्तुओं की तुलना में कम मजबूत हैं। वे शून्य नहीं हैं। पूर्णांक अतिप्रवाह। आपको उन्हें पुनः प्राप्त करने के लिए कुछ अतिरिक्त काम करना है। वे स्थिर रूप से टाइप कर रहे हैं। कभी-कभी ये चीजें समस्याएं साबित होती हैं, यहां तक कि अप्रत्याशित भी।
तो वहां आप जाते हैं: एक निश्चित उत्तर। "निर्भर करता है।"
# timeme.py
x = xrange(1000)
def times_five(a):
return a + a + a + a + a
def square(a):
if a == 0:
return 0
value = a
for i in xrange(a - 1):
value += a
return value
def good_square(a):
return a ** 2
क्यों नहीं यह समय की कोशिश? – mpen