6 ^ 6 ^ 6 का मूल्यांकन करने में अजगर बनाम बीसी


29

मैं अभिव्यक्ति 6^6^6का उपयोग करके pythonऔर bcअलग से मूल्यांकन कर रहा हूं ।

अजगर फ़ाइल की सामग्री है print 6**6**6। जब मैं निष्पादित करता हूं time python test.py, तो मुझे आउटपुट मिलता है

real        0m0.067s
user        0m0.050s
sys         0m0.011s

और फिर, मैंने कमांड रन time echo 6^6^6 | bcकिया जिसने मुझे निम्नलिखित आउटपुट दिया

real        0m0.205s
user        0m0.197s
sys         0m0.005s

इन परिणामों से यह स्पष्ट है कि अजगर और ई.पू. द्वारा लिया गया sys का समय क्रमशः 11ms और 5ms था। ईसा पूर्व आदेश sys समय स्तर पर अजगर से बेहतर प्रदर्शन किया लेकिन जब यह करने के लिए आता उपयोगकर्ता और वास्तविक समय अजगर लगभग 4 बार ईसा पूर्व की तुलना में तेजी थी । वहां क्या गया होगा। मैंने इस तरह की प्रक्रियाओं को कोई प्राथमिकता नहीं दी है। मैं इस स्थिति को समझने की कोशिश कर रहा हूं।


तो क्या आपका मतलब यह है कि sys घटक केवल लोड होने में लगने वाला समय देता है और आउटपुट के उपयोगकर्ता घटक में रनटाइम दिया जाएगा?
गनेश

मुझे सच में यकीन नहीं है, इसीलिए मैंने एक टिप्पणी पोस्ट की है। यह सिर्फ एक अनुमान है।
terdon

7
echo | bcपाइप की वजह से एक सब-लॉन्च शुरू करना शामिल है - यही वह जगह है जहाँ आपके कुछ अतिरिक्त उपयोगकर्ता समय संभवतः से आए थे। इसे एक न्यायसंगत परीक्षण बनाने के लिए, अजगर स्क्रिप्ट को स्टडिन से पढ़ना चाहिए ताकि आप कर सकें time echo 6**6**6 | whatever.py
गोल्डीलॉक्स

1
मैं एक स्क्रिप्ट में कमांड लाइन रखना चाहता हूं और उस पर अमल करना चाहिए। या उपयोग करें echo 6^6^6 | time bc
डेनियल कुल्मन

1
साइड नोट: अजगर में 6**6**6अभिव्यक्ति वास्तव में संकलित समय पर गणना की जाती है । हालाँकि जब से आप किसी मॉड्यूल से इसे आयात करने के बजाय सीधे फ़ाइल लॉन्च कर रहे हैं, यह बात नहीं होनी चाहिए। अंतर 10**12345678को एक a.pyफ़ाइल में देखने के लिए और इंटरएक्टिव इंटरप्रेटर से इसे आयात करने का प्रयास करें। फिर दुभाषिया बंद करें, इसे पुनरारंभ करें और aफिर से आयात करें। पहली बार इसे ध्यान देने योग्य मात्रा में समय लेना चाहिए (क्योंकि अजगर मॉड्यूल का संकलन कर रहा है), जबकि दूसरी बार यह लोड करता है .pyc, जो तात्कालिक होना चाहिए,
बाकुरि

जवाबों:


25

अजगर स्टार्टअप पर बड़ी संख्या में फ़ाइलों का आयात करता है:

% python -c 'import sys; print len(sys.modules)'
39

इनमें से प्रत्येक को पायथन फ़ाइल खोलने के लिए और भी अधिक प्रयासों की आवश्यकता होती है, क्योंकि मॉड्यूल को परिभाषित करने के कई तरीके हैं:

% python -vv -c 'pass'
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# trying site.so
# trying sitemodule.so
# trying site.py
# trying site.pyc
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/sitemodule.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.py
# /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.pyc matches /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.py
import site # precompiled from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.pyc
# trying os.so
# trying osmodule.so
# trying os.py
# trying os.pyc
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/osmodule.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py
# /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc matches /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py
import os # precompiled from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc
    ...

प्रत्येक "कोशिश कर रहे", उन लोगों को छोड़कर जो बिलियन हैं, एक ओएस-स्तर / सिस्टम कॉल की आवश्यकता होती है, और प्रत्येक "आयात" संदेशों के बारे में 8 "ट्रिगर" लगता है। (Zipimport का उपयोग करके इसे कम करने के तरीके थे, और आपके PYTHONPATH में प्रत्येक पथ को किसी अन्य कॉल की आवश्यकता हो सकती है।)

इसका मतलब है कि मेरी मशीन पर पायथन शुरू होने से पहले लगभग 200 स्टेट सिस्टम कॉल हैं, और "समय" बताता है कि "उपयोगकर्ता" के बजाय "sys" है, क्योंकि उपयोगकर्ता प्रोग्राम सिस्टम पर चीजों को करने के लिए इंतजार कर रहा है।

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

डिस्क की प्रतीक्षा धीमी है।

आप पायथन की स्टार्टअप लागत के लिए भाव प्राप्त कर सकते हैं:

time python -c pass

यह मेरी मशीन पर 0.032s है, जबकि 'प्रिंट 6 ** 6 ** 6' 0.072s है, इसलिए स्टार्टअप की लागत समग्र समय का 1/2 वां है और गणना + दशमलव में रूपांतरण अन्य आधा है। जबकि:

time echo 1 | bc

0.005 s लेता है, और "6 ^ 6 ^ 6" में 0.184 का समय लगता है, इसलिए bc का घातांक अजगर की तुलना में 4x से अधिक धीमा होता है, भले ही यह आरंभ करने के लिए 7x तेज़ है।


4
आप थोड़े ने वहां नेतृत्व को दफन कर दिया। आप अंतिम बिट को शीर्ष पर ले जाना चाह सकते हैं।
रेकिंग

बस मेरे मशीन पर ब्याज से बाहर: समय अजगर -c 'पास' 0m0.025s, समय अजगर -c '6 प्रिंट 6 0m0.087s लेकिन समय अजगर -c' एक्स = 6 6 ' 6 6' 0m0.028s तो सबसे की समय बड़ी संख्या में आउटपुट कर रहा है।
स्टीव बार्न्स

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

11

मुझे अलग-अलग क्षेत्रों के बारे में बताते हुए SO पर एक अच्छा उत्तर मिला :

  • वास्तविक दीवार घड़ी का समय है - कॉल के शुरू से अंत तक का समय। यह सभी बीता हुआ समय है जिसमें अन्य प्रक्रियाओं द्वारा उपयोग किए जाने वाले समय के स्लाइस शामिल हैं और समय अवरुद्ध हो जाता है (उदाहरण के लिए अगर यह I / O के पूरा होने का इंतजार कर रहा है)।

  • उपयोगकर्ता प्रक्रिया के भीतर उपयोगकर्ता-मोड कोड (कर्नेल के बाहर) में खर्च होने वाले CPU समय की राशि है। यह केवल वास्तविक सीपीयू समय है जो प्रक्रिया को निष्पादित करने में उपयोग किया जाता है। अन्य प्रक्रियाएं और समय प्रक्रिया अवरुद्ध होती है, इस आंकड़े की ओर गिनती नहीं होती है।

  • Sys प्रक्रिया के भीतर कर्नेल में खर्च होने वाले CPU समय की मात्रा है। इसका अर्थ है कि लाइब्रेरी कॉल कोड के विपरीत, कर्नेल के भीतर सिस्टम कॉल में बिताए गए CPU समय को निष्पादित करना, जो अभी भी उपयोगकर्ता-अंतरिक्ष में चल रहा है। 'उपयोगकर्ता' की तरह, यह प्रक्रिया द्वारा उपयोग किया जाने वाला केवल CPU समय है। कर्नेल मोड (जिसे 'पर्यवेक्षक' मोड के रूप में भी जाना जाता है) और सिस्टम कॉल तंत्र के संक्षिप्त विवरण के लिए नीचे देखें।

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

इससे आपको कोई फर्क नहीं पड़ता है, केवल वही जानकारी realजिसकी आप वास्तव में परवाह करते हैं, जो कि कमांड लॉन्च करने और इसे आउटपुट प्राप्त करने के बीच का वास्तविक समय है।

आपको यह भी पता होना चाहिए कि ये छोटे अंतर स्थिर नहीं हैं, वे आपके सिस्टम के भार पर भी निर्भर करेंगे और आपके द्वारा आयोजित किए जाने पर हर बार बदलेंगे:

$ for i in {1..10}; do ( time python test.py > /dev/null ) 2>&1; done | grep user
user    0m0.056s
user    0m0.052s
user    0m0.052s
user    0m0.052s
user    0m0.060s
user    0m0.052s
user    0m0.052s
user    0m0.056s
user    0m0.048s
user    0m0.056s

$ for i in {1..10}; do ( time echo 6^6^6 | bc > /dev/null ) 2>&1; done | grep user
user    0m0.188s
user    0m0.188s
user    0m0.176s
user    0m0.176s
user    0m0.172s
user    0m0.176s
user    0m0.180s
user    0m0.172s
user    0m0.172s
user    0m0.172s

10

मैं इसे दूसरे दृष्टिकोण से समझाऊंगा।

उचित होने के लिए, bcइसका फायदा है क्योंकि इसे डिस्क से कुछ भी पढ़ने की ज़रूरत नहीं है और केवल इसकी बूँद / बायनेरिज़ की ज़रूरत है, जबकि अजगर को मॉड्यूल + की एक श्रृंखला को पढ़ने के लिए आयात करना पड़ता है। तो आपका परीक्षण पक्षपाती हो सकता है bc। वास्तव में इसका परीक्षण करने के लिए आपको इसका उपयोग करना चाहिए bc -q fileजिसमें fileशामिल हैं:

6^6^6
quit

सिर्फ बदलने का उपयोग करने के समय को संशोधित echo:

bc  0.33s user 0.00s system 80% cpu 0.414 total

फ़ाइल का उपयोग करने के लिए:

bc -q some  0.33s user 0.00s system 86% cpu 0.385 total

(आपको अधिक मतभेदों को नोटिस करने के लिए टेराडो की विधि का उपयोग करना होगा, लेकिन कम से कम हम जानते हैं कि वे हैं)

अब, अजगर के दृष्टिकोण से, अजगर को डिस्क से पढ़ने की जरूरत है, हर बार फ़ाइल को संकलित करना और निष्पादित करना, प्लस को लोड करना मॉड्यूल एंड्रयू अंक के रूप में , जो निष्पादन समय को धीमा कर देता है। यदि आप अजगर स्क्रिप्ट के बाइट कोड को संकलित करते हैं, तो आप देखेंगे कि कोड को निष्पादित करने में कुल 50% कम समय लगता है:

python some.py > /dev/null  0.25s user 0.01s system 63% cpu 0.413 total

संकलित:

./some.pyc  0.22s user 0.00s system 77% cpu 0.282 total

जैसा कि आप देख सकते हैं, कई कारक हैं जो विभिन्न उपकरणों के बीच समय निष्पादन को प्रभावित कर सकते हैं।


3

मुझे अन्य उत्तरों को पढ़ने का लाभ मिला है। के लिए मेरे जैसे शुरुआत के लोगों कारण पता होना चाहिए कि हम क्यों इतनी बड़ी पूर्णांक यहाँ के साथ हैं निपटने है कि दोनों है Pythonऔर bcकर सही-साहचर्य , घातांक विस्तार जिसका अर्थ है कि यह नहीं है 6^36कि हम मूल्यांकन कर रहे हैं बल्कि 6^46656जो काफी बड़ा है। 1

निम्न आदेशों पर विविधताओं का उपयोग करते हुए, हम timeआरक्षित शब्द और कमांड दोनों के आउटपुट के एक विशिष्ट तत्व के लिए औसत निकाल सकते हैं :

for i in {1..1000}; do (time echo 6^6^6 | bc > /dev/null) 2>&1; done | grep 'rea' | sed -e s/.*m// | awk '{sum += $1} END {print sum / NR}'

for i in {1..1000}; do (/usr/bin/time -v sh -c 'echo 6^6^6 | bc > /dev/null') 2>&1; done | grep 'Use' | sed -e s/.*:// | awk '{sum += $1} END {print sum / NR}'

किसी अन्य मार्ग पर जाना और फ़ाइल को पूरी तरह से तुलना से निकालना संभव है। इसके अलावा, हम dcकमांड जैसे कुछ के साथ bc की टाइमिंग की तुलना कर सकते हैं , क्योंकि ऐतिहासिक रूप से पूर्व बाद में "फ्रंट एंड प्रोसेसर" है। निम्नलिखित आदेश समयबद्ध थे:

echo 6^6^6 | bc
echo 6 6 6 ^ ^ p | dc
echo print 6**6**6 | python2.7

नोट dcकमांड, घातांक के लिए बाएं-सहयोगी है। 2

time1000 पुनरावृत्तियों (सेकंड में) के साथ हमारे कुछ परिणाम हैं :

0.229678 real bc
0.228348 user bc
0.000569 sys bc
0.23306  real dc
0.231786 user dc
0.000395 sys dc
0.07 real python
0.065907 user python
0.003141 sys python

bcऔर dcइस संदर्भ में तुलनीय प्रदर्शन की पेशकश करते हैं।

GNU कमांड से कम सटीक 3 परिणाम (पैमाने सटीक यहाँ मान्य नहीं है लेकिन परिणाम समान हैं):/usr/bin/timetime

0.2224 user bc
0 sys bc
0.23 Elapsed bc
0.22998 user dc
0 sys dc
0.23 Elapsed dc
0.06008 user python
0 sys python
0.07 Elapsed python

इसका एक फायदा /usr/bin/timeयह है कि यह -vविकल्प प्रदान करता है जो अधिक जानकारी देता है जो अंततः उपयोगी हो सकता है।

पायथन मॉड्यूल के साथ बात करने के लिए आंतरिक रूप से इसका मूल्यांकन करना भी संभव है timeit:

python2.7 -m timeit -n 1000 -r 1 'print 6**6**6' | grep 'loops'
1000 loops, best of 1: 55.4 msec per loop

जो हमने पहले देखा था, उससे थोड़ा तेज है। चलिए दुभाषिए की ही कोशिश करते हैं:

>>> import timeit
>>> import sys
>>> import os
>>> T = timeit.Timer("print 6**6**6")
>>> n = int(1000)
>>> f = open(os.devnull, 'w')
>>> sys.stdout = f
>>> t = t.timeit(n)
>>> sys.stdout = sys.__stdout__
>>> print t/n
0.0553743481636

मैंने देखा है यह सबसे तेज है।


यदि हम एक कम घातांक का मूल्यांकन करते हैं 6^6, तो समय कमांड आश्चर्यजनक परिणाम देता है - उसी forलूप कमांड का उपयोग करके जिसका उपयोग हमने अभी किया है:

0.001001 bc real
0.000304 user
0.000554 sys
0.014    python real i.e. 10x more than bc??
0.010432 user
0.002606 sys

तो एक छोटे पूर्णांक के साथ bcअचानक बहुत तेज है ?? सिस्टम रिबूट से दूसरे रन तक कोई फर्क नहीं पड़ता। एक ही समय में, अगर हम timeitअजगर के लिए उपयोग करते हैं, तो हमें मिलता है:

python2.7 -m timeit -n 100000 -r 1 'print 6**6' | grep loops  
100000 loops, best of 1: 0.468 usec per loop

यह माइक्रोसेकंड है , मिलीसेकंड नहीं, इसलिए यह forलूप का उपयोग करते हुए बहुत धीमे परिणामों के साथ मेल नहीं खाता है । हो सकता है कि अन्य उपकरणों को इसके आगे परीक्षण करने की आवश्यकता हो और जैसा कि अन्य लोगों ने समझाया है कि यहां आंख से मिलने से अधिक है। ऐसा लगता है कि पायथन सवाल के परिदृश्य में तेज था, लेकिन यह स्पष्ट नहीं है कि क्या निष्कर्ष उससे परे खींचा जा सकता है ...


1. यह कहने की आवश्यकता नहीं है कि यह किसी चीज के दायरे से परे है जैसे कि गूंज का अंकगणितीय विस्तार echo $((6**6**6))- यानी इसके साथ bashही सही-सही संबंध भी होता है 6^6^6 = 6^(6^6)

2. इसके साथ तुलना करें 6 6 ^ 6 ^ p:।

3. यह संभव है कि GNU टाइम कमांड BSD UNIX (GNU टाइम इंफो डॉक्यूमेंट) पर चलने पर अधिक जानकारी प्रदान करता है: 'टाइम' द्वारा दर्शाई गई अधिकांश जानकारी 'प्रतीक्षा 3' सिस्टम कॉल से ली गई है। संख्याएँ केवल उतनी ही अच्छी हैं जितनी 'प्रतीक्षा 3' द्वारा लौटी हैं। कई सिस्टम उन सभी संसाधनों को नहीं मापते हैं जिन पर 'समय' रिपोर्ट कर सकता है; उन संसाधनों को शून्य के रूप में सूचित किया जाता है। जो सिस्टम सबसे अधिक या सभी संसाधनों को मापते हैं, वे 4.2 या 4.3BSD पर आधारित होते हैं। बाद में बीएसडी रिलीज़ विभिन्न मेमोरी मैनेजमेंट कोड का उपयोग करता है जो कम संसाधनों को मापता है। - उन सिस्टमों पर जिनके पास 'प्रतीक्षा 3' कॉल नहीं है, जो स्थिति की जानकारी देता है, इसके बजाय 'बार' सिस्टम कॉल का उपयोग किया जाता है। यह 'प्रतीक्षा 3' की तुलना में बहुत कम जानकारी प्रदान करता है, इसलिए उन प्रणालियों के समय में अधिकांश संसाधनों को शून्य के रूप में रिपोर्ट करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.