2012-10-10 21 views
5
  1. llvm या gcc कंपाइलर्स का उपयोग करते समय परिणामस्वरूप मशीन कोड के संदर्भ में निम्नलिखित दो कोड ब्लॉक के बीच कोई अंतर है?
  2. यह अनुकूलन वास्तव में सार्थक कब होता है, अगर कभी?

अनुकूलित नहीं:क्या यह लूप के लिए सशर्त प्रीकंप्यूटिंग के लायक है?

for (int i=0; i<array.count; i++) { 
    //do some work 
} 

अनुकूलित:

int count = array.count; 
for (int i=0; i<count; i++) { 
    //do some work 
} 

संपादित: मैं कहना चाहिए कि array अपरिवर्तनीय है और array.count पाश के निष्पादन के दौरान नहीं बदलता है।

+2

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

+1

इस मामले में, किसी ऑब्जेक्ट को भेजा गया एक संदेश है, मुझे संदेह है कि संकलक इसमें हस्तक्षेप करता है, इसलिए मेरा अनुमान होगा कि प्रत्येक पुनरावृत्ति पर 'गिनती' विधि को बुलाया जाएगा। हालांकि, यह शायद एक बहुत सस्ता कॉल है। इस विशेष मामले में सबसे अच्छा तरीका सरणी पर तेज गणना का उपयोग करना होगा। – Guillaume

+3

"सरणी अपरिवर्तनीय है और array.count बदलता नहीं है" - मुझे उद्देश्य-सी नहीं पता, चाहे "अपरिवर्तनीय" एक ऐसी संपत्ति है जिसे संकलक समझता है, लेकिन अनुकूलन उद्देश्यों के लिए इससे कोई फर्क नहीं पड़ता कि ' array.count' परिवर्तन, यह महत्वपूर्ण है कि संकलक स्वयं को साबित कर सकता है कि 'array.count' नहीं बदलेगा। –

उत्तर

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

मान लीजिए array.count कुछ वास्तव में धीमा है, तो आपको पता चल जाएगा कि हमेशा एक ही परिणाम वापस आ जाएगा लेकिन संकलक इसे नहीं जानता है। तो यह मैन्युअल रूप से इसे उभारा लायक हो सकता है। strlen एक उदाहरण के रूप में उपयोग किया जाता है। यह बहस का मुद्दा है कि कितनी बार strlen व्यवहार में वास्तव में धीमी है, लेकिन धीमी गति से वे की जरूरत को चलाने की संभावना उदाहरण निर्माण करने के लिए आसान है:

char some_function(char a) { 
    return (a * 2 + 1) & 0x3F; 
} 

for (int i = 0; i < strlen(ptr); ++i) { 
    ptr[i] = some_function(ptr[i]); // faster than strlen for long enough strings. 
} 

आप और मुझे पता है कि some_function कभी नहीं देता है 0, और इसलिए की लंबाई स्ट्रिंग कभी नहीं बदलती है। कंपाइलर को some_function की परिभाषा दिखाई नहीं दे सकती है, और यहां तक ​​कि यदि यह देखता है कि परिभाषा को यह नहीं पता हो सकता है कि इसकी गैर-शून्य-वापसी महत्वपूर्ण है।

1

स्टीव जेसॉप उत्तर एक अच्छा है। मैं बस जोड़ना चाहता हूं:

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

संबंधित मुद्दे