python - पाइथन 3 पाइथन 2 की तुलना में काफी धीमी क्यों है?



performance python-2.7 (1)

अंतर int प्रकार के कार्यान्वयन में है। पायथन 3.x मनमाने ढंग से आकार वाले पूर्णांक प्रकार (2.x में long ) का उपयोग करता है, जबकि पायथन 2.x में sys.maxint मानों के लिए एक सरल int प्रकार का उपयोग किया जाता है जो हुड के नीचे एक साधारण सी long उपयोग करता है।

एक बार जब आप अपने लूप को long पूर्णांक long सीमित कर देते हैं, तो पायथन 3.x तेज होता है:

>>> from timeit import timeit
>>> MAX_NUM = 3*10**3
>>> def bar():
...     i = MAX_NUM + sys.maxsize
...     while i > sys.maxsize:
...         i -= 1
... 

पायथन 2:

>>> timeit(bar, number=10000)
5.704327821731567

पायथन 3:

>>> timeit(bar, number=10000)
3.7299320790334605

मैंने sys.maxsize उपयोग किया क्योंकि sys.maxint को पायथन 3 से हटा दिया गया था, लेकिन पूर्णांक मान मूल रूप से वही है।

पाइथन 2 में गति अंतर इस प्रकार पहले (2 ** 63) - 64-बिट पर 1 पूर्णांक तक सीमित है, (2 ** 31) - 32 बिट सिस्टम पर 1 पूर्णांक।

चूंकि आप पाइथन 2 पर xrange() साथ long प्रकार का उपयोग नहीं कर सकते हैं, इसलिए मैंने उस फ़ंक्शन के लिए तुलना शामिल नहीं की थी।

इस प्रश्न का उत्तर यहां दिया गया है:

मैं समझने की कोशिश कर रहा हूं कि पाइथन 3 वास्तव में कुछ स्थितियों में पाइथन 2 की तुलना में अधिक समय क्यों ले रहा है, नीचे दिए गए कुछ मामले हैं जिन्हें मैंने पाइथन 3.4 से पायथन 2.7 तक सत्यापित किया है।

नोट: मैं कुछ प्रश्नों से गुजर चुका हूं जैसे Python3 में कोई xrange फ़ंक्शन क्यों नहीं है? और python3 में पाइपोन 2 की तुलना में बहुत धीमी है और Python2 की तुलना में Python3 में समान कोड धीमा है , लेकिन मुझे लगता है कि मुझे इस मुद्दे के पीछे वास्तविक कारण नहीं मिला है।

मैंने कोड के इस टुकड़े को यह दिखाने के लिए कोशिश की है कि यह कैसे अंतर कर रहा है:

MAX_NUM = 3*10**7

# This is to make compatible with py3.4.
try:
    xrange
except:
    xrange = range


def foo():
    i = MAX_NUM
    while i> 0:
        i -= 1

def foo_for():
    for i in xrange(MAX_NUM):
        pass

जब मैंने इस प्रोग्राम को py3.4 और py2.7 के साथ चलाने का प्रयास किया है तो मुझे परिणाम नीचे मिल गए हैं।

नोट: ये आंकड़े 2.6Ghz गीगाहर्ट्ज प्रोसेसर के साथ 64 bit मशीन के माध्यम से आए और टाइम लूप में time.time() का उपयोग करके time.time() गणना की।

Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791

Output: Python 2.7
------------------
1.5131521225
0.475143909454

मैं वास्तव में नहीं सोचता कि 2.7 से 3.4 तक, या xrange परिवर्तन किए गए हैं, मुझे पता है कि range को xrange में xrange के रूप में कार्य करना शुरू कर दिया गया है लेकिन जैसा कि दस्तावेज कहता है

range() अब व्यवहार करता है जैसे xrange() व्यवहार करने के लिए प्रयोग किया जाता है, सिवाय इसके कि यह मनमाने ढंग से आकार के मूल्यों के साथ काम करता है। उत्तरार्द्ध अब मौजूद नहीं है।

इसका मतलब है कि xrange से range में परिवर्तन नाम परिवर्तन के बराबर है लेकिन मनमानी मानों के साथ काम करना है।

मैंने डिस्सेम्बल बाइट कोड भी सत्यापित किया है।

फ़ंक्शन foo() के लिए अलग-अलग बाइट कोड नीचे दिया गया है:

Python 3.4:
--------------- 

 13           0 LOAD_GLOBAL              0 (MAX_NUM)
              3 STORE_FAST               0 (i)

 14           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (i)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       34

 15          21 LOAD_FAST                0 (i)
             24 LOAD_CONST               2 (1)
             27 INPLACE_SUBTRACT
             28 STORE_FAST               0 (i)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

python 2.7
-------------

 13           0 LOAD_GLOBAL              0 (MAX_NUM)
              3 STORE_FAST               0 (i)

 14           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (i)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       34

 15          21 LOAD_FAST                0 (i)
             24 LOAD_CONST               2 (1)
             27 INPLACE_SUBTRACT    
             28 STORE_FAST               0 (i)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK           
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE        

और नीचे foo_for() फ़ंक्शन के लिए अलग-अलग बाइट कोड है:

Python: 3.4

 19           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_GLOBAL              1 (MAX_NUM)
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 GET_ITER
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

 20          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE


Python: 2.7
-------------

 19           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_GLOBAL              1 (MAX_NUM)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

 20          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK           
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE        

यदि हम बाइट कोड दोनों की तुलना करते हैं तो उन्होंने वही डिस्सेम्बल बाइट कोड बनाया है।

अब मैं सोच रहा हूं कि 2.7 से 3.4 में क्या परिवर्तन वास्तव में कोड के दिए गए टुकड़े में निष्पादन समय में इस विशाल परिवर्तन का कारण बन रहा है।






cpython