बस बदलते कंपाइलर्स कई बार एक ही स्रोत कोड के लिए आपके सी प्रदर्शन को बेहतर बना सकते हैं। जीसीसी ने पिछले कुछ वर्षों में प्रदर्शन के लिए बेहतर नहीं पाया है, कुछ कार्यक्रमों के लिए जीसीसी 3.x 4.x से अधिक कठिन कोड उत्पन्न करता है। वापस जब मेरे पास टूल्स तक पहुंच थी, एआरएम कंपाइलर ने जीसीसी की तुलना में काफी बेहतर कोड बनाया। जितना 3 या 4 गुना तेज। एलएलवीएम ने जीसीसी 4.x तक पकड़ा है और मुझे संदेह है कि एम्बेडेड कोड को संकलित करने के लिए प्रदर्शन और समग्र उपयोग के संदर्भ में जीसीसी पास होगा। यदि आप जीसीसी का उपयोग कर रहे हैं तो जीसीसी, 3.x और 4.x के विभिन्न संस्करणों को आजमाएं। मेटावेयर का कंपाइलर और हथियार एटीटी gcc3.x के आसपास सर्किल चला गया, gcc3.x gcc4.xa को आर्म कोड के साथ अपने पैसे के लिए चलाएगा, अंगूठे कोड gcc4.x बेहतर है और अंगूठे 2 (जो आपके लिए लागू नहीं होता है) gcc4.x भी बेहतर। याद रखें मैंने कोड की एक पंक्ति को बदलने के बारे में एक शब्द नहीं कहा है (अभी तक)।
एलएलवीएम जीसीसी की तुलना में असीमित रूप से अधिक ट्यूनिंग knobs के अलावा पूर्ण कार्यक्रम अनुकूलन करने में सक्षम है। इसके बावजूद कोड उत्पन्न हुआ (वर्क 27) केवल कुछ कार्यक्रमों के प्रदर्शन के संदर्भ में वर्तमान जीसीसी 4.x तक ही पकड़ रहा है।और मैंने ऑप्टिमाइज़ेशन संयोजनों की एन फैक्टरल संख्या (संकलन चरण पर अनुकूलित, प्रत्येक फ़ाइल के लिए अलग-अलग विकल्प, या दो फाइलों या तीन फाइलों या सभी फ़ाइलों को गठबंधन करने और उन बंडलों को अनुकूलित करने की कोशिश नहीं की, मेरा सिद्धांत सी से बीसी पर कोई अनुकूलन नहीं है चरण, सभी बीसी को एकसाथ लिंक करें, फिर पूरे कार्यक्रम पर एक ऑप्टिमाइज़ेशन पास करें, जब इसे एलसीसी लक्ष्य पर ले जाता है तो डिफ़ॉल्ट अनुकूलन की अनुमति दें)।
उसी टोकन से बस अपने कंपाइलर को जानना और अनुकूलन कोड के प्रदर्शन को बिना किसी बदलाव के बेहतर कर सकते हैं। आपके पास AR1111 arr है जिसे आप arm11 या जेनेरिक आर्म के लिए संकलित करते हैं? आप जेनेरिक armv4 (ARM7) पर विशेष रूप से डिफ़ॉल्ट रूप से चुने गए संकलक/परिवार (उदाहरण के लिए armv6) को संकलक बताकर एक दर्जन प्रतिशत प्राप्त कर सकते हैं। यदि आप बहादुर हैं तो -ओ 2 या -ओ 3 का उपयोग करना सीखना।
अक्सर यह मामला नहीं है लेकिन अंगूठे मोड में स्विच करने से विशिष्ट प्लेटफार्मों के प्रदर्शन में सुधार हो सकता है। आपके लिए लागू नहीं होता है लेकिन गेमबॉय अग्रिम एक आदर्श उदाहरण है, जो गैर-शून्य प्रतीक्षा राज्य 16 बिट बस के साथ भरा हुआ है। अंगूठे में एक प्रतिशत ओवरहेड है, क्योंकि यह एक ही काम करने के लिए और अधिक निर्देश लेता है, लेकिन fetch समय को बढ़ाकर, और जीबीए थंब कोड की कुछ अनुक्रमिक पढ़ने की विशेषताओं का लाभ लेना हाथ के कोड से काफी तेजी से चला सकता है एक ही स्रोत कोड।
एक arm11 होने के कारण आपके पास शायद एक एल 1 और शायद एल 2 कैश हो, क्या वे चालू हैं? क्या वे कॉन्फ़िगर हैं? क्या आपके पास एमएमयू है और क्या आपकी भारी उपयोग मेमोरी कैश है? या आप शून्य प्रतीक्षा राज्य मेमोरी चला रहे हैं और कैश की आवश्यकता नहीं है और इसे बंद करना चाहिए? यह महसूस करने के अलावा कि आप एक ही स्रोत कोड ले सकते हैं और इसे कंपाइलर्स या विकल्पों को बदलकर कई बार तेज़ी से चला सकते हैं, लोगों को अक्सर यह नहीं पता कि जब आप कैश का उपयोग करते हैं तो बस अपने स्टार्टअप कोड में कुछ नॉप्स को सिंगल जोड़ना (कोड को दो, दो, कुछ शब्दों द्वारा स्मृति में स्थानांतरित करने के लिए एक चाल के रूप में) आप अपने कोड निष्पादन गति को 10 से 20 प्रतिशत तक बदल सकते हैं। जहां उन कैश लाइन भारी उपयोग किए गए कार्यों/लूप में हिट पढ़ती हैं, वहां एक बड़ा अंतर होता है। यहां तक कि एक कोड कैश लाइन को सहेजकर भी पढ़ा जाता है जहां कोड भूमि ध्यान देने योग्य है (उदाहरण के लिए इसे 3 से 2 या 2 से 1 तक काटकर)।
अपने आर्किटेक्चर को जानना, प्रोसेसर और आपकी मेमोरी पर्यावरण दोनों, जहां कोई भी शुरू होता है तो ट्यूनिंग। अधिकांश सी पुस्तकालय यदि आप एक उच्च स्तर के उपयोग के लिए पर्याप्त हैं (मैं अक्सर सी लाइब्रेरी का उपयोग नहीं करता क्योंकि मैं ऑपरेटिंग सिस्टम के बिना और बहुत सीमित संसाधनों के साथ चलाता हूं) दोनों अपने सी कोड में और कभी-कभी कुछ असेंबलर को मेम्प्पी जैसे बाधा दिनचर्या बनाने के लिए जोड़ते हैं, काफी तेज। यदि आपके प्रोग्राम 32 या उससे भी बेहतर 64 बिट पते पर गठबंधन कर रहे हैं, और यदि आप इसका मतलब है कि प्रत्येक संरचना/सरणी/memcpy के लिए बाइट्स को अधिक मेमोरी का उपयोग करना है तो 32 बिट्स या 64 बिट्स का एक अभिन्न एकाधिक होना ध्यान देने योग्य सुधार (यदि आपका कोड structs का उपयोग करता है या अन्य तरीकों से डेटा कॉपी करता है)। अपनी संरचनाओं को प्राप्त करने के अलावा (यदि आप उनका उपयोग करते हैं, तो मैं निश्चित रूप से एम्बेडेड कोड के साथ नहीं) आकार गठबंधन करता हूं, भले ही आप स्मृति को बर्बाद करते हैं, तत्वों को गठबंधन करते हैं, बाइट्स या आधा पासवर्ड के बजाय प्रत्येक तत्व के लिए 32 बिट पूर्णांक का उपयोग करने पर विचार करें। आपकी मेमोरी सिस्टम के आधार पर यह मदद कर सकता है (यह भी बीटीडब्ल्यू को चोट पहुंचा सकता है)। जैसा कि ऊपर दिए गए जीबीए उदाहरण के साथ-साथ प्रोफाइलिंग या अंतर्ज्ञान से आपको पता चलता है कि आपके प्रोसेसर या प्लेटफार्म या पुस्तकालयों का लाभ उठाने के तरीके को लागू नहीं किया जा रहा है, आप शुरुआत में सी से स्क्रैच या संकलन से असेंबलर में बदलना चाह सकते हैं फिर अलग करना और हाथ ट्यूनिंग। Memcpy एक अच्छा उदाहरण है, आप अपने सिस्टम मेमोरी प्रदर्शन को जान सकते हैं और विशेष रूप से गठबंधन डेटा के लिए अपनी खुद की memcpy बनाने के लिए चुन सकते हैं, प्रति निर्देश 64 या 128 या अधिक बिट्स की प्रतिलिपि बना सकते हैं।
इसी प्रकार वैश्विक और स्थानीय चर मिश्रण करने से एक उल्लेखनीय प्रदर्शन अंतर हो सकता है। परंपरागत रूप से लोगों को कभी भी ग्लोबल्स का उपयोग नहीं करने के लिए कहा जाता है, लेकिन एम्बेडेड में यह जरूरी नहीं है कि यह कितना गहराई से एम्बेडेड है और कितनी ट्यूनिंग और गति और अन्य कारकों में आप रुचि रखते हैं। यह एक स्पर्शपूर्ण विषय है और मैं इसके लिए फ्लेम हो सकता हूं, इसलिए मैं इसे वहां पर छोड़ दूंगा।
कंपाइलर को फ़ंक्शन कॉल करने के लिए रजिस्टरों को जला देना और बेदखल करना पड़ता है, साथ ही यदि आप स्थानीय चर का उपयोग करते हैं तो स्टैक फ्रेम की आवश्यकता हो सकती है, इसलिए फ़ंक्शन कॉल महंगे होते हैं, लेकिन साथ ही, कोड के आधार पर कार्य जो अब कार्यों से बचकर आकार में उगाया गया है, आप उस समस्या को बना सकते हैं जिसे आप टालने का प्रयास कर रहे थे, रजिस्टरों को दोबारा उपयोग करने के लिए बेदखल कर रहे थे। यहां तक कि सी कोड की एक पंक्ति भी रजिस्ट्रारों के समूह को बेदखल करने के लिए रजिस्टरों में फिट बैठने वाले सभी चर के बीच अंतर कर सकती है। कोड के फ़ंक्शंस या सेगमेंट के लिए जहां आप जानते हैं कि आपको कुछ प्रदर्शन लाभ की आवश्यकता होती है और डिस्सेबल (और रजिस्टर उपयोग को देखते हैं, यह स्मृति को कितनी बार लाता है या स्मृति में लिखता है)। आप उन जगहों को ढूंढ सकते हैं जहां आपको एक अच्छी तरह से इस्तेमाल किया जाने वाला लूप लेने की आवश्यकता होती है और फ़ंक्शन कॉल को दंडित करने के बावजूद इसे अपना स्वयं का फ़ंक्शन बनाते हैं क्योंकि ऐसा करने से संकलक लूप को बेहतर अनुकूलित कर सकता है और रजिस्टरों को बेदखल/पुन: उपयोग नहीं कर सकता है और आपको एक मिलता है कुल शुद्ध लाभ। एक लूप में भी एक अतिरिक्त निर्देश जो सैकड़ों बार जाता है, एक मापनीय प्रदर्शन हिट होता है।
उम्मीद है कि आप पहले से ही डीबग के लिए संकलन नहीं करना चाहते हैं, डीबग विकल्पों के लिए सभी संकलन बंद करें। आप पहले से ही जानते हैं कि बग के बिना चलने वाले डीबग के लिए कोड संकलन का मतलब यह नहीं है कि यह डिबग किया गया है, डीबग के लिए संकलन और डिबगर्स का उपयोग करके उन्हें छोड़ने के लिए अपने अंतिम संकलन के लिए आपके कोड में समय बम के रूप में उन्हें छोड़कर बग को छुपाएं। प्रदर्शन के लिए रिलीज संस्करण के साथ संकलन और परीक्षण के लिए हमेशा संकलन करना सीखें और अपने कोड में बग ढूंढें।
अधिकांश निर्देश सेट में विभाजित फ़ंक्शन नहीं है। अपने कोड में विभाजित या मॉड्यूलो का उपयोग करने से बचें जितना संभव हो उतना मानव प्रदर्शन संभवतः वे प्रदर्शन हत्यारे हैं। स्वाभाविक रूप से यह दो की शक्तियों का मामला नहीं है, संकलक को बचाने के लिए और मानसिक रूप से विभाजन से बचने के लिए और मॉड्यूलोज़ शिफ्ट और एंड्स का उपयोग करने का प्रयास करते हैं। बहुसंख्यक निर्देश सेट में आसान और अक्सर पाए जाते हैं, लेकिन अभी भी महंगा हैं। सी संकलक इसे करने की बजाय आपके गुणों को करने के लिए असेंबलर लिखना एक अच्छा मामला है। बांह गुणा एक 32 बिट * 32 बिट = 32 बिट है ताकि बिना किसी बहने के सटीक गणित करने के लिए अतिरिक्त सी कोड को गुणा करने के लिए लपेटा जाना चाहिए, यदि आप पहले से ही जानते हैं कि आप ओवरफ्लो नहीं हैं, तो फ़ंक्शन कॉल के लिए रजिस्टरों को जलाएं और गुणा करें असेंबलर (हाथ के लिए)।
इसी प्रकार अधिकांश निर्देश सेटों में फ्लोटिंग पॉइंट यूनिट नहीं है, आपके साथ आप भी हो सकते हैं, यहां तक कि यदि संभव हो तो फ्लोट से बचें। यदि आपको फ्लोट का उपयोग करना है जो प्रदर्शन मुद्दों के एक अन्य पैंडोरा बॉक्स है। अधिकांश लोगों को न इस के रूप में सरल कोड के साथ प्रदर्शन की समस्याओं देखें:
float a,b;
...
a = b * 7.0;
समस्या के बाकी चल बिन्दु सटीकता और कैसे समझ नहीं है अच्छा या बुरा सी पुस्तकालयों बस चल बिन्दु में अपने स्थिरांक पाने के लिए कोशिश कर रहे हैं प्रपत्र। फिर से प्रदर्शन प्रदर्शन समस्याओं पर एक और लंबी चर्चा है।
मैं माइकल एब्रैश का एक उत्पाद हूं (वास्तव में असेंबली भाषा के जेन की एक प्रिंट प्रति है) और नीचे की रेखा आपके कोड का समय है। कोड के समय के सटीक तरीके से आते हैं, आपको लगता है कि आप जानते हैं कि बाधाएं कहां हैं और आपको लगता है कि आप अपने वास्तुकला को जानते हैं लेकिन विभिन्न चीजों को आजमाते हैं, भले ही आपको लगता है कि वे गलत हैं, और उन्हें समय देने पर आपको मिल सकता है और अंततः अपनी सोच में त्रुटि का पता लगाएं। शुरू करने के लिए nops जोड़ना। अंतिम ट्यूनिंग चरण के रूप में इसका एक अच्छा उदाहरण है, प्रदर्शन के लिए आपके द्वारा किए गए सभी अन्य कार्यों को कैश के साथ अच्छा संरेखण न होने के तुरंत बाद मिटाया जा सकता है, इसका मतलब यह भी है कि आपके भीतर कार्यों को फिर से व्यवस्थित करना स्रोत कोड ताकि वे बाइनरी छवि में विभिन्न स्थानों पर उतर सकें। मैंने कैश लाइन संरेखण के परिणामस्वरूप गति वृद्धि और कमी के 10 से 20 प्रतिशत स्विंग्स को देखा है।
क्या कोई ओएस है? यह क्या है? आप किस कंपाइलर/टूलचेन का उपयोग कर रहे हैं? क्या आपके पास अतिरिक्त जीपीआईओ है? क्या आपके पास सिम्युलेटर काम कर रहा है? _Embedded_ एक बड़ा क्षेत्र है। – nategoose