2012-06-20 10 views
21

सी के लिए किया गया है प्रस्तावों ++ "प्रतिनिधियों" जो boost::function की तुलना में कम भूमि के ऊपर है:फास्ट डेलेगेट (एट अल) के पीछे विचारों का उपयोग std :: function को अनुकूलित करने के लिए किया गया है?

उन विचारों के किसी भी std::function लागू करने के लिए इस्तेमाल किया गया है, परिणामस्वरूप boost::function से बेहतर प्रदर्शन हुआ? क्या किसी ने std::function बनाम boost::function के प्रदर्शन की तुलना की है?

मैं जीसीसी संकलक और libstdC++ इंटेल 64-बिट आर्किटेक्चर पर के लिए विशेष रूप से इस जानना चाहते हैं, लेकिन अन्य compilers के बारे में जानकारी (जैसे बजना के रूप में) का स्वागत है।

+0

'std :: function' एक अंतरफलक, नहीं एक कार्यान्वयन है। आप कुलपति ++ के stdlib, libstdC++, या libC++ _specifically_ के बारे में पूछना चाहते हैं तो यह एक मान्य सवाल है, लेकिन जैसा कि-है आपके सवाल का दायरा बहुत अधिक व्यापक – ildjarn

+1

@ildjarn है: सवाल का अंतिम वाक्य पढ़ें। वह विशिष्ट कार्यान्वयन के बारे में पूछ रहा है, और सबसे विशेष रूप से libstdC++ के बारे में पूछ रहा है। – abarnert

+0

@abarnert: इसे पढ़ने के बिना मैं इसका जवाब कैसे दे सकता हूं? जाहिर है, मैंने इसे पढ़ा, और मुझे यह व्यापक रूप से व्यापक लगता है। – ildjarn

उत्तर

28

libstdC++ के std::function में हम एक यूनियन प्रकार का उपयोग करते हैं जो उचित रूप से आकार और प्वाइंटर्स, फ़ंक्शन पॉइंटर्स या पॉइंटर्स को सदस्य कार्यों में संग्रहीत करने के लिए गठबंधन किया जाता है। हम किसी भी समारोह उद्देश्य यह है कि कि आकार और संरेखण, लेकिन में संग्रहित किया जा सकता है के लिए एक ढेर आवंटन केवल अगर यह होता है "स्थान अपरिवर्तनीय"

/** 
* Trait identifying "location-invariant" types, meaning that the 
* address of the object (or any of its members) will not escape. 
* Also implies a trivial copy constructor and assignment operator. 
*/ 

कोड std::tr1::function कार्यान्वयन पर आधारित है और वह हिस्सा hasn 'से बचने टी महत्वपूर्ण रूप से बदल गया। मुझे लगता है कि std::aligned_storage का उपयोग करके सरलीकृत किया जा सकता है और विशेषता को विशेषज्ञता देकर इसे बेहतर किया जा सकता है ताकि अधिक प्रकार के स्थान invariant के रूप में पहचाना जा सके।

लक्ष्य ऑब्जेक्ट को आमंत्रित करना किसी वर्चुअल फ़ंक्शन कॉल के बिना किया जाता है, टाइप एरर std::function में एक फ़ंक्शन पॉइंटर को संग्रहीत करके किया जाता है जो फ़ंक्शन टेम्पलेट विशेषज्ञता का पता होता है। सभी ऑपरेशन संग्रहीत सूचक के माध्यम से उस फ़ंक्शन टेम्पलेट को कॉल करके और एक enum में गुजरने के द्वारा किया जाता है यह पहचानने के लिए कहा जा रहा है कि कौन सा ऑपरेशन किया जा रहा है। इसका मतलब कोई vtable नहीं है और ऑब्जेक्ट में केवल एक ही फ़ंक्शन पॉइंटर को संग्रहीत करने की आवश्यकता है।

इस डिजाइन को मूल boost::function लेखक द्वारा योगदान दिया गया था और मेरा मानना ​​है कि यह बढ़ावा कार्यान्वयन के करीब है। बूस्ट के लिए Performance दस्तावेज़ देखें। कुछ तर्क के लिए समारोह। इसका मतलब है कि यह बहुत संभावना नहीं है कि जीसीसी का std::functionboost::function से भी तेज है, क्योंकि यह एक ही व्यक्ति द्वारा समान डिजाइन है।

एनबी। हमारे std::function अभी तक एक आवंटक के साथ निर्माण का समर्थन नहीं करता है, किसी भी आवंटन को करने की आवश्यकता है new का उपयोग करके किया जाएगा।


एमिल की टिप्पणी के जवाब में एक std::function जो सदस्य समारोह और एक वस्तु के लिए सूचक धारण के लिए एक ढेर आवंटन से बचने के लिए एक इच्छा व्यक्त, यहाँ यह करने के लिए एक छोटे से हैक है (लेकिन आप से यह नहीं सुना मुझे ;-)

struct A { 
    int i = 0; 
    int foo() const { return 0; } 
}; 

struct InvokeA 
{ 
    int operator()() const { return a->foo(); } 
    A* a; 
}; 

namespace std 
{ 
    template<> struct __is_location_invariant<InvokeA> 
    { static const bool value = true; }; 
} 

int main() 
{ 
    A a; 
    InvokeA inv{ &a }; 

    std::function<int()> f2(inv); 

    return f2(); 
} 

चाल कि InvokeA काफी छोटा function की छोटी सी वस्तु बफर में फिट करने के लिए है, और विशेषता विशेषज्ञता उस में वहाँ स्टोर करने के लिए सुरक्षित है कहते हैं, तो function कि की एक प्रति को धारण करता है ढेर पर नहीं, सीधे वस्तु।यह a की आवश्यकता है जब तक यह करने के लिए सूचक बनी रहती है लागू करने के लिए है, लेकिन स्थिति वैसे भी हो सकता है अगर function के लक्ष्य bind(&A::foo, &a) था।

+4

वाह, घोड़े के मुंह से स्ट्रेट! अगर मैंने इस अभिव्यक्ति 'std :: bind (& Object :: सदस्य फ़ंक्शन, ऑब्जेक्ट इंस्टेंस)' से 'std :: function'' बनाया है, तो क्या यह "स्थान invariant" के रूप में बन जाएगा? –

+0

यदि आप एक सूचक और एक enum पास करते हैं, तो मुझे लगता है कि कार्यान्वयन में कुछ प्रकार का 'स्विच' कथन है जो enum मूल्य के अनुसार स्विच करता है। क्या एनम का मूल्य स्थिर है जिसे संकलित समय पर हल किया जा सकता है? यदि नहीं, तो मुझे नहीं लगता कि यह एक vtable लुकअप से अधिक कुशल कैसे है। –

+4

नहीं, यह स्थान परिवर्तक नहीं होगा, क्योंकि उस बाइंड अभिव्यक्ति के परिणाम में आपके ऑब्जेक्ट की एक प्रति सदस्य फ़ंक्शन _and_ के सूचक होंगे! मैं संघ के आकार को बढ़ाने की योजना बना रहा हूं ताकि यह सदस्य और सूचक के लिए सूचक हो सके, ताकि 'बाध्य (और ओ :: एफ, और ओ)' ठीक रहेगा, लेकिन यह अपेक्षाकृत मुश्किल होगा। –

3

टिप्पणी, std :: समारोह में बताया गया है केवल एक इंटरफेस है, और विभिन्न कार्यान्वयन अलग अलग बातें कर सकते हैं, लेकिन यह ध्यान देने योग्य बात है कि मानक वास्तव में कुछ इस मामले के बारे में कहना है लायक है। से 20.8.11.2.1/5 (जो और अधिक मानक का एक हिस्सा से एक आईपी पता तरह दिखता है):

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

यह "छोटे समारोह अनुकूलन," जो प्रतिनिधियों पर उद्धृत लेख से प्रेरित हुआ रोजगार इसको लागू करने को प्रोत्साहित करने के मानक का तरीका है। (लेख खुद को वास्तव में नेट अर्थ में प्रतिनिधियों के बारे में बात नहीं करते। बल्कि, वे शब्द "प्रतिनिधि" का उपयोग बाध्य सदस्य कार्यों मतलब करने के लिए।)