2013-03-21 7 views
14

प्रोग्रामिंग में एक बहुत ही सामान्य पैटर्न किसी प्रकार के अपडेट के बाद अधिकतम मूल्य को कैप करना है। मैं जानना चाहते हैं क्या है, अगर वहाँ कोड की निम्न दो टुकड़ों के बीच एक अंतर है, और एक प्राथमिकता दी जानी चाहिए, यदि:सी ++ में, क्या std :: min या if शाखा का उपयोग करके मूल्य को कैप करना बेहतर है?

value += increment; 
value = std::min(value, valueMax); 

बनाम

value += increment; 

if (value > valueMax) 
    value = valueMax; 

मेरे सोच है कि इस नीचे आता है क्या सीपीयू के पास दो मान लेने और न्यूनतम उत्पादन करने के निर्देश हैं। यदि ऐसा है, तो std :: min पर कॉल का परिणाम इस निर्देश में होना चाहिए और एक अनावश्यक शाखा से बचें। यदि नहीं, तो दूसरा संस्करण एक अनावश्यक असाइनमेंट से बचाता है जब मान < = valueMax।

मैं इस तरह की चीज़ के साथ बहुत अच्छा नहीं हूं, लेकिन मुझे यकीन है कि पुरानी स्कूल असेंबली हैकर जो इसे जान लेंगे। उनके लिए मैं पूछता हूं: कौन सा बेहतर है?

+2

दोनों को आजमाएं और असेंबली को देखें ... – Mysticial

+0

मैं कहूंगा कि पहला संस्करण हमेशा * कम से कम * साथ ही दूसरे संस्करण को भी करेगा, इसलिए इसका उपयोग करने का कोई कारण नहीं है। पहला संस्करण * भी * तेज हो सकता है, हालांकि इसके बारे में कोई गारंटी नहीं है। –

+0

रहस्यवादी निहित की तरह, यह std :: min (http://en.cppreference.com/w/cpp/algorithm/min) के कार्यान्वयन पर निर्भर करता है। – DavidA

उत्तर

10

आधुनिक कंपाइलर दोनों मामलों में एक ही कोड उत्पन्न करने के लिए पर्याप्त स्मार्ट हैं। उदाहरण के लिए, 32-बिट जीसीसी उत्पन्न करता है:

addl %esi, %edi 
cmpl %edx, %edi 
movl %edi, %eax 
cmovgl %edx, %eax 

64-बिट बजना:

%1 = add nsw i32 %increment, %value 
%2 = icmp sgt i32 %1, %valueMax 
%value = select i1 %2, i32 %valueMax, i32 %1 
+0

+1। क्या आप यहां असेंबली को कुछ एनोटेशन दे सकते हैं? क्या कोई शाखा है? – voltrevo

+2

@ मोज़ाज़ा 314 यहां कोई शाखा नहीं है। कंपाइलर ने उतना ही अच्छा किया जितना किया जा सकता है - जो एक सशर्त चाल का उपयोग करना है। – Mysticial

4

VC10 पर रिलीज पर निम्न कोड हम निम्नलिखित विधानसभा के लिए:

int main(int argc, char *argv[]) 
{ 
    int dummyValue = 0, valueMax = 3000, value = valueMax + 1; 

    cin >> valueMax; 
    cin >> value; 

    dummyValue = std::min(value, valueMax); 

    cout << dummyValue; 
    cin >> valueMax; 
    cin >> value; 

    if (value > valueMax) 
    dummyValue = valueMax; 

    cout << dummyValue; 
    return 0; 
} 

जनरेट किया गया :

24: dummyValue = std::min(value, valueMax); 
00E112AF mov   eax,dword ptr [valueMax] 
00E112B2 cmp   eax,dword ptr [value] 
00E112B5 lea   edx,[value] 
00E112B8 lea   ecx,[valueMax] 
00E112BB cmovge  ecx,edx  // <-- this is our conditional assignment 
00E112BE mov   esi,dword ptr [ecx] 

और

if (value > valueMax) 
    dummyValue = valueMax 
00E112ED mov   eax,dword ptr [valueMax] 
00E112F0 cmp   dword ptr [value],eax 
00E112F3 mov   ecx,dword ptr ds:[0E13038h] 
00E112F9 cmovg  esi,eax 

तो दोनों ही मामलों में या तो cmovge या cmovg निर्देश करने के लिए अनुकूलित।

मैं अभी भी std::min के साथ जाऊंगा क्योंकि यह if कथन से बेहतर इरादा दिखाता है। यह अनुकूलित है और यह और अधिक पठनीय है।

+0

जब आप सरल एल्गोरिदम के लिए चर के निरंतर मान प्रदान करते हैं जैसे न्यूनतम (जो अधिकांश समय में रेखांकित है)। कंपाइलर समय संकलित, न्यूनतम मूल्य पर पता लगा सकता है। वह लूप निष्पादित नहीं किया जाएगा ताकि आपको '0' मिल रहा हो। रन-टाइम पर न्यूनतम मूल्यों को उत्पन्न करने का प्रयास करें और आपको उचित माप मिलेगा। –

+0

किसी भी मामले में, आपका परीक्षण कई तरीकों से टूटा हुआ है। 1) यह वास्तव में कुछ भी नहीं करता है। तो संकलक उन लूप दोनों को अनुकूलित करने के लिए स्वतंत्र है। इसे लूप के परिणाम का उपयोग करके तय किया जा सकता है। 2) पूरे पहले लूप को 'dummyValue = 3001'' के लिए अनुकूलित किया जाएगा। और पूरे दूसरे लूप को 'value = 3001'' के लिए अनुकूलित किया जाएगा। – Mysticial

0

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

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