2008-09-30 23 views
26

विजुअल स्टूडियो में __forceinline के लिए समर्थन शामिल है। माइक्रोसॉफ्ट विजुअल स्टूडियो 2005 प्रलेखन राज्यों:मुझे इनलाइन के बजाय __forceinline का उपयोग कब करना चाहिए?

__forceinline कीवर्ड ओवरराइड करता है लागत/लाभ विश्लेषण और प्रोग्रामर बजाय फैसले पर निर्भर करता है।

यह सवाल उठाता है: कंपाइलर की लागत/लाभ विश्लेषण गलत कब होता है? और, मुझे कैसे पता होना चाहिए कि यह गलत है?

यह किस परिदृश्य में माना जाता है कि मैं इस मुद्दे पर अपने कंपाइलर से बेहतर जानता हूं?

उत्तर

14

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

अधिक बार नहीं है, हालांकि से

, मेरे अनुभव में, alogorithms में सुधार करने के लिए सीधे कोड अनुकूलन की तुलना में बेहतर परिणाम देता है।

5

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

35

आप केवल संकलक से बेहतर जानते हैं जब आपका प्रोफाइलिंग डेटा आपको बताता है।

+1

शीर्ष जवाब होना चाहिए के लिए;) – aaronsnoswell

1

ऐसी कई स्थितियां हैं जहां संकलक स्पष्ट रूप से निर्धारित करने में सक्षम नहीं है कि यह एक फ़ंक्शन को इनलाइन करने के लिए उचित या फायदेमंद है या नहीं। इनलाइनिंग में व्यापार-बंद शामिल हो सकता है कि संकलक बनाने के लिए तैयार नहीं है, लेकिन आप (उदा।, कोड ब्लोट) हैं।

सामान्य रूप से, आधुनिक संकलक वास्तव में इस निर्णय को करने में बहुत अच्छे हैं।

8

मैं 9 साल या ऐसा करने के लिए सीमित संसाधन उपकरणों के लिए सॉफ्टवेयर विकसित किया है और केवल समय मैंने कभी __forceinline एक तंग पाश जहां एक कैमरा चालक एक से पिक्सेल डेटा कॉपी करने की जरूरत में था उपयोग करने की आवश्यकता को देखा है डिवाइस स्क्रीन पर बफर कैप्चर करें। वहाँ हम स्पष्ट रूप से देख सकते हैं कि एक विशेष समारोह कॉल की लागत वास्तव में ओवरले प्रदर्शन ड्राइंग hogged।

29

एक ही स्थान पर मैं इसे उपयोग कर रहा हूँ लाइसेंस सत्यापन है।

एक महत्वपूर्ण कारक के खिलाफ की रक्षा करने के लिए आसान * खुर के बजाय कई स्थानों केवल एक में लाइसेंस प्राप्त किया जा रहा सत्यापित करने के लिए, और आप इन स्थानों में एक ही समारोह कॉल होने के लिए नहीं करना चाहती है।


*) कृपया इसे इस चर्चा में न करें कि सब कुछ क्रैक किया जा सकता है - मुझे पता है। इसके अलावा, इस अकेले ज्यादा मदद नहीं करता है।

+2

+1, चालाक सोच और एक विचार मैं उधार ले जाएगा। –

+0

मैं उसी कारण से __foceinline का उपयोग करने की योजना बना रहा हूं। क्या आप 100% हो सकते हैं कि यह __forceinline का उपयोग करते समय रेखांकित किया जाएगा। मुझे संदेह है क्योंकि एमएसडीएन यह भी कहता है: "आप कंपाइलर को किसी विशेष फ़ंक्शन को इनलाइन करने के लिए मजबूर नहीं कर सकते हैं, यहां तक ​​कि __forceinline कीवर्ड के साथ भी।" – mentat

+0

@ कोरे: आपको जेनरेट कोड की जांच करनी चाहिए। मेरे अनुभव में, हाँ, टीआई विशाल कार्यों के लिए भी काम करता है। एक अपवाद (आईआईआरसी) परिवर्तनीय तर्कों के साथ कार्य करता है, और यह संभव है कि दस्तावेज उस संदर्भ को संदर्भित करता है। – peterchen

3

इनलाइन निर्देश पूरी तरह से जब कार्य करता है जो कर रहे हैं के लिए इस्तेमाल किया किसी काम का नहीं होगा:

पुनरावर्ती, लंबे, छोरों से बना,

आप इस निर्णय का उपयोग कर के लिए मजबूर करना चाहते हैं __forceinline

1

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

3

वास्तव में, यहां तक ​​कि __forceinline कीवर्ड के साथ भी। दृश्य सी ++ कभी-कभी कोड को इनलाइन करने का विकल्प नहीं चुनता है। (स्रोत:। परिणामस्वरूप विधानसभा स्रोत कोड)

हमेशा (जैसे तंग भीतरी प्रत्येक फ्रेम पर चलाया जा करने के लिए आवश्यक छोरों के रूप में) जिसके परिणामस्वरूप विधानसभा कोड जहां गति महत्वपूर्ण है को देखो।

कभी कभी इनलाइन के बजाय #define का उपयोग कर चाल करेंगे। (निश्चित रूप से आप #define का उपयोग करके बहुत सारी जांच खो देते हैं, इसलिए इसे केवल तभी उपयोग करें जब यह वास्तव में मायने रखता है)।

+2

वास्तव में, असेंबलर को जांचने की कोई आवश्यकता नहीं है (ऐसा नहीं कि यह बहुत अधिक दर्द होता है)। वीएस में एक [चेतावनी है - सी 4714] (http://msdn.microsoft.com/en-us/library/a98sb923%28v=vs.110%29.aspx)। –

0

वास्तव में, इसके साथ बूस्ट लोड किया जाता है।

उदाहरण

BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_RV_REF(flat_tree) x) 
    BOOST_NOEXCEPT_IF((allocator_traits_type::propagate_on_container_move_assignment::value || 
         allocator_traits_type::is_always_equal::value) && 
         boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) 
{ m_data = boost::move(x.m_data); return *this; } 

BOOST_CONTAINER_FORCEINLINE const value_compare &priv_value_comp() const 
{ return static_cast<const value_compare &>(this->m_data); } 

BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp() 
{ return static_cast<value_compare &>(this->m_data); } 

BOOST_CONTAINER_FORCEINLINE const key_compare &priv_key_comp() const 
{ return this->priv_value_comp().get_comp(); } 

BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp() 
{ return this->priv_value_comp().get_comp(); } 

public: 
// accessors: 
BOOST_CONTAINER_FORCEINLINE Compare key_comp() const 
{ return this->m_data.get_comp(); } 

BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const 
{ return this->m_data; } 

BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const 
{ return this->m_data.m_vect.get_allocator(); } 

BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const 
{ return this->m_data.m_vect.get_stored_allocator(); } 

BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() 
{ return this->m_data.m_vect.get_stored_allocator(); } 

BOOST_CONTAINER_FORCEINLINE iterator begin() 
{ return this->m_data.m_vect.begin(); } 

BOOST_CONTAINER_FORCEINLINE const_iterator begin() const 
{ return this->cbegin(); } 

BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const 
{ return this->m_data.m_vect.begin(); } 
संबंधित मुद्दे