स्थानीय / वैश्विक वैरिएबल स्टोर के समय के अलावा, ओपकोड भविष्यवाणी कार्य को तेज करती है।
जैसा कि अन्य उत्तर बताते हैं, फ़ंक्शन STORE_FAST
लूप में ओपकोड का उपयोग करता है । यहाँ फ़ंक्शन के लूप के लिए बायटेकोड है:
>> 13 FOR_ITER 6 (to 22) # get next value from iterator
16 STORE_FAST 0 (x) # set local variable
19 JUMP_ABSOLUTE 13 # back to FOR_ITER
आम तौर पर जब एक कार्यक्रम चलाया जाता है, तो पायथन प्रत्येक ओपकोड को एक के बाद एक निष्पादित करता है, एक स्टैक का ट्रैक रखता है और प्रत्येक ओपकोड को निष्पादित करने के बाद स्टैक फ्रेम पर अन्य चेक को प्रीफॉर्म करता है। ओपोड भविष्यवाणी का मतलब है कि कुछ मामलों में पायथन सीधे अगले ओपोड में कूदने में सक्षम है, इस प्रकार इस ओवरहेड में से कुछ से बचा जा सकता है।
इस मामले में, हर बार पायथन देखता है FOR_ITER
(लूप के ऊपर), यह "भविष्यवाणी" करेगा जो कि STORE_FAST
अगले ओपोड को निष्पादित करना है। अजगर फिर अगले ओपकोड में झांकता है और अगर भविष्यवाणी सही थी, तो वह सीधे कूद जाता है STORE_FAST
। इसमें दो opcodes को एक opcode में निचोड़ने का प्रभाव होता है।
दूसरी ओर, STORE_NAME
वैश्विक स्तर पर लूप में ओपकोड का उपयोग किया जाता है। जब यह ओपकोड देखता है तो पायथन * * नहीं करता है । इसके बजाय, यह मूल्यांकन-लूप के शीर्ष पर वापस जाना चाहिए जिसमें लूप निष्पादित होने की गति के लिए स्पष्ट निहितार्थ हैं।
इस अनुकूलन के बारे में कुछ और तकनीकी जानकारी देने के लिए, यहाँ ceval.c
फ़ाइल का एक उद्धरण (पायथन की वर्चुअल मशीन का "इंजन") दिया गया है:
कुछ ऑपकोड जोड़े में आते हैं और इस प्रकार पहले कोड के चलते दूसरे कोड की भविष्यवाणी करना संभव हो जाता है। उदाहरण के लिए,
GET_ITER
अक्सर इसके बाद होता है FOR_ITER
। तथाFOR_ITER
अक्सरSTORE_FAST
या उसके बाद होता हैUNPACK_SEQUENCE
।
भविष्यवाणी को सत्यापित करना एक स्थिर के खिलाफ रजिस्टर चर के एक एकल उच्च गति परीक्षण की लागत। यदि युग्मन अच्छा था, तो प्रोसेसर की अपनी आंतरिक शाखा की भविष्यवाणी में सफलता की एक उच्च संभावना है, जिसके परिणामस्वरूप अगले ओपोड में लगभग शून्य-ओवरहेड संक्रमण होता है। एक सफल भविष्यवाणी अपनी दो अप्रत्याशित शाखाओं सहित eval-loop के माध्यम से एक यात्रा को बचाता है,HAS_ARG
परीक्षण और स्विच-केस । प्रोसेसर की आंतरिक शाखा की भविष्यवाणी के साथ संयुक्त, एक सफल के PREDICT
पास दो ऑपकोड चलाने का प्रभाव होता है जैसे कि वे संयुक्त निकायों के साथ एक एकल नया ओपकोड थे।
हम FOR_ITER
ओपकोड के लिए स्रोत कोड में देख सकते हैं, जहां के लिए भविष्यवाणी STORE_FAST
की गई है:
case FOR_ITER: // the FOR_ITER opcode case
v = TOP();
x = (*v->ob_type->tp_iternext)(v); // x is the next value from iterator
if (x != NULL) {
PUSH(x); // put x on top of the stack
PREDICT(STORE_FAST); // predict STORE_FAST will follow - success!
PREDICT(UNPACK_SEQUENCE); // this and everything below is skipped
continue;
}
// error-checking and more code for when the iterator ends normally
PREDICT
कार्य करने के लिए फैलता है if (*next_instr == op) goto PRED_##op
यानी हम सिर्फ भविष्यवाणी opcode के शुरू करने के लिए कूद। इस मामले में, हम यहां कूदते हैं:
PREDICTED_WITH_ARG(STORE_FAST);
case STORE_FAST:
v = POP(); // pop x back off the stack
SETLOCAL(oparg, v); // set it as the new local variable
goto fast_next_opcode;
स्थानीय चर अब सेट हो गया है और अगला ओपोड निष्पादन के लिए तैयार है। पायथन जब तक अंत तक नहीं पहुंचता, तब तक चलता रहता है, जब तक कि हर बार सफल भविष्यवाणी न हो जाए।
अजगर विकि पृष्ठ कैसे CPython के आभासी मशीन काम करता है के बारे में अधिक जानकारी नहीं है।