क्यों अधिकतम की तुलना में धीमी है?


92

मैंने पाया है कि पायथन 2 और 3 में कार्य maxकी तुलना में धीमी है sort

अजगर २

$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 239 usec per loop
$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'max(a)'        
1000 loops, best of 3: 342 usec per loop

अजगर ३

$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 252 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a)'
1000 loops, best of 3: 371 usec per loop

क्यों है max ( O(n)) की तुलना में धीमी sortसमारोह ( O(nlogn))?


3
आपने पायथन 2 विश्लेषण को एक बार चलाया और पायथन 3 कोड बिल्कुल समान है।
erip

9
a.sort()काम करता है। कोशिशsorted(a)
एंड्रिया कोरबेलिनी

यदि आपने इसे ठीक कर लिया है, तो इसे ठीक करने के लिए आपने जो किया था, उसे वापस पोस्ट करें।
प्रेट्ज़ेल

4
@Pretzel OP का मतलब है कि पोस्ट को एडिट किया गया है, न कि इस समस्या को ठीक किया गया है।
erip

2
@ WeizhongTu लेकिन sortसॉर्ट करता है, और फिर aहमेशा के लिए सॉर्ट किया जाता है
njzk2

जवाबों:


125

timeitपायथन में मॉड्यूल का उपयोग करते समय आपको बहुत सावधान रहना होगा ।

python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'

यहां रैंडमाइज्ड ऐरे तैयार करने के लिए इनिशियल कोड एक बार चलता है a। फिर बाकी कोड कई बार चलाया जाता है। पहली बार यह सरणी को सॉर्ट करता है, लेकिन हर बार जब आप पहले से सॉर्ट किए गए सरणी पर सॉर्ट विधि को कॉल कर रहे होते हैं। केवल सबसे तेज़ समय लौटाया जाता है, इसलिए आप वास्तव में समय दे रहे हैं कि पहले से ही सॉर्ट किए गए सरणी को क्रमबद्ध करने में अजगर को कितना समय लगता है।

पायथन के सॉर्ट एल्गोरिथ्म का हिस्सा यह पता लगाने के लिए है कि सरणी पहले से आंशिक रूप से या पूरी तरह से सॉर्ट की गई है। जब यह पूरी तरह से हल हो जाता है तो इसे यह पता लगाने के लिए सरणी के माध्यम से एक बार स्कैन करना पड़ता है और फिर यह बंद हो जाता है।

अगर इसके बजाय आपने कोशिश की:

python -m timeit -s 'import random;a=range(100000);random.shuffle(a)' 'sorted(a)[-1]'

तब सॉर्ट हर टाइमिंग लूप पर होता है और आप देख सकते हैं कि किसी ऐरे को छांटने का समय वास्तव में सिर्फ ज्यादा से ज्यादा वैल्यू खोजने के लिए ज्यादा लंबा होता है।

संपादित करें: @ स्काइकिंग का उत्तर बताता है कि मैंने जिस हिस्से को अस्पष्टीकृत छोड़ दिया है: a.sort()वह जानता है कि यह एक सूची पर काम कर रहा है ताकि सीधे तत्वों तक पहुंच सके। max(a)किसी भी मनमाना चलने पर काम करता है ताकि सामान्य पुनरावृत्ति का उपयोग किया जा सके।


10
अच्छी पकड़। मुझे कभी भी यह महसूस नहीं हुआ कि कोड रन के दौरान दुभाषिया राज्य बरकरार रहता है। अब मुझे आश्चर्य है कि मैंने अतीत में कितने दोषपूर्ण मानक बनाए। : -}
Frerich Raabe

1
मेरे लिए यह बहुत स्पष्ट था। लेकिन ध्यान दें कि यदि आप पहले से ही सॉर्ट किए गए सरणी को सॉर्ट करते हैं, तो भी आपको सभी तत्वों की जांच करनी होगी। जो अधिकतम प्राप्त करने के समान ही काम है .... मेरे लिए यह एक आधे उत्तर की तरह दिखता है।
कारोली होर्वाथ

2
@KarolyHorvath, आप सही हैं। मुझे लगता है कि @skyking को जवाब का दूसरा हिस्सा मिला: a.sort()जानता है कि यह एक सूची पर काम कर रहा है ताकि सीधे तत्वों तक पहुंच सके। max(a)ओटी का सामान्य उपयोग करने के लिए एक मनमाना अनुक्रम पर काम करता है।
डंकन

1
@KarolyHorvath शायद शाखा की भविष्यवाणी समझा सकते हैं कि बार-बार सॉर्ट किए गए सरणी को क्यों
छांटना

1
@JuniorCompressor listsort.txt"यह आंशिक रूप से ऑर्डर किए गए सरणियों (कम से कम g (एन!) तुलना की आवश्यकता है, और एन -1 के रूप में कुछ) के कई प्रकार पर अलौकिक प्रदर्शन है" और फिर सभी प्रकार के अनुकूलन अनुकूलन की व्याख्या करता है। मुझे लगता है कि यह बहुत सारी धारणाएं बना maxसकता है जो नहीं कर सकते हैं, यानी छांटना asymptotically तेज नहीं है।
Frerich Raabe

87

सबसे पहले, ध्यान दें कि max()itter प्रोटोकॉल list.sort()का उपयोग करता है , जबकि तदर्थ कोड का उपयोग करता है । स्पष्ट रूप से, एक इटरेटर का उपयोग करना एक महत्वपूर्ण ओवरहेड है, इसीलिए आप उस अंतर को समय में देख रहे हैं।

हालाँकि, इसके अलावा, आपके परीक्षण निष्पक्ष नहीं हैं। आप a.sort()एक से अधिक बार एक ही सूची में चल रहे हैं । अजगर द्वारा प्रयोग किया जाता एल्गोरिथ्म विशेष रूप से पहले से ही के लिए तेजी से डिज़ाइन किया गया है (आंशिक रूप से) डेटा सॉर्ट किया। आपके परीक्षण कह रहे हैं कि एल्गोरिथ्म अपना काम अच्छी तरह से कर रहा है।

ये निष्पक्ष परीक्षण हैं:

$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a[:])'
1000 loops, best of 3: 227 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a[:].sort()'
100 loops, best of 3: 2.28 msec per loop

यहां मैं हर बार सूची की एक प्रति बना रहा हूं। जैसा कि आप देख सकते हैं, परिणामों की परिमाण के क्रम अलग-अलग हैं: सूक्ष्म बनाम मिलीसेकंड, जैसा कि हम उम्मीद करेंगे।

और याद रखें: बड़ा-ओह एक ऊपरी सीमा को निर्दिष्ट करता है! पायथन की छँटाई एल्गोरिथ्म के लिए निचली सीमा n ( n ) है। O ( n log n ) होने का मतलब यह नहीं है कि प्रत्येक रन n लॉग एन के आनुपातिक समय के लिए होता है । इसका अर्थ यह भी नहीं है कि इसे O ( n ) एल्गोरिथम की तुलना में धीमा होना चाहिए , लेकिन यह एक और कहानी है। यह समझना महत्वपूर्ण है कि कुछ अनुकूल मामलों में, एक O ( n लॉग एन ) एल्गोरिथ्म O ( n ) समय या उससे कम में चल सकता है।


31

यह हो सकता है क्योंकि l.sortएक सदस्य है listजबकि maxएक सामान्य कार्य है। इसका मतलब यह है कि उस समय l.sortके आंतरिक प्रतिनिधित्व पर भरोसा कर सकते हैं, listजबकि maxसामान्य पुनरावृत्ति प्रोटोकॉल से गुजरना होगा।

यह बनाता है कि प्रत्येक तत्व लाने वाला प्रत्येक तत्व लाने वाले की l.sortतुलना में अधिक तेज़ maxहोता है।

मुझे लगता है कि यदि आप इसके बजाय उपयोग करते sorted(a)हैं तो आपको परिणाम की तुलना में धीमा मिलेगा max(a)


5
यह धारणा अधिक ठोस बनने के लिए केवल एक लाइनर-टाइमिंग है। आपके ज्ञान पर सवाल नहीं उठा रहा है, बस इस तरह का जोड़ उन लोगों के प्रदर्शन के लिए तुच्छ है जो इसे नहीं जानते हैं।
१५

आप सही है कि sorted(a)की तुलना में धीमी है max(a)। आश्चर्य की बात नहीं है कि यह उसी गति के बारे में है a.sort(), लेकिन आपके अनुमान के कारण के रूप में क्यों नहीं है - यह इसलिए है क्योंकि ओपी ने उनके परीक्षण में गलती की है क्योंकि स्वीकृत उत्तर में बताया गया है।
मार्टीन्यू

मुद्दा यह था कि log(n)जटिलता में कारक को ऑफसेट करने के लिए जेनेरिक पुनरावृत्त प्रोटोकॉल के पास पर्याप्त ओवरहेड है । यह एक O(n)एल्गोरिथ्म केवल O(nlogn)पर्याप्त रूप से बड़े के लिए एक एल्गोरिथ्म से तेज होने की गारंटी है n(उदाहरण के लिए क्योंकि प्रत्येक ऑपरेशन का समय एल्गोरिदम के बीच भिन्न हो सकता है - nlognतेज कदम nधीमे कदमों की तुलना में तेज हो सकता है )। वास्तव में, जहां इस मामले में भी ब्रेक पर विचार नहीं किया गया है (लेकिन किसी को पता होना चाहिए कि log nकारक छोटा होना बहुत बड़ा कारक नहीं है n)।
8:16 बजे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.