2012-01-26 15 views
12

मैं एक टेम्पलेट समारोह है कि एक std::stack<T> के साथ कुछ और T का एक उदाहरण है, उदाहरण के लिए लिखना चाहते हैं:क्या एक अच्छा सी ++ संकलक एक संदर्भ को अनुकूलित करेगा?

template<class StackType> inline 
bool some_func(StackType const &s, typename StackType::value_type const &v) { 
    // ... 
} 

कारण मैं संदर्भ द्वारा v पारित मामले के लिए अनुकूलन करने के लिए जहां StackType::value_type एक struct है निश्चित रूप से है या class और मूल्य से एक संपूर्ण वस्तु की प्रतिलिपि बनाएँ।

हालांकि, StackType::value_typeint जैसे "सरल" प्रकार है, तो यह निश्चित रूप से इसे मूल्य से पारित करने के लिए बेहतर है।

प्रश्न यह है: int जैसे एक प्रकार के लिए जो ऊपर दिए गए फ़ंक्शन में औपचारिक तर्क के रूप में int const& बन जाएगा, क्या संकलक संदर्भ को अनुकूलित कर देगा और इसे केवल मूल्य से पास करेगा?

+2

यह एक बुरा संकलक होगा करता है। – lapk

+0

यदि संकलक वास्तव में फ़ंक्शन को इनलाइन करने का निर्णय लेता है, तो यह निश्चित रूप से सबसे प्रभावी चीज़ करेगा, भले ही आप इसे कैसे परिभाषित करते हैं। – enobayram

उत्तर

6

हालांकि मैं वास्तव में इस के लिए किसी भी compilers परीक्षण नहीं किया है, मैं यह संदेह है। आप मानते हैं कि एक कॉन्स संदर्भ पास करने से केवल एक मूल्य पारित करने से अलग नहीं है, लेकिन यह सच नहीं है, और संकलक को यह नहीं मानना ​​चाहिए कि यह है।

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

कुछ को संशोधित करता है कि मूल चर, अपने कार्य, अपने संदर्भ के साथ, नए मूल्य देखने चाहिए। यदि संकलक ने एक प्रतिलिपि के साथ संदर्भ को प्रतिस्थापित किया है, तो फ़ंक्शन अभी भी पुराना मान देखेगा।

आपको बूस्ट का call traits पुस्तकालय में रुचि रखते हैं, हालांकि हो सकता है। यह एक टेम्पलेट प्रकार call_traits<T>::param_type जो "बड़ी" प्रकार है कि आप कॉपी नहीं करना चाहती के लिए एक स्थिरांक संदर्भ, और "छोटे" प्रकार जहां एक प्रति और अधिक कुशल हो जाएगा के लिए एक मूल्य है प्रदान करता है। असल में, आप संकलक को पूरी तरह से करने के लिए क्या चाहते हैं, आप स्पष्ट रूप से अपने कोड के साथ कर सकते हैं।

+3

आप धागे के बारे में सही नहीं हैं। कंपाइलर ऑप्टिमाइज़र अक्सर कोड को तोड़ता है जो खराब "लॉक-फ्री" (बेवकूफ) डेटा संरचनाओं के साथ काम करता है। कंपाइलर को अन्य धागे के बारे में सोचना चाहिए! –

+0

इसके अलावा, सरल फ़ंक्शंस अन्य कार्यों को सभी –

+0

@AlexandrPriymak पर कॉल नहीं करते हैं, प्रश्न यह नहीं बताता कि फ़ंक्शन में कौन सा कोड है, इसलिए यह एक ऐसा हो सकता है जो अन्य कार्यों को कॉल करता हो। और सी ++ 11 में एक समवर्ती-जागरूक स्मृति मॉडल और मानकीकृत थ्रेडिंग सुविधाएं शामिल हैं, इसलिए सी ++ 11 कंपाइलर को यह समझना चाहिए कि सी ++ 98 कंपाइलर नहीं होने पर भी अन्य धागे क्या कर सकते हैं। – Wyzard

6

जब भी संकलक इनलाइन करने में सक्षम है, जिसके परिणामस्वरूप पार प्रक्रियात्मक अनुकूलन खोजने और एक पते गुजर की कीमत को खत्म होगा।

गैर-इनलाइन-सक्षम फ़ंक्शन कॉल के लिए, संदर्भ संभवतः एक सूचक के रूप में लागू किया जाएगा, पास-दर-मूल्य नहीं।

3

यह MSVC2010 64 बिट संकलक, पूर्ण अनुकूलन है: - पता RCX पर पारित

int foo(int i) 
{ 
int a = i + i; 

return (a); 
} 
//Disassembly: 
//00000001`3ff11c50 8d0409   lea  eax,[rcx+rcx] 
//00000001`3ff11c53 c3    ret 

int bar(int const & i) 
{ 
int a = i + i; 

return (a); 
} 
//Disassembly: 
//00000001`3ff11c10 8b01   mov  eax,dword ptr [rcx] 
//00000001`3ff11c12 03c0   add  eax,eax 
//00000001`3ff11c14 c3    ret 

पहले मामले में, मूल्य दूसरे में RCX पारित हो जाता है,। बेशक, अगर कार्यों को रेखांकित किया गया है, जैसा कि बेन ने कहा था, तो उत्पादित कोड दोनों मामलों में बिल्कुल समान हो सकता है।

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

template< typename PType > 
PType Func(typename std::enable_if< (sizeof(PType) > sizeof(size_t)), PType const & >::type f) 
{ 
//large things: reference 
} 

template< typename PType > 
PType Func(typename std::enable_if< (sizeof(PType) <= sizeof(size_t)), PType >::type f) 
{ 
//small things: value 
} 
+1

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

+0

@ ब्रुक्समोस फ़ंक्शन इनलाइनिंग यह टेम्पलेट या गैर-टेम्पलेट फ़ंक्शन पर निर्भर नहीं है। बस तथ्य यह है कि प्रत्येक ने प्रत्येक संकलन इकाई में टेम्पलेट की परिभाषा को टेम्पलेट किया है, इसका उपयोग इसकी इनलाइनिंग की गारंटी नहीं देता है ... यदि मेरे "प्रयोगात्मक" कार्यों को एक संकलन इकाई में एक साथ घोषित और परिभाषित किया गया है, तो उन्हें रेखांकित किया जाएगा। और कोड वही होगा। और दूसरी तरफ, यहां तक ​​कि "सरल" टेम्पलेट किए गए कार्यों को भी रेखांकित नहीं किया जा सकता है। – lapk

+0

हां, मैंने oversimplified। फिर भी, यदि आपके "प्रयोगात्मक" कार्यों को एक संकलन इकाई में घोषित और परिभाषित किया गया है, लेकिन इस तरह से घोषित किया जाता है कि उन्हें उस कार्यात्मक इकाई से निर्यात किया जाता है, तो उन्हें रेखांकित नहीं किया जा सकता है। और आपने कोई संकेत नहीं दिया कि वे या तो स्थैतिक थे या आप एक आत्मनिर्भर पूरे कार्यक्रम को संकलित कर रहे थे, जिसका अर्थ है कि उन्हें जरूरी रूप से निर्यात किया गया था। –

6

मैं जीसीसी अनुकूलन विकल्प यहाँ http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

में देखने के लिए और वास्तव में अपने मामले के लिए एक विकल्प है:

-fipa-एसआरए

interprocedural अदिश प्रदर्शन समेकन के प्रतिस्थापन, अप्रयुक्त पैरामीटर को हटाने और मूल्य द्वारा पारित पैरामीटर द्वारा संदर्भ द्वारा पारित पैरामीटर के प्रतिस्थापन।

स्तरों -O2, -O3 और -Os

जहाँ तक मुझे पता है, -O2 लिनक्स पर रिलीज निर्माण के लिए सामान्य विकल्प है पर सक्षम किया गया।

तो, कम जवाब है: अच्छा संकलक से एक

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