अनुकूलन संकलक

From alpha
Jump to navigation Jump to search

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

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

इन कारकों के कारण, अनुकूलन शायद ही कभी किसी भी अर्थ में इष्टतम उत्पादन उत्पन्न करता है, और वास्तव में, अनुकूलन कुछ मामलों में प्रदर्शन को बाधित कर सकता है। बल्कि, वे विशिष्ट कार्यक्रमों में संसाधन उपयोग में सुधार के लिए अनुमानी तरीके हैं।[1]


अनुकूलन के प्रकार

ऑप्टिमाइज़ेशन में उपयोग की जाने वाली तकनीकों को विभिन्न स्कोपों ​​​​में विभाजित किया जा सकता है जो किसी एक कथन से लेकर पूरे कार्यक्रम तक किसी भी चीज़ को प्रभावित कर सकते हैं। सामान्यतया, स्थानीय स्तर पर लागू की जाने वाली तकनीकों को वैश्विक तकनीकों की तुलना में लागू करना आसान होता है, लेकिन इसके परिणामस्वरूप छोटे लाभ होते हैं। कार्यक्षेत्रों के कुछ उदाहरणों में शामिल हैं:

पीपहोल अनुकूलन: ये आमतौर पर मशीन कोड उत्पन्न होने के बाद संकलन प्रक्रिया में देर से किए जाते हैं। अनुकूलन का यह रूप कुछ आसन्न निर्देशों (जैसे कोड पर एक छिद्र के माध्यम से देखना) की जांच करता है ताकि यह देखा जा सके कि उन्हें एक निर्देश या निर्देशों के छोटे अनुक्रम से बदला जा सकता है या नहीं।[2] उदाहरण के लिए, किसी मान को 2 से गुणा करना बिट शिफ्ट द्वारा अधिक कुशलता से निष्पादित किया जा सकता है। मान को लेफ्ट-शिफ्टिंग या स्वयं में मान जोड़कर (यह उदाहरण भी शक्ति में कमी का एक उदाहरण है)।

लोकल ऑप्टिमाइज़ेशन
ये केवल सूचनाओं को एक बुनियादी ब्लॉक के लिए स्थानीय मानते हैं।[3] चूंकि बुनियादी ब्लॉकों का कोई नियंत्रण प्रवाह नहीं है, इसलिए इन अनुकूलनों को बहुत कम विश्लेषण, समय की बचत और भंडारण आवश्यकताओं को कम करने की आवश्यकता होती है, लेकिन इसका मतलब यह भी है कि छलांग भर में कोई जानकारी संरक्षित नहीं की जाती है।

वैश्विक अनुकूलन: इन्हें इंट्राप्रोसेडुरल तरीके भी कहा जाता है और पूरे कार्यों पर कार्य करता है।[3]इससे उन्हें काम करने के लिए अधिक जानकारी मिलती है, लेकिन अक्सर महंगी संगणनाएं आवश्यक हो जाती हैं। फ़ंक्शन कॉल होने पर सबसे खराब स्थिति की धारणा बनानी पड़ती है या वैश्विक चर का उपयोग किया जाता है क्योंकि उनके बारे में बहुत कम जानकारी उपलब्ध है। लूप अनुकूलन: ये उन कथनों पर कार्य करते हैं जो एक लूप बनाते हैं, जैसे कि लूप के लिए, उदाहरण के लिए लूप-इनवेरिएंट कोड मोशन। लूप ऑप्टिमाइज़ेशन का एक महत्वपूर्ण प्रभाव हो सकता है क्योंकि कई प्रोग्राम अपने समय का एक बड़ा प्रतिशत लूप के अंदर बिताते हैं।[4]

प्रेजेंटर स्टोर ऑप्टिमाइज़ेशन
ये स्टोर ऑपरेशंस को थ्रेड्स (कंप्यूटर साइंस) और लॉक्स के संदर्भ में अन्यथा अनुमति देने की तुलना में पहले होने की अनुमति देते हैं। प्रक्रिया को समय से पहले जानने के कुछ तरीके की आवश्यकता होती है कि असाइनमेंट द्वारा कौन सा मूल्य संग्रहीत किया जाएगा जिसका पालन किया जाना चाहिए। इस छूट का उद्देश्य संकलक अनुकूलन को कुछ प्रकार के कोड पुनर्व्यवस्था करने की अनुमति देना है जो ठीक से सिंक्रनाइज़ किए गए कार्यक्रमों के शब्दार्थ को संरक्षित करता है।[5]

इंटरप्रोसेडुरल, पूरे प्रोग्राम या लिंक-समय अनुकूलन: ये प्रोग्राम के सभी स्रोत कोड का विश्लेषण करते हैं। अधिक मात्रा में जानकारी निकालने का मतलब है कि अनुकूलन तब अधिक प्रभावी हो सकता है जब उनके पास केवल स्थानीय जानकारी तक पहुंच हो, अर्थात एक ही कार्य के भीतर। इस प्रकार का अनुकूलन नई तकनीकों को भी प्रदर्शित करने की अनुमति दे सकता है। उदाहरण के लिए, फ़ंक्शन इनलाइन विस्तार, जहां फ़ंक्शन कॉल को फ़ंक्शन बॉडी की एक प्रति द्वारा प्रतिस्थापित किया जाता है। मशीन कोड ऑप्टिमाइज़ेशन और वस्तु कोड अनुकूलक: ये सभी निष्पादन योग्य मशीन कोड लिंकर (कंप्यूटिंग) होने के बाद प्रोग्राम की निष्पादन योग्य कार्य छवि का विश्लेषण करते हैं। कुछ ऐसी तकनीकें जिन्हें अधिक सीमित दायरे में लागू किया जा सकता है, जैसे कि मैक्रो कम्प्रेशन जो निर्देशों के सामान्य अनुक्रमों को ढहाकर स्थान बचाता है, जब संपूर्ण निष्पादन योग्य कार्य छवि विश्लेषण के लिए उपलब्ध होती है तो अधिक प्रभावी होती हैं।[6] स्कोप्ड ऑप्टिमाइज़ेशन के अलावा, ऑप्टिमाइज़ेशन की दो और सामान्य श्रेणियां हैं:

प्रोग्रामिंग भाषा-इंडिपेंडेंट बनाम लैंग्वेज-डिपेंडेंट
अधिकांश उच्च-स्तरीय भाषाएं सामान्य प्रोग्रामिंग निर्माण और सार साझा करती हैं: निर्णय (यदि, स्विच, केस), लूपिंग (के लिए, जबकि, दोहराएं.. जब तक, करें.. जबकि), और एनकैप्सुलेशन (संरचनाएं, वस्तुएं)। इस प्रकार समान अनुकूलन तकनीकों का उपयोग भाषाओं में किया जा सकता है। हालाँकि, कुछ भाषा सुविधाएँ कुछ प्रकार के अनुकूलन को कठिन बनाती हैं। उदाहरण के लिए, C (प्रोग्रामिंग लैंग्वेज) और C++ में पॉइंटर्स की मौजूदगी से एरे एक्सेस को ऑप्टिमाइज़ करना मुश्किल हो जाता है (उपनाम विश्लेषण देखें)। हालांकि, पीएल/आई (जो पॉइंटर्स का भी समर्थन करता है) जैसी भाषाएं फिर भी कई अन्य तरीकों से बेहतर प्रदर्शन प्राप्त करने के लिए परिष्कृत अनुकूलन कंपाइलर उपलब्ध हैं। इसके विपरीत, कुछ भाषा सुविधाएँ कुछ अनुकूलन को आसान बनाती हैं। उदाहरण के लिए, कुछ भाषाओं में कार्यों के दुष्प्रभाव (कंप्यूटर विज्ञान) की अनुमति नहीं है। इसलिए, यदि कोई प्रोग्राम एक ही फ़ंक्शन पर एक ही तर्क के साथ कई कॉल करता है, तो संकलक तुरंत अनुमान लगा सकता है कि फ़ंक्शन के परिणाम की गणना केवल एक बार की जानी चाहिए। जिन भाषाओं में कार्यों को साइड इफेक्ट की अनुमति है, वहां एक और रणनीति संभव है। ऑप्टिमाइज़र यह निर्धारित कर सकता है कि किस फ़ंक्शन का कोई साइड इफेक्ट नहीं है और इस तरह के अनुकूलन को साइड इफेक्ट फ्री फ़ंक्शंस तक सीमित करता है। यह ऑप्टिमाइज़ेशन तभी संभव है जब ऑप्टिमाइज़र के पास कॉल किए गए फ़ंक्शन तक पहुंच हो।

मशीन-स्वतंत्र बनाम मशीन-निर्भर: अमूर्त प्रोग्रामिंग अवधारणाओं (लूप, ऑब्जेक्ट्स, स्ट्रक्चर्स) पर काम करने वाले कई अनुकूलन कंपाइलर द्वारा लक्षित मशीन से स्वतंत्र हैं, लेकिन सबसे प्रभावी अनुकूलन में से कई ऐसे हैं जो विशेष सुविधाओं का सबसे अच्छा फायदा उठाते हैं लक्ष्य मंच। उदाहरण ऐसे निर्देश हैं जो एक साथ कई काम करते हैं, जैसे कि डिक्रीमेंट रजिस्टर और यदि शून्य नहीं तो शाखा।

निम्नलिखित स्थानीय मशीन निर्भर अनुकूलन का एक उदाहरण है। एक प्रोसेसर रजिस्टर को 0 पर सेट करने के लिए, एक निर्देश में निरंतर '0' का उपयोग करने का स्पष्ट तरीका है जो एक रजिस्टर मान को एक स्थिरांक पर सेट करता है। एक कम स्पष्ट तरीका XOR को अपने साथ रजिस्टर करना है। यह संकलक पर निर्भर है कि वह किस निर्देश संस्करण का उपयोग करे। कई जोखिम मशीनों पर, दोनों निर्देश समान रूप से उपयुक्त होंगे, क्योंकि वे दोनों एक ही लंबाई के होंगे और एक ही समय लेंगे। इंटेल x86 परिवार जैसे कई अन्य माइक्रोप्रोसेसरों पर, यह पता चला है कि एक्सओआर संस्करण छोटा और शायद तेज़ है, क्योंकि तत्काल ऑपरेंड को डीकोड करने की आवश्यकता नहीं होगी, न ही आंतरिक तत्काल ऑपरेंड रजिस्टर का उपयोग करें। इसके साथ एक संभावित समस्या यह है कि एक्सओआर रजिस्टर के पिछले मूल्य पर डेटा निर्भरता पेश कर सकता है, जिससे निर्देश पाइपलाइन स्टाल हो सकता है। हालांकि, प्रोसेसर के पास अक्सर एक विशेष मामले के रूप में एक रजिस्टर का एक्सओआर होता है जो स्टालों का कारण नहीं बनता है।

अनुकूलन को प्रभावित करने वाले कारक

मशीन ही: कई विकल्प जिनके बारे में अनुकूलन किया जा सकता है और किया जाना चाहिए, लक्ष्य मशीन की विशेषताओं पर निर्भर करते हैं। कभी-कभी इन मशीन आश्रित कारकों में से कुछ को पैरामीटर करना संभव होता है, ताकि मशीन विवरण पैरामीटर को बदलकर विभिन्न मशीनों को अनुकूलित करने के लिए कंपाइलर कोड का एक टुकड़ा इस्तेमाल किया जा सके। जीएनयू परियोजना से जीएनयू कंपाइलर संग्रह और एलएलवीएम से बजना इस दृष्टिकोण का पालन करने वाले कंपाइलरों को अनुकूलित करने के उदाहरण हैं।

लक्ष्य सीपीयू की वास्तुकला
सेंट्रल प्रोसेसिंग यूनिट प्रोसेसर रजिस्टर की संख्या: एक निश्चित सीमा तक, जितने अधिक रजिस्टर होते हैं, प्रदर्शन के लिए अनुकूलन करना उतना ही आसान होता है। स्थानीय चर को रजिस्टरों में आवंटित किया जा सकता है न कि कॉल स्टैक पर। अस्थाई/मध्यवर्ती परिणामों को बिना लिखे और स्मृति से वापस पढ़े बिना रजिस्टरों में छोड़ा जा सकता है।
  • RISC बनाम जटिल निर्देश सेट कंप्यूटर: CISC इंस्ट्रक्शन सेट में अक्सर वेरिएबल इंस्ट्रक्शन लेंथ होते हैं, अक्सर बड़ी संख्या में संभावित इंस्ट्रक्शन होते हैं जिनका इस्तेमाल किया जा सकता है, और हर इंस्ट्रक्शन में अलग-अलग समय लग सकता है। आरआईएससी निर्देश सेट इनमें से प्रत्येक में परिवर्तनशीलता को सीमित करने का प्रयास करता है: निर्देश सेट आमतौर पर स्थिर लंबाई के होते हैं, कुछ अपवादों के साथ, आमतौर पर रजिस्टरों और मेमोरी ऑपरेशंस के कम संयोजन होते हैं, और निर्देश जारी करने की दर (समय अवधि के अनुसार पूर्ण किए गए निर्देशों की संख्या, आमतौर पर घड़ी चक्र का एक पूर्णांक बहु) आमतौर पर उन मामलों में स्थिर होता है जहां मेमोरी लेटेंसी एक कारक नहीं है। एक निश्चित कार्य को पूरा करने के कई तरीके हो सकते हैं, CISC आमतौर पर RISC की तुलना में अधिक विकल्प प्रदान करता है। कंपाइलर्स को विभिन्न निर्देशों के बीच सापेक्ष लागतों को जानना होगा और सर्वोत्तम निर्देश अनुक्रम चुनना होगा (निर्देश चयन देखें)।
  • निर्देश पाइपलाइन: एक पाइपलाइन अनिवार्य रूप से एक सीपीयू है जो समनुक्रम में टूट जाती है। यह विभिन्न चरणों में निर्देशों के निष्पादन को तोड़कर विभिन्न निर्देशों के लिए सीपीयू कैश कुछ हिस्सों का उपयोग करने की अनुमति देता है: निर्देश डिकोड, पता डिकोड, मेमोरी फ़ेच, रजिस्टर फ़ेच, कंप्यूट, रजिस्टर स्टोर, आदि। एक निर्देश रजिस्टर स्टोर चरण में हो सकता है। , जबकि दूसरा रजिस्टर फ़ेच चरण में हो सकता है। पाइपलाइन संघर्ष तब होता है जब पाइपलाइन के एक चरण में एक निर्देश पाइपलाइन में उससे पहले के दूसरे निर्देश के परिणाम पर निर्भर करता है लेकिन अभी तक पूरा नहीं हुआ है। पाइपलाइन संघर्षों से पाइपलाइन स्टॉल हो सकती है: जहां CPU चक्रों को हल करने के लिए संघर्ष की प्रतीक्षा कर रहा है।
कंपाइलर शेड्यूल कर सकते हैं, या निर्देशों को पुन: व्यवस्थित कर सकते हैं ताकि पाइपलाइन स्टाल कम बार-बार हों।
  • सुपरस्कालर: कुछ सीपीयू में कई अंकगणितीय तर्क इकाई और फ्लोटिंग-पॉइंट यूनिट होती है। यह उन्हें एक साथ कई निर्देशों को निष्पादित करने की अनुमति देता है। इस पर प्रतिबंध हो सकता है कि कौन से निर्देश किन अन्य निर्देशों के साथ जोड़े जा सकते हैं (युग्मन दो या दो से अधिक निर्देशों का एक साथ निष्पादन है), और कौन सी कार्यात्मक इकाई किस निर्देश को निष्पादित कर सकती है। उनके पास पाइपलाइन संघर्षों के समान मुद्दे भी हैं।
यहां फिर से, निर्देशों को शेड्यूल किया जाना है ताकि विभिन्न कार्यात्मक इकाइयों को निष्पादित करने के निर्देशों के साथ पूरी तरह से खिलाया जा सके।

मशीन की वास्तुकला:

  • CPU कैश आकार (256 kiB-12 MiB) और प्रकार (डायरेक्ट मैप किया गया, 2-/4-/8-/16-वे सहयोगी, पूरी तरह से सहयोगी): इनलाइन विस्तार और लूप अनोलिंग जैसी तकनीकें जनरेट किए गए आकार को बढ़ा सकती हैं कोड और कोड इलाके को कम करें। यदि कोड का अत्यधिक उपयोग किया जाने वाला खंड (जैसे विभिन्न एल्गोरिदम में आंतरिक लूप) अचानक कैश में फिट नहीं हो पाता है, तो प्रोग्राम काफी धीमा हो सकता है। इसके अलावा, ऐसे कैश जो पूरी तरह से सहयोगी नहीं हैं, उनके कैशे के टकराव की संभावना अधिक होती है, यहां तक ​​कि एक खाली कैश में भी।
  • कैश / मेमोरी ट्रांसफर रेट: ये कंपाइलर को कैश मिस के लिए पेनल्टी का संकेत देते हैं। यह मुख्य रूप से विशेष अनुप्रयोगों में उपयोग किया जाता है।

उत्पन्न कोड का इरादा उपयोग:

डिबगिंग: एक एप्लिकेशन लिखते समय, एक प्रोग्रामर फिर से कॉम्पी करेगाle और परीक्षण अक्सर, और इसलिए संकलन तेज होना चाहिए। यह एक कारण है कि परीक्षण/डीबगिंग चरण के दौरान अधिकांश अनुकूलन जानबूझकर टाले जाते हैं। इसके अलावा, प्रोग्राम कोड आमतौर पर एक प्रतीकात्मक डिबगर का उपयोग करके (कार्यक्रम एनिमेशन देखें) के माध्यम से कदम रखा जाता है, और परिवर्तनों को अनुकूलित करना, विशेष रूप से वे जो कोड को पुन: व्यवस्थित करते हैं, मूल स्रोत कोड में लाइन नंबरों के साथ आउटपुट कोड को जोड़ना मुश्किल बना सकते हैं। यह डिबगिंग टूल और उनका उपयोग करने वाले प्रोग्रामर दोनों को भ्रमित कर सकता है।
सामान्य उद्देश्य का उपयोग
प्रीपैकेज्ड सॉफ़्टवेयर को अक्सर विभिन्न मशीनों और सीपीयू पर निष्पादित होने की उम्मीद होती है जो एक ही निर्देश सेट साझा कर सकते हैं, लेकिन अलग-अलग समय, कैश या मेमोरी विशेषताएँ होती हैं। नतीजतन, कोड किसी विशेष सीपीयू के लिए ट्यून नहीं किया जा सकता है, या सबसे लोकप्रिय सीपीयू पर सबसे अच्छा काम करने के लिए ट्यून किया जा सकता है और फिर भी अन्य सीपीयू पर स्वीकार्य रूप से अच्छी तरह से काम करता है।
विशेष-उद्देश्य उपयोग
यदि सॉफ़्टवेयर को एक या कुछ समान मशीनों पर ज्ञात विशेषताओं के साथ उपयोग करने के लिए संकलित किया गया है, तो संकलक उन विशिष्ट मशीनों के लिए उत्पन्न कोड को भारी रूप से ट्यून कर सकता है, बशर्ते ऐसे विकल्प उपलब्ध हों। महत्वपूर्ण विशेष मामलों में समांतर कंप्यूटिंग और वेक्टर प्रोसेसर के लिए डिज़ाइन किया गया कोड शामिल है, जिसके लिए विशेष समांतर संकलक कार्यरत हैं।
अंतः स्थापित प्रणाली
ये विशेष प्रयोजन के उपयोग का एक सामान्य मामला है। एंबेडेड सॉफ़्टवेयर को एक सटीक सीपीयू और मेमोरी आकार में कसकर ट्यून किया जा सकता है। साथ ही, सिस्टम की लागत या विश्वसनीयता कोड की गति से अधिक महत्वपूर्ण हो सकती है। उदाहरण के लिए, एम्बेडेड सॉफ़्टवेयर के लिए कंपाइलर आमतौर पर ऐसे विकल्प प्रदान करते हैं जो गति की कीमत पर कोड आकार को कम करते हैं, क्योंकि मेमोरी एक एम्बेडेड कंप्यूटर की मुख्य लागत है। कोड के समय को जितनी जल्दी हो सके अनुमानित करने की आवश्यकता हो सकती है, इसलिए कोड कैशिंग को अक्षम किया जा सकता है, इसके लिए आवश्यक कंपाइलर अनुकूलन के साथ।

सामान्य विषय

काफी हद तक, कंपाइलर ऑप्टिमाइज़ेशन तकनीकों में निम्नलिखित विषय हैं, जो कभी-कभी संघर्ष करते हैं।

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

रनटाइम मेट्रिक्स मदद कर सकते हैं
टेस्ट रन के दौरान एकत्रित की गई जानकारी का उपयोग प्रोफ़ाइल-निर्देशित अनुकूलन में किया जा सकता है। रनटाइम पर एकत्र की गई जानकारी, आदर्श रूप से न्यूनतम कम्प्यूटेशनल ओवरहेड के साथ, गतिशील रूप से अनुकूलन में सुधार करने के लिए समय-समय पर संकलन कंपाइलर द्वारा उपयोग की जा सकती है।

शक्ति में कमी: जटिल या कठिन या महंगे संचालन को सरल लोगों से बदलें। उदाहरण के लिए, विभाजन को इसके पारस्परिक द्वारा गुणा के साथ एक स्थिर द्वारा प्रतिस्थापित करना, या जोड़ के साथ एक लूप इंडेक्स द्वारा गुणा को बदलने के लिए प्रेरण चर विश्लेषण का उपयोग करना।

विशिष्ट तकनीक

लूप अनुकूलन

मुख्य रूप से लूप पर काम करने के लिए डिज़ाइन की गई कुछ अनुकूलन तकनीकों में शामिल हैं:

प्रेरण चर विश्लेषण: मोटे तौर पर, यदि लूप में एक चर सूचकांक चर का एक सरल रैखिक कार्य है, जैसे कि j := 4*i + 1, हर बार लूप वेरिएबल बदलने पर इसे उचित रूप से अपडेट किया जा सकता है। यह एक ताकत में कमी है, और इंडेक्स वेरिएबल की परिभाषाओं को मृत कोड बनने की अनुमति भी दे सकता है।[7] यह जानकारी अन्य बातों के साथ-साथ बाउंड-चेकिंग उन्मूलन और निर्भरता विश्लेषण के लिए भी उपयोगी है।

लूप विखंडन या लूप वितरण: लूप विखंडन एक लूप को एक ही इंडेक्स रेंज पर कई लूपों में तोड़ने का प्रयास करता है लेकिन प्रत्येक लूप के शरीर का केवल एक हिस्सा लेता है। यह संदर्भ की स्थानीयता में सुधार कर सकता है, दोनों डेटा को लूप में एक्सेस किया जा रहा है और लूप के शरीर में कोड।

लूप फ्यूजन या लूप कॉम्बिनेशन या लूप रैमिंग या लूप जैमिंग: एक अन्य तकनीक जो लूप ओवरहेड को कम करने का प्रयास करती है। जब दो सन्निकट लूप समान संख्या में पुनरावृति करेंगे चाहे वह संख्या संकलन समय पर ज्ञात हो, उनके शरीर को तब तक जोड़ा जा सकता है जब तक कि वे एक दूसरे के डेटा का कोई संदर्भ न दें।

लूप व्युत्क्रमण
यह तकनीक एक मानक जबकि लूप को एक if कंडीशनल में लपेटे गए डू/वाइल (रिपीट/जब तक के रूप में भी जाना जाता है) लूप में बदल देती है, लूप निष्पादित होने के मामलों के लिए जंप की संख्या को दो से कम कर देती है। ऐसा करने से कंडीशन चेक (कोड का आकार बढ़ाना) डुप्लिकेट हो जाता है, लेकिन यह अधिक कुशल है क्योंकि जंप आमतौर पर पाइपलाइन स्टाल का कारण बनता है। इसके अतिरिक्त, यदि प्रारंभिक स्थिति को संकलन-समय पर जाना जाता है और साइड इफेक्ट (कंप्यूटर विज्ञान) के रूप में जाना जाता है। साइड-इफेक्ट-फ्री, if गार्ड को छोड़ दिया जा सकता है।

लूप इंटरचेंज: ये अनुकूलन बाहरी लूप के साथ आंतरिक लूप का आदान-प्रदान करते हैं। जब लूप वेरिएबल इंडेक्स को एक एरे में बदल देता है, तो इस तरह के ट्रांसफॉर्मेशन से एरे के लेआउट के आधार पर संदर्भ की स्थानीयता में सुधार हो सकता है।

लूप-इनवेरिएंट कोड गति
यदि प्रत्येक पुनरावृत्ति के दौरान एक लूप के अंदर एक मात्रा की गणना की जाती है, और इसका मान प्रत्येक पुनरावृत्ति के लिए समान होता है, तो यह लूप के बाहर फहराने के लिए दक्षता में काफी सुधार कर सकता है और लूप शुरू होने से ठीक पहले एक बार इसके मूल्य की गणना कर सकता है। .[4]यह विशेष रूप से सरणियों पर लूप द्वारा उत्पन्न पता-गणना अभिव्यक्तियों के साथ महत्वपूर्ण है। सही कार्यान्वयन के लिए, इस तकनीक का उपयोग लूप इनवर्जन के साथ किया जाना चाहिए, क्योंकि लूप के बाहर फहराए जाने के लिए सभी कोड सुरक्षित नहीं हैं।
लूप नेस्ट ऑप्टिमाइज़ेशन
कुछ व्यापक एल्गोरिदम जैसे मैट्रिक्स गुणन में बहुत खराब कैश व्यवहार और अत्यधिक मेमोरी एक्सेस होती है। लूप नेस्ट ऑप्टिमाइज़ेशन छोटे ब्लॉकों पर ऑपरेशन करके और लूप इंटरचेंज का उपयोग करके कैश हिट्स की संख्या बढ़ाता है।
पाश उलटा
लूप रिवर्सल उस क्रम को उलट देता है जिसमें मान इंडेक्स वेरिएबल को असाइन किए जाते हैं। यह एक सूक्ष्म अनुकूलन है जो निर्भरता विश्लेषण को खत्म करने में मदद कर सकता है और इस प्रकार अन्य अनुकूलन को सक्षम कर सकता है। इसके अलावा, कुछ आर्किटेक्चर पर, लूप रिवर्सल छोटे कोड में योगदान देता है, जैसे कि लूप इंडेक्स को कम किया जा रहा है, लूप से बाहर निकलने के लिए चल रहे प्रोग्राम के लिए जिस शर्त को पूरा करने की आवश्यकता है वह शून्य के साथ तुलना है। यह अक्सर एक विशेष, पैरामीटर-रहित निर्देश होता है, एक संख्या के साथ तुलना के विपरीत, जिसकी तुलना करने के लिए संख्या की आवश्यकता होती है। इसलिए, पैरामीटर को स्टोर करने के लिए आवश्यक बाइट्स की मात्रा को लूप रिवर्सल का उपयोग करके सहेजा जाता है। इसके अतिरिक्त, यदि तुलना संख्या प्लेटफ़ॉर्म के शब्द के आकार से अधिक है, तो मानक लूप क्रम में, तुलना का मूल्यांकन करने के लिए कई निर्देशों को निष्पादित करने की आवश्यकता होगी, जो कि लूप रिवर्सल के मामले में नहीं है।

लूप अनोलिंग: लूप की स्थिति का परीक्षण करने की संख्या और जंप की संख्या को कम करने के लिए अनलोलिंग लूप के शरीर को कई बार डुप्लिकेट करता है, जो निर्देश पाइपलाइन को ख़राब करके प्रदर्शन को नुकसान पहुंचाता है। एक कम छलांग अनुकूलन। एक लूप को पूरी तरह से अनियंत्रित करने से सभी ओवरहेड समाप्त हो जाते हैं, लेकिन यह आवश्यक है कि संकलन समय पर पुनरावृत्तियों की संख्या ज्ञात हो।

पाश विभाजन
लूप स्प्लिटिंग एक लूप को सरल बनाने का प्रयास करता है या इसे कई लूपों में तोड़कर निर्भरता को समाप्त करता है जिसमें एक ही बॉडी होती है लेकिन इंडेक्स रेंज के विभिन्न सन्निहित भागों पर पुनरावृति होती है। एक उपयोगी विशेष मामला लूप छीलना है, जो लूप में प्रवेश करने से पहले उस पुनरावृत्ति को अलग से करके एक समस्याग्रस्त पहले पुनरावृत्ति के साथ एक लूप को सरल बना सकता है।
लूप अनस्विचिंग
अनस्विचिंग एक कंडीशनल को लूप के अंदर से लूप के बाहर ले जाता है, इसके लिए लूप की बॉडी को प्रत्येक if और else क्लाज के कंडीशनल के अंदर डुप्लीकेट करता है।

सॉफ्टवेयर पाइपलाइनिंग: लूप को इस तरह से पुनर्गठित किया जाता है कि पुनरावृत्ति में किए गए कार्य को कई भागों में विभाजित किया जाता है और कई पुनरावृत्तियों पर किया जाता है। तंग लूप में, यह तकनीक मूल्यों को लोड करने और उपयोग करने के बीच विलंबता को छुपाती है।

स्वचालित समांतरता: बहु-कोर मशीनों सहित साझा-मेमोरी मल्टीप्रोसेसर (एसएमपी) मशीन में एक साथ कई प्रोसेसर का उपयोग करने के लिए एक लूप को बहु-थ्रेडेड या वेक्टरकृत (या यहां तक ​​​​कि दोनों) कोड में परिवर्तित किया जाता है।

डेटा प्रवाह अनुकूलन

डेटा प्रवाह | डेटा प्रवाह अनुकूलन, डेटा प्रवाह विश्लेषण के आधार पर, मुख्य रूप से इस बात पर निर्भर करता है कि नियंत्रण प्रवाह ग्राफ में नियंत्रण किनारों द्वारा डेटा के कुछ गुणों का प्रचार कैसे किया जाता है। इनमें से कुछ में शामिल हैं:

सामान्य उप-अभिव्यक्ति उन्मूलन: एक्सप्रेशन में (a + b) - (a + b)/4, सामान्य उपअभिव्यक्ति डुप्लीकेट को संदर्भित करता है (a + b). इस तकनीक को लागू करने वाले संकलक यह महसूस करते हैं (a + b) नहीं बदलेगा, और इसलिए केवल एक बार इसके मान की गणना करें।[8]

लगातार तह
[9] स्थिरांक वाले व्यंजकों को प्रतिस्थापित करना (उदा., 3 + 5) उनके अंतिम मूल्य के साथ (8) रन-टाइम में गणना करने के बजाय संकलन समय पर। अधिकांश आधुनिक भाषाओं में प्रयुक्त।

प्रेरण चर पहचान और उन्मूलन: प्रेरण चर विश्लेषण के बारे में ऊपर चर्चा देखें।

सख्त अलियासिंग: पॉइंटर (कंप्यूटर प्रोग्रामिंग) की उपस्थिति में, कोई भी अनुकूलन करना मुश्किल है, क्योंकि संभावित रूप से किसी भी चर को तब बदला जा सकता है जब एक मेमोरी लोकेशन को असाइन किया जाता है। यह निर्दिष्ट करके कि कौन से संकेत किस चर को उपनाम कर सकते हैं, असंबंधित संकेत को अनदेखा किया जा सकता है।

डेड स्टोर | डेड-स्टोर एलिमिनेशन
वेरिएबल्स के असाइनमेंट को हटाना जो बाद में नहीं पढ़े जाते हैं, क्योंकि या तो वेरिएबल का जीवनकाल समाप्त हो जाता है या बाद के असाइनमेंट के कारण जो पहले मान को ओवरराइट कर देगा।

सर्व शिक्षा अभियान आधारित अनुकूलन

ये ऑप्टिमाइजेशन प्रोग्राम को एसएसए (कंपाइलर) नामक एक विशेष रूप में प्रोग्राम को बदलने के बाद किए जाने का इरादा है, जिसमें प्रत्येक चर को केवल एक ही स्थान पर असाइन किया जाता है। हालांकि कुछ एसएसए के बिना काम करते हैं, वे एसएसए के साथ सबसे प्रभावी हैं। अन्य अनुभागों में सूचीबद्ध कई अनुकूलन भी बिना किसी विशेष परिवर्तन के लाभान्वित होते हैं, जैसे कि पंजीकरण आवंटन।

वैश्विक मूल्य अंकन
जीवीएन प्रोग्राम के वैल्यू ग्राफ (कंपाइलर) का निर्माण करके अतिरेक को समाप्त करता है, और फिर यह निर्धारित करता है कि समकक्ष अभिव्यक्तियों द्वारा किन मूल्यों की गणना की जाती है। GVN कुछ अतिरेक की पहचान करने में सक्षम है जो सामान्य उप-अभिव्यक्ति उन्मूलन नहीं कर सकता है, और इसके विपरीत।

विरल सशर्त निरंतर प्रसार: निरंतर प्रसार, निरंतर तह और डेड-कोड उन्मूलन को जोड़ता है, और उन्हें अलग-अलग चलाकर जो संभव है उसमें सुधार करता है।[10][11] यह अनुकूलन कार्यक्रम को सांकेतिक रूप से निष्पादित करता है, साथ ही साथ निरंतर मूल्यों का प्रचार करता है और नियंत्रण-प्रवाह ग्राफ के कुछ हिस्सों को समाप्त कर देता है जिससे यह पहुंच से बाहर हो जाता है।

कोड जनरेटर अनुकूलन

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

निर्देश चयन: अधिकांश आर्किटेक्चर, विशेष रूप से कॉम्प्लेक्स इंस्ट्रक्शन सेट कंप्यूटर आर्किटेक्चर और कई एड्रेसिंग मोड वाले, निर्देशों के पूरी तरह से अलग अनुक्रमों का उपयोग करके एक विशेष ऑपरेशन करने के कई अलग-अलग तरीके प्रदान करते हैं। निर्देश चयनकर्ता का काम समग्र रूप से एक अच्छा काम करना है कि निम्न-स्तरीय मध्यवर्ती प्रतिनिधित्व में कौन से ऑपरेटरों को लागू करने के लिए कौन से निर्देशों को चुनना है। उदाहरण के लिए, 68000 परिवार में और x86 आर्किटेक्चर पर कई प्रोसेसर पर, जटिल एड्रेसिंग मोड का उपयोग lea 25(a1,d5*4), a0 जैसे बयानों में किया जा सकता है, जिससे एक निर्देश कम अंकगणित के साथ महत्वपूर्ण मात्रा में प्रदर्शन कर सकता है। भंडारण।

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

रीमैटेरियलाइजेशन: रीमैटेरियलाइज़ेशन किसी मान को मेमोरी से लोड करने के बजाय मेमोरी एक्सेस को रोकने के बजाय उसकी पुनर्गणना करता है। यह स्पिल से बचने के लिए रजिस्टर आवंटन के साथ मिलकर किया जाता है।

कोड फैक्टरिंग: यदि कोड के कई अनुक्रम समान हैं, या समान होने के लिए पैरामीटरयुक्त या पुन: व्यवस्थित किए जा सकते हैं, तो उन्हें कॉल के साथ एक साझा सबरूटीन में बदला जा सकता है। यह अक्सर सबरूटीन सेट-अप और कभी-कभी टेल-रिकर्सन के लिए कोड साझा कर सकता है।[12] ट्रैम्पोलिन (कंप्यूटिंग): कई[citation needed] कम मेमोरी तक पहुँचने के लिए CPU में छोटे सबरूटीन कॉल निर्देश होते हैं। एक कंपाइलर कोड के मुख्य भाग में इन छोटी कॉलों का उपयोग करके जगह बचा सकता है। कम मेमोरी में जंप निर्देश रूटीन को किसी भी पते पर एक्सेस कर सकते हैं। यह कोड फैक्टरिंग से जगह की बचत को गुणा करता है।[12]

पुनर्क्रमित संगणनाएँ: पूर्णांक रैखिक प्रोग्रामिंग के आधार पर, पुनर्गठन करने वाले संकलक डेटा स्थानीयता को बढ़ाते हैं और संगणनाओं को पुनर्व्यवस्थित करके अधिक समानता को उजागर करते हैं। स्पेस-ऑप्टिमाइज़िंग कंपाइलर अनुक्रमों को लंबा करने के लिए कोड को पुन: क्रमित कर सकते हैं जिन्हें सबरूटीन्स में शामिल किया जा सकता है।

कार्यात्मक भाषा अनुकूलन

हालांकि इनमें से कई गैर-कार्यात्मक भाषाओं पर भी लागू होते हैं, वे या तो लिस्प प्रोग्रामिंग भाषा और एमएल प्रोग्रामिंग भाषा जैसी कार्यात्मक भाषाओं में उत्पन्न होती हैं या विशेष रूप से महत्वपूर्ण हैं।

टेल-कॉल ऑप्टिमाइजेशन: एक फंक्शन कॉल में स्टैक स्पेस की खपत होती है और इसमें पैरामीटर पासिंग और निर्देश कैश को फ्लश करने से संबंधित कुछ ओवरहेड शामिल होते हैं। पूंछ की पुनरावृत्ति | टेल-रिकर्सिव एल्गोरिदम को टेल-रिकर्सन एलिमिनेशन या टेल-कॉल ऑप्टिमाइज़ेशन नामक प्रक्रिया के माध्यम से पुनरावृति में परिवर्तित किया जा सकता है।

वनों की कटाई (कंप्यूटर विज्ञान) (डेटा संरचना संलयन)
उन भाषाओं में जहां एक सूची में परिवर्तनों के अनुक्रम को लागू करना आम है, वनों की कटाई मध्यवर्ती डेटा संरचनाओं के निर्माण को हटाने का प्रयास करती है।
आंशिक मूल्यांकन

अन्य अनुकूलन

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

शाखा-ऑफ़सेट अनुकूलन (मशीन पर निर्भर)
लक्ष्य तक पहुँचने वाली सबसे छोटी शाखा विस्थापन चुनें।

कोड-ब्लॉक रीऑर्डरिंग: सशर्त शाखाओं को कम करने और संदर्भ के इलाके में सुधार करने के लिए कोड-ब्लॉक रीऑर्डरिंग प्रोग्राम में मूल ब्लॉक (प्रोग्रामिंग) के क्रम को बदल देता है।

डेड-कोड एलिमिनेशन: उन निर्देशों को हटाता है जो प्रोग्राम के व्यवहार को प्रभावित नहीं करेंगे, उदाहरण के लिए ऐसी परिभाषाएँ जिनका कोई उपयोग नहीं है, जिन्हें डेड कोड कहा जाता है। यह कोड आकार को कम करता है और अनावश्यक संगणना को समाप्त करता है।

इनवेरिएंट्स (पाश अपरिवर्तनीय्स) से फैक्टरिंग
यदि कोई एक्सप्रेशन किसी शर्त के पूरा होने पर और पूरा नहीं होने पर किया जाता है, तो इसे कंडीशनल स्टेटमेंट के बाहर सिर्फ एक बार लिखा जा सकता है। इसी तरह, यदि कुछ प्रकार के व्यंजक (उदाहरण के लिए, एक चर में एक स्थिरांक का असाइनमेंट) एक लूप के अंदर दिखाई देते हैं, तो उन्हें इससे बाहर निकाला जा सकता है क्योंकि उनका प्रभाव समान होगा चाहे वे कई बार निष्पादित हों या सिर्फ एक बार . इसे कुल अतिरेक उन्मूलन के रूप में भी जाना जाता है। एक समान लेकिन अधिक शक्तिशाली अनुकूलन आंशिक अतिरेक उन्मूलन (PRE) है।

इनलाइन विस्तार या मैक्रो (कंप्यूटर विज्ञान) विस्तार: जब कुछ कोड एक सबरूटीन का आह्वान करते हैं, तो नियंत्रण को स्थानांतरित करने के बजाय कॉलिंग कोड के अंदर प्रक्रिया के शरीर को सीधे सम्मिलित करना संभव है। यह प्रक्रिया कॉल से संबंधित ओवरहेड को बचाता है, साथ ही कई अलग-अलग पैरामीटर-विशिष्ट अनुकूलन के लिए अवसर प्रदान करता है, लेकिन स्थान की कीमत पर आता है; प्रक्रिया निकाय को प्रत्येक बार प्रक्रिया को इनलाइन कहा जाता है। आम तौर पर, प्रदर्शन-महत्वपूर्ण कोड में इनलाइनिंग उपयोगी होती है जो छोटी प्रक्रियाओं के लिए बड़ी संख्या में कॉल करती है। एक कम छलांग अनुकूलन[sentence fragment]. अनिवार्य प्रोग्रामिंग भाषाओं का कथन (कंप्यूटर विज्ञान) भी ऐसे अनुकूलन का एक उदाहरण है। हालांकि बयानों को सबरूटीन के साथ लागू किया जा सकता है, लेकिन वे लगभग हमेशा कोड इनलाइनिंग के साथ लागू होते हैं।

जंप थ्रेडिंग
इस ऑप्टिमाइज़ेशन में, एक ही स्थिति पर पूरी तरह या आंशिक रूप से अनुमानित लगातार सशर्त कूद मर्ज किए जाते हैं।
जैसे, if (c) { foo; } if (c) { bar; } को if (c) { foo; bar; },
और if (c) { foo; } if (!c) { bar; } को if (c) { foo; } else { bar; }.
मैक्रो संपीड़न
एक स्थान अनुकूलन जो कोड के सामान्य अनुक्रमों को पहचानता है, उपप्रोग्राम (कोड मैक्रोज़) बनाता है जिसमें सामान्य कोड होता है, और सामान्य कोड अनुक्रमों की घटनाओं को संबंधित उपप्रोग्रामों में कॉल के साथ बदल देता है।[6]यह मशीन कोड अनुकूलन के रूप में सबसे प्रभावी ढंग से किया जाता है, जब सभी कोड मौजूद होते हैं। तकनीक का उपयोग पहली बार माइक्रो-कंप्यूटरों पर एसपीआईटीबीओएल कंपाइलर के कार्यान्वयन में उपयोग की जाने वाली व्याख्यात्मक बाइट स्ट्रीम में अंतरिक्ष को संरक्षित करने के लिए किया गया था।[13] किसी दिए गए कोड सेगमेंट द्वारा आवश्यक स्थान को कम करने वाले मैक्रोज़ के इष्टतम सेट को निर्धारित करने की समस्या को एनपी-पूर्ण कहा जाता है,[6]लेकिन कुशल अनुमानी लगभग इष्टतम परिणाम प्राप्त करते हैं।[14]
कैश कम करना (कंप्यूटिंग) टकराव
(उदाहरण के लिए, एक पृष्ठ के भीतर संरेखण को बाधित करके)
स्टैक (कंप्यूटर विज्ञान)-ऊंचाई में कमी
अभिव्यक्ति मूल्यांकन के लिए आवश्यक संसाधनों को कम करने के लिए अभिव्यक्ति ट्री को पुनर्व्यवस्थित करें।
टेस्ट रीऑर्डरिंग
यदि हमारे पास दो परीक्षण हैं जो किसी चीज़ के लिए शर्त हैं, तो हम पहले सरल परीक्षणों से निपट सकते हैं (उदाहरण के लिए, एक चर की किसी चीज़ से तुलना करना) और उसके बाद ही जटिल परीक्षणों के साथ (जैसे, जिन्हें फ़ंक्शन कॉल की आवश्यकता होती है) . यह तकनीक आलसी मूल्यांकन का पूरक है, लेकिन इसका उपयोग केवल तभी किया जा सकता है जब परीक्षण एक दूसरे पर निर्भर न हों। न्यूनतम मूल्यांकन|शॉर्ट-सर्किटिंग शब्दार्थ इसे कठिन बना सकते हैं।

अंतरप्रक्रियात्मक अनुकूलन

इंटरप्रोसेरल अनुकूलन प्रक्रिया और फ़ाइल सीमाओं के पार, पूरे प्रोग्राम पर काम करता है। यह एक स्थानीय भाग और वैश्विक भाग के सहयोग से किए गए अंतःक्रियात्मक समकक्षों के साथ कसकर काम करता है। विशिष्ट इंटरप्रोसेडुरल ऑप्टिमाइज़ेशन हैं: प्रक्रिया इनलाइनिंग, इंटरप्रोसेडुरल डेड-कोड एलिमिनेशन, इंटरप्रोसेडुरल कॉन्सटेंट प्रोपेगेशन, और प्रक्रिया पुनर्क्रमित करना सामान्य रूप से, कंपाइलर को वास्तविक अनुकूलन से पहले इंटरप्रोसेडुरल विश्लेषण करने की आवश्यकता होती है। इंटरप्रोसेडुरल विश्लेषण में उपनाम विश्लेषण, सरणी पहुंच विश्लेषण और कॉल ग्राफ़ का निर्माण शामिल है।

सिलिकॉन ग्राफिक्स, इंटेल, माइक्रोसॉफ्ट, और सन माइक्रोसिस्टम्स के आधुनिक वाणिज्यिक कंपाइलरों में इंटरप्रोसेडुरल ऑप्टिमाइज़ेशन आम है। लंबे समय तक, ओपन सोर्स GNU कंपाइलर कलेक्शन की आलोचना की गई थी[citation needed] शक्तिशाली अंतर-प्रक्रियात्मक विश्लेषण और अनुकूलन की कमी के लिए, हालांकि अब इसमें सुधार हो रहा है।[citation needed] पूर्ण विश्लेषण और अनुकूलन अवसंरचना के साथ एक अन्य ओपन सोर्स कंपाइलर Open64 है।

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

व्यावहारिक विचार

ऑप्टिमाइज़ेशन की एक विस्तृत श्रृंखला हो सकती है जो एक कंपाइलर सरल और सीधे से कर सकता है, जिसमें थोड़ा संकलन समय लगता है और विस्तृत और जटिल होता है जिसमें काफी मात्रा में संकलन समय शामिल होता है।[15] तदनुसार, संकलक अक्सर अपने नियंत्रण आदेश या प्रक्रिया को विकल्प प्रदान करते हैं ताकि संकलक उपयोगकर्ता को यह चुनने की अनुमति मिल सके कि अनुरोध करने के लिए कितना अनुकूलन है; उदाहरण के लिए, आईबीएम फोरट्रान एच कंपाइलर ने उपयोगकर्ता को कोई अनुकूलन निर्दिष्ट करने की अनुमति नहीं दी, केवल रजिस्टर स्तर पर अनुकूलन, या पूर्ण अनुकूलन।[16] 2000 के दशक तक, क्लैंग जैसे कंपाइलरों के लिए कई कंपाइलर कमांड विकल्प होना आम बात थी, जो परिचित से शुरू होने वाले विभिन्न प्रकार के अनुकूलन विकल्पों को प्रभावित कर सकते थे। -O2 बदलना।[17] अलगाव अनुकूलन के लिए एक दृष्टिकोण तथाकथित पोस्ट-पास ऑप्टिमाइज़र का उपयोग है (जिनमें से कुछ व्यावसायिक संस्करण 1970 के दशक के अंत के मेनफ्रेम सॉफ़्टवेयर में वापस आते हैं)।[18] ये उपकरण एक ऑप्टिमाइज़िंग कंपाइलर द्वारा निष्पादन योग्य आउटपुट लेते हैं और इसे आगे भी अनुकूलित करते हैं। पोस्ट-पास ऑप्टिमाइज़र आमतौर पर असेंबली भाषा या मशीन कोड स्तर पर काम करते हैं (कंपाइलर के विपरीत जो कार्यक्रमों के मध्यवर्ती प्रतिनिधित्व को अनुकूलित करते हैं)। ऐसा ही एक उदाहरण 1980 के दशक का पोर्टेबल सी कंपाइलर (पीसीसी) है, जिसमें एक वैकल्पिक पास था जो जनरेट किए गए असेंबली कोड पर पोस्ट-ऑप्टिमाइज़ेशन करेगा।[19] एक अन्य विचार यह है कि अनुकूलन एल्गोरिदम जटिल हैं और विशेष रूप से जब बड़ी, जटिल प्रोग्रामिंग भाषाओं को संकलित करने के लिए उपयोग किया जा रहा है, तो इसमें बग हो सकते हैं जो उत्पन्न कोड में त्रुटियों का परिचय देते हैं या संकलन के दौरान आंतरिक त्रुटियों का कारण बनते हैं। किसी भी प्रकार की संकलक त्रुटियाँ उपयोगकर्ता के लिए चिंताजनक हो सकती हैं, लेकिन विशेष रूप से इस मामले में, क्योंकि यह स्पष्ट नहीं हो सकता है कि अनुकूलन तर्क में गलती है।[20] आंतरिक त्रुटियों के मामले में, समस्या को एक असफल-सुरक्षित प्रोग्रामिंग तकनीक द्वारा आंशिक रूप से सुधारा जा सकता है जिसमें संकलक में अनुकूलन तर्क को इस तरह से कोडित किया जाता है कि एक विफलता फंस जाती है, एक चेतावनी संदेश जारी किया जाता है, और शेष संकलन आगे बढ़ता है सफल समापन।[21]


इतिहास

1960 के शुरुआती संकलक अक्सर मुख्य रूप से कोड को सही ढंग से या कुशलता से संकलित करने से संबंधित थे, जैसे कि संकलन समय एक प्रमुख चिंता का विषय था। एक उल्लेखनीय प्रारंभिक अनुकूलन संकलक 1960 के दशक के उत्तरार्ध का IBM FORTRAN H संकलक था।[16]परम आनंद (1970) के लिए सबसे शुरुआती और महत्वपूर्ण ऑप्टिमाइज़िंग कंपाइलर में से एक, जिसने कई उन्नत तकनीकों का नेतृत्व किया, जिसका वर्णन एक ऑप्टिमाइज़िंग कंपाइलर का डिज़ाइन (1975) में किया गया था।[22] 1980 के दशक के अंत तक, अनुकूलन करने वाले संकलक पर्याप्त रूप से प्रभावी थे कि असेंबली भाषा में प्रोग्रामिंग में गिरावट आई। यह आरआईएससी चिप्स और उन्नत प्रोसेसर सुविधाओं जैसे निर्देश शेड्यूलिंग और सट्टा निष्पादन के विकास के साथ सह-विकसित हुआ, जिसे मानव-लिखित असेंबली कोड के बजाय कंपाइलर्स को अनुकूलित करने के लिए डिज़ाइन किया गया था।[citation needed]


स्थैतिक कोड विश्लेषणों की सूची

यह भी देखें

संदर्भ

  1. Aho, Alfred V.; Sethi, Ravi; Ullman, Jeffrey D. (1986). Compilers: Principles, Techniques, and Tools. Reading, Massachusetts: Addison-Wesley. p. 585. ISBN 0-201-10088-6.
  2. Aho, Sethi, and Ullman, Compilers, p. 554.
  3. 3.0 3.1 Cooper, Keith D.; Torczon, Linda (2003) [2002-01-01]. इंजीनियरिंग एक संकलक. Morgan Kaufmann. pp. 404, 407. ISBN 978-1-55860-698-2.
  4. 4.0 4.1 Aho, Sethi, and Ullman, Compilers, p. 596.
  5. "MSDN - Prescient Store Actions". Microsoft. Retrieved 2014-03-15.
  6. 6.0 6.1 6.2 Clinton F. Goss (August 2013) [First published June 1986]. Machine Code Optimization - Improving Executable Object Code (PDF) (Ph.D. dissertation). Vol. Computer Science Department Technical Report #246. Courant Institute, New York University. arXiv:1308.4815. Bibcode:2013arXiv1308.4815G. Archived (PDF) from the original on 2022-10-09. Retrieved 22 Aug 2013.
  7. Aho, Sethi, and Ullman, Compilers, pp. 596–598.
  8. Aho, Sethi, and Ullman, Compilers, pp. 592–594.
  9. Steven Muchnick; Muchnick and Associates (15 August 1997). Advanced Compiler Design Implementation. Morgan Kaufmann. pp. 329–. ISBN 978-1-55860-320-2. constant folding.
  10. Wegman, Mark N. and Zadeck, F. Kenneth. "Constant Propagation with Conditional Branches." ACM Transactions on Programming Languages and Systems, 13(2), April 1991, pages 181-210.
  11. Click, Clifford and Cooper, Keith. "Combining Analyses, Combining Optimizations", ACM Transactions on Programming Languages and Systems, 17(2), March 1995, pages 181-196
  12. 12.0 12.1 Cx51 Compiler Manual, version 09.2001, p155, Keil Software Inc.
  13. Robert B. K. Dewar; Martin Charles Golumbic; Clinton F. Goss (August 2013) [First published October 1979]. MICRO SPITBOL. Computer Science Department Technical Report. Vol. No. 11. Courant Institute of Mathematical Sciences. arXiv:1308.6096. Bibcode:2013arXiv1308.6096D.
  14. Martin Charles Golumbic; Robert B. K. Dewar; Clinton F. Goss (1980). "Macro Substitutions in MICRO SPITBOL - a Combinatorial Analysis". Proc. 11th Southeastern Conference on Combinatorics, Graph Theory and Computing, Congressus Numerantium, Utilitas Math., Winnipeg, Canada. 29: 485–495.
  15. Aho, Sethi, and Ullman, Compilers, p. 15.
  16. 16.0 16.1 Aho, Sethi, and Ullman, Compilers, p. 737.
  17. Guelton, Serge (August 5, 2019). "Customize the compilation process with Clang: Optimization options". Red Hat.
  18. Software engineering for the Cobol environment. Portal.acm.org. Retrieved on 2013-08-10.
  19. Aho, Sethi, and Ullman, Compilers, p. 736.
  20. Sun, Chengnian; et al. (July 18–20, 2016). "Toward understanding compiler bugs in GCC and LLVM". ISSTA 2016: Proceedings of the 25th International Symposium on Software Testing and Analysis. Issta 2016: 294–305. doi:10.1145/2931037.2931074. ISBN 9781450343909. S2CID 8339241.
  21. Schilling, Jonathan L. (August 1993). "Fail-safe programming in compiler optimization". ACM SIGPLAN Notices. 28 (8): 39–42. doi:10.1145/163114.163118. S2CID 2224606.
  22. Aho, Sethi, and Ullman, Compilers, pp. 740, 779.


बाहरी संबंध