স্থানীয় / গ্লোবাল ভেরিয়েবল স্টোরের সময় বাদে , অপকোড পূর্বাভাসটি ফাংশনটিকে আরও দ্রুত করে তোলে।
অন্যান্য উত্তরগুলি ব্যাখ্যা করার সাথে সাথে ফাংশনটি 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
। এটি দুটি ওপকোডকে একটি একক অপকোডে চেপে ধরার প্রভাব ফেলে।
অন্যদিকে, STORE_NAME
অপকোডটি বৈশ্বিক স্তরে লুপে ব্যবহৃত হয়। পাইথন যখন এই অপকোডটি দেখেন তখন অনুরূপ পূর্বাভাস দেয় না * । পরিবর্তে, এটি অবশ্যই মূল্যায়ন-লুপের শীর্ষে ফিরে যেতে হবে যার লুপটি যে গতিতে সঞ্চালিত হয় তার স্পষ্ট প্রভাব রয়েছে।
এই অপ্টিমাইজেশান সম্পর্কে আরও কিছু প্রযুক্তিগত বিবরণ দেওয়ার জন্য, ceval.c
ফাইলটি থেকে একটি উদ্ধৃতি (পাইথনের ভার্চুয়াল মেশিনের "ইঞ্জিন"):
কিছু ওপকোড জোড়ায় আসার প্রবণতা থাকে যাতে প্রথমটি চালিত হওয়ার পরে দ্বিতীয় কোডটির পূর্বাভাস দেওয়া সম্ভব হয়। উদাহরণস্বরূপ,
GET_ITER
প্রায়শই অনুসরণ করা হয় FOR_ITER
। এবং FOR_ITER
প্রায়শই অনুসরণ করা হয়STORE_FAST
বা UNPACK_SEQUENCE
।
পূর্বাভাস যাচাই করার জন্য ধ্রুবকের বিরুদ্ধে রেজিস্টার ভেরিয়েবলের একক উচ্চ-গতির পরীক্ষার প্রয়োজন হয়। যদি জুড়িটি ভাল ছিল, তবে প্রসেসরের নিজস্ব অভ্যন্তরীণ শাখার পূর্বাভাস সাফল্যের উচ্চ সম্ভাবনা রয়েছে, যার ফলে পরবর্তী অপকোডে প্রায় শূন্য-ওভারহেড রূপান্তর ঘটে। একটি সফল পূর্বাভাস তার দুটি অপ্রত্যাশিত শাখা, 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 এর ভার্চুয়াল মেশিন কাজ করে সে সম্পর্কে আরও তথ্য রয়েছে।