2011-12-23 23 views
22

Ho appena provato a confrontare le prestazioni delle espressioni lambda in C++ 11, quindi ho eseguito la somma di elementi di prova di calcolo in un vettore di valori double. Ecco l'attuazione:Perché C + + lambda è più lento della funzione normale quando viene chiamato più volte?

#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; 
} 

Ecco il risultato di questo programma (compilato in VS2010 SP1, in modalità di rilascio):

 
iterator 
0.32 s 
out = 1e+008 

lambda 
0.326 s 
out = 1e+008 

Come si può vedere, non c'è praticamente alcuna differenza in termini di prestazioni. Tuttavia, se do 10 come valore di MAX (significa somma verrà eseguita 10 volte invece di uno), risultati differiscono:

 
iterator 
0.287 s 
out = 1e+009 

lambda 
2.84 s 
out = 1e+009 

del test per l'espressione lambda voluti circa 10 volte più tempo. Perché? Ho pensato che potrebbe essere causato dal fatto, che su ogni iterazione nuova lambda si crea, ma stuzzicare ho provato questo:

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); 

i risultati non erano cambiate. Qualcuno potrebbe spiegarmi questo comportamento?

+2

Questo è molto intrigante! Potresti provare a usare lambda in un ciclo scritto a mano invece di 'foreach'? – dasblinkenlight

+0

g ++ 4.6.2 su linux fornisce tempi di esecuzione esattamente identici (0.13 - 0.12 s sul mio computer) – Cubbi

+0

Non più mistero, controlla la mia modifica. Il mio errore, ma lo trovo piuttosto interessante. :) – Archie

risposta

39

Si è scoperto che questo non è un problema con le espressioni lambda, solo il compilatore ha ottimizzato il ciclo esterno nel primo caso memorizzando nella cache il risultato della funzione sum(). cambiare dopo il primo caso di questa forma:

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 
} 

entrambi i casi temporizzazioni sono approssimativamente uguali, con lambda come preferito.

+9

Bella inchiesta. –

+3

E la morale della storia: test e benchmark sempre con codice * real *, mai con il codice * toy *. –

+2

@Archie Hai aggiunto anche la v [i] = 1.0 alla lambda? – sprite

Problemi correlati