2011-12-23 10 views
22

मैंने सी ++ 11 में लैम्ब्डा अभिव्यक्तियों के प्रदर्शन की तुलना करने की कोशिश की है, इसलिए मैंने double मानों के वेक्टर में तत्वों का परीक्षण - गणना योग किया है।क्यों कई बार बुलाए जाने पर सामान्य कार्य से सी ++ लैम्ब्डा धीमा है?

#include <vector> 
#include <algorithm> 
#include <iostream> 
#include <ctime> 

#define LOG(x) { std::cout << #x << " = " << (x) << "\n"; } 
#define TIME(t) { std::cout << ((double)(clock() - (t))/CLOCKS_PER_SEC) << " s\n"; } 

double sum(const std::vector<double>& v) 
{ 
    double s = 0.0; 
    for (auto i = v.cbegin(); i != v.cend(); ++i) 
     s += *i; 
    return s; 
} 

int main() 
{ 
    const size_t MAX = 1; // number of tests 
    const size_t SIZE = 100000000; // length of the vector 

    std::vector<double> v(SIZE, 1.0); 
    double out; 

    clock_t clk; 

    std::cout << "iterator\n"; 

    clk = clock(); 
    out = 0.0; 
    for (size_t i = 0; i < MAX; ++i) 
     out += sum(v); 
    TIME(clk) 
    LOG(out) 

    std::cout << "\nlambda\n"; 

    clk = clock(); 
    out = 0.0; 
    for (size_t i = 0; i < MAX; ++i) 
     std::for_each(v.cbegin(), v.cend(), [&](double d) { out += d; }); 
    TIME(clk) 
    LOG(out) 

    return 0; 
} 

यहाँ (रिलीज़ मोड में, VS2010 SP1 में संकलित) इस कार्यक्रम का परिणाम है::

 
iterator 
0.32 s 
out = 1e+008 

lambda 
0.326 s 
out = 1e+008 

एक दिखाई दे सकता हैं, वहाँ व्यावहारिक रूप से प्रदर्शन में कोई अंतर नहीं है यहाँ कार्यान्वयन है। हालांकि, अगर मैं MAX के मूल्य के रूप में 10 देना (इसका मतलब है कि योग एक के बजाय 10 बार प्रदर्शन किया जाएगा), परिणाम अलग: लैम्ब्डा अभिव्यक्ति के लिए

 
iterator 
0.287 s 
out = 1e+009 

lambda 
2.84 s 
out = 1e+009 

टेस्ट लगभग 10 गुना अधिक समय लगा। क्यूं कर? मैंने सोचा कि यह इस तथ्य के कारण हो सकता है कि हर यात्रा नई लैम्ब्डा पर बनाई गई है, लेकिन तेज करना मैं इस कोशिश की:

out = 0.0; 
auto f = [&](double d) { out += d; }; 
for (size_t i = 0; i < MAX; ++i) 
    std::for_each(v.cbegin(), v.cend(), f); 

परिणाम नहीं बदले हैं। क्या कोई मुझे उस व्यवहार को समझा सकता है?

+2

यह बहुत ही दिलचस्प है! क्या आप 'foreach' के बजाय हाथ से लिखित लूप में लैम्ब्डा का उपयोग करने का प्रयास कर सकते हैं? – dasblinkenlight

+0

जी ++ 4.6.2 लिनक्स पर बिल्कुल समान रन टाइम (0.13 - 0.12 एस मेरे कंप्यूटर पर) देता है – Cubbi

+0

कोई और मिस्टर नहीं, मेरा संपादन देखें। मेरी गलती, लेकिन फिर भी मुझे यह बहुत दिलचस्प लगता है। :) – Archie

उत्तर

39

यह पता चला कि यह लैम्ब्डा अभिव्यक्तियों के साथ कोई मुद्दा नहीं है, केवल संकलक sum() फ़ंक्शन के परिणाम को कैश करके पहले मामले में बाहरी लूप को ऑप्टिमाइज़ किया गया है। इसके बाद फार्म के लिए पहला मामला बदलने के लिए:

out = 0.0; 
for (size_t i = 0; i < MAX; ++i) 
{ 
    out += sum(v); 
    v[i] = 1.0; // this adds O(1) time and prevents caching 
} 

दोनों ही मामलों समय लगभग बराबर हैं, एक पसंदीदा के रूप में लैम्ब्डा के साथ।

+9

अच्छी जांच। –

+3

और कहानी का नैतिक - हमेशा * वास्तविक * कोड के साथ परीक्षण और बेंचमार्क, कभी * खिलौना * कोड के साथ। –

+2

@Achieची क्या आपने भी v [i] = 1.0 को लैम्ब्डा में भी जोड़ा था? – sprite

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