पायथन 3 * की तुलना में x**4.0
तेज़ क्यों है ?x**4
पायथन 3 int
ऑब्जेक्ट एक पूर्ण आकार की वस्तु हैं जो एक मनमाने आकार का समर्थन करने के लिए डिज़ाइन किया गया है; उस तथ्य के कारण, उन्हें सी स्तर पर इस तरह संभाला जाता है (देखें कि सभी चर कैसे PyLongObject *
टाइप किए जाते हैं long_pow
)। यह भी उनके घातांक को बहुत अधिक पेचीदा और थकाऊ बनाता है क्योंकि आपको ob_digit
इसे प्रदर्शन करने के लिए इसके मूल्य का प्रतिनिधित्व करने के लिए उपयोग किए जाने वाले सरणी के साथ खेलने की आवश्यकता होती है। ( बहादुर के लिए स्रोत। देखें: एस पर अधिक के लिए अजगर में बड़े पूर्णांकों के लिए स्मृति आवंटन को समझनाPyLongObject
।)
अजगर float
वस्तुओं, इसके विपरीत, एक सी प्रकार में परिवर्तित किया जा सकता है double
(उपयोग करके PyFloat_AsDouble
) और उन मूल प्रकारों का उपयोग करके संचालन किया जा सकता है । यह बहुत अच्छा है क्योंकि, प्रासंगिक किनारे के मामलों की जाँच करने के बाद, यह पायथन को प्लेटफ़ॉर्मpow
का उपयोग करने की अनुमति देता है ( सी है pow
, जो है ) वास्तविक घातांक को संभालने के लिए:
/* Now iv and iw are finite, iw is nonzero, and iv is
* positive and not equal to 1.0. We finally allow
* the platform pow to step in and do the rest.
*/
errno = 0;
PyFPE_START_PROTECT("pow", return NULL)
ix = pow(iv, iw);
जहाँ iv
और सी के रूप में iw
हमारे मूल हैं ।PyFloatObject
double
इसके लायक क्या है: 2.7.13
मेरे लिए अजगर 2~3
तेजी से एक कारक है , और उलटा व्यवहार दिखाता है।
पिछला तथ्य भी पायथन 2 और 3 के बीच विसंगति की व्याख्या करता है, इसलिए मैंने सोचा कि मैं इस टिप्पणी को भी संबोधित करूंगा क्योंकि यह दिलचस्प है।
पायथन 2 में, आप पुरानी int
वस्तु का उपयोग कर रहे हैं जो कि int
पायथन 3 में ऑब्जेक्ट से अलग है ( int
3.x में सभी ऑब्जेक्ट PyLongObject
प्रकार के हैं)। पायथन 2 में, एक अंतर है जो वस्तु के मूल्य पर निर्भर करता है (या, यदि आप प्रत्यय का उपयोग करते हैं L/l
):
# Python 2
type(30) # <type 'int'>
type(30L) # <type 'long'>
<type 'int'>
आप यहाँ देख एक ही बात करता है float
रों करना इसे सुरक्षित रूप से एक सी में परिवर्तित हो जाती, long
जब घातांक यह पर किया जाता है ( int_pow
, यह भी एक रजिस्टर में उन्हें डाल करने के लिए 'संकलक संकेत करता है, तो वह ऐसा कर सकते हैं ताकि सकता है कोई फर्क) :
static PyObject *
int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
{
register long iv, iw, iz=0, ix, temp, prev;
/* Snipped for brevity */
यह एक अच्छी गति हासिल करने की अनुमति देता है।
यह देखने के लिए कि <type 'long'>
एस की तुलना में सुस्त कैसे हैं <type 'int'>
, यदि आप पायथन 2 x
में एक long
कॉल में नाम लपेटते हैं (अनिवार्य long_pow
रूप से इसे पायथन 3 में उपयोग करने के लिए मजबूर करते हैं ), गति लाभ गायब हो जाता है:
# <type 'int'>
(python2) ➜ python -m timeit "for x in range(1000):" " x**2"
10000 loops, best of 3: 116 usec per loop
# <type 'long'>
(python2) ➜ python -m timeit "for x in range(1000):" " long(x)**2"
100 loops, best of 3: 2.12 msec per loop
ध्यान दें कि, हालांकि एक स्निपेट बदल जाता int
है, long
जबकि दूसरा नहीं (जैसा कि @pydsinger द्वारा बताया गया है), यह कास्ट मंदी के पीछे योगदान करने वाला बल नहीं है। का कार्यान्वयन long_pow
है। (समय केवल long(x)
देखने के लिए बयानों के साथ )।
[...] यह लूप के बाहर नहीं होता है। [...] इस बारे में कोई विचार?
यह आपके लिए स्थिरांक को तह करते हुए सीपीथॉन का पीपहोल आशावादी है। आप या तो मामले के समान सटीक समय प्राप्त करते हैं क्योंकि घातांक के परिणाम को खोजने के लिए कोई वास्तविक गणना नहीं है, केवल मूल्यों का लोडिंग:
dis.dis(compile('4 ** 4', '', 'exec'))
1 0 LOAD_CONST 2 (256)
3 POP_TOP
4 LOAD_CONST 1 (None)
7 RETURN_VALUE
समान बाइट के साथ समान बाइट के लिए आइडेंटिकल बाइट-कोड जेनरेट किया '4 ** 4.'
जाता है जो कि int के बजाय LOAD_CONST
फ्लोट को लोड करता है :256.0
256
dis.dis(compile('4 ** 4.', '', 'exec'))
1 0 LOAD_CONST 3 (256.0)
2 POP_TOP
4 LOAD_CONST 2 (None)
6 RETURN_VALUE
तो समय समान हैं।
* उपरोक्त सभी केवल अजगर के संदर्भ कार्यान्वयन, सीपीथॉन के लिए लागू होते हैं। अन्य कार्यान्वयन अलग तरीके से प्रदर्शन कर सकते हैं।