2013-04-10 6 views
31

Kann/funktioniert der Compiler inline Lambda-Funktionen zur Steigerung der Effizienz, wie es mit einfachen Standardfunktionen möglich ist?Sind lambdas wie in C++ inlined?

z.B.

std::vector<double> vd; 
std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;}); 

Oder gibt es einen Effizienzverlust aufgrund fehlender Optimierung?

Eine zweite Frage: wo kann ich überprüfen, ob der Compiler, den ich verwende, Aufrufe von Inline-Funktionen optimiert hat, die an einen Algorithmus gesendet werden? Was ich meine ist, wenn eine Funktion - kein Funktionsobjekt - an einen Algorithmus gesendet wird, erhält der letzte einen Zeiger auf die Funktion, und einige Compiler optimieren Zeiger auf Inline-Funktionen und andere nicht.

+4

Einige sind optimiert, manche nicht, wie jeder Funktionsaufruf. Wenn Sie an einem bestimmten Aufruf interessiert sind, müssen Sie überprüfen, was Ihr bestimmter Compiler mit diesem bestimmten Aufruf macht. –

+2

Sie verwirren Konzepte hier. Alle Lambdas sind Inline. Nicht alle Anrufe an sie sind notwendigerweise inline. –

+0

Ich glaube nicht, dass ein Lambda inline sein kann, wenn es an eine externe Funktion übergeben wird. – nobar

Antwort

26

In einfachen Fällen wie Ihr Beispiel Sie eine bessere Leistung mit Lambda-Ausdrücke als mit Funktionszeiger erwarten sollten, sehen

Why can lambdas be better optimized by the compiler than plain functions?

Wie andere haben bereits darauf hingewiesen, gibt es keine Garantie, dass Ihr Anruf wird inline sein, aber Sie haben bessere Chancen mit Lambdas. Eine Möglichkeit, zu überprüfen, ob der Anruf inline ausgeführt wurde, besteht darin, den generierten Code zu prüfen. Wenn Sie gcc verwenden, übergeben Sie das -S Flag an den Compiler. Natürlich wird davon ausgegangen, dass Sie den Assemblercode verstehen können.

+21

Jeder kann Assembler-Code lesen, die Frage ist, ob Sie es verstehen können. – Bolpat

+3

Anonyme downvotes helfen niemandem. Was ist falsch an der Frage? – Ali

17

Zunächst einmal: Der ganze Sinn des Entwurfs von Lambdas in C++ ist, dass sie keinen Overhead im Vergleich zu Funktionsaufrufen haben. Dazu gehört insbesondere, dass Anrufe an sie getätigt werden können.

Aber es gibt eine Verwirrung der Begriffe hier: „inline“ ist die Verknüpfung einer Funktion, das heißt, es eine Aussage darüber, wie eine Funktion ist definiert, nicht, wie es genannt wird. Aber Funktionen, die inline definiert sind, können profitieren von einer Compiler-Optimierung, durch die Aufrufe an solche Funktionen inline sind. Es sind andere, aber sehr verwandte Konzepte.

Jetzt im Fall von Lambdas ist die tatsächliche Funktion eine operator(), die Inline in einer anonymen Klasse definiert ist. Direkte Anrufe des Lambdas sind direkte Anrufe zu seinem operator() und können daher inline sein.

11

Es hängt von der Optimierungsstufe ab, die dem Compiler zugewiesen wird. Nehmen Sie zum Beispiel diese beiden Funktionen, die semantisch identisch sind. Einer ist C++ 11-Stil, der andere C-Stil.

void foo1 (void) 
{ 
    int arr[100]; 
    std::generate(std::begin(arr), std::end(arr), [](){return std::rand()%100;}); 
} 

void foo2 (void) 
{ 
    int arr[100]; 
    for (int *i = arr; i < arr+100; i++) *i = std::rand()%100; 
} 

Zusammenstellung dieses mit gcc -O4 aussendet Code, der sehr ähnlich ist (nicht identisch, aber äquivalente Komplexität) für die beiden Funktionen.

Allerdings ist das Lambda beim Kompilieren nicht optimiert (und auch die Aufrufe std :: begin und std :: end nicht).

Also, obwohl der Compiler eine hervorragende Arbeit bei der Optimierung des modernen Stilcodes leisten kann (und tut), wenn es dazu aufgefordert wird, gibt es möglicherweise oder wahrscheinlich eine Leistungseinbuße für diese Art von Code in einem nicht optimierten Debug-Build .

+9

Es gibt übrigens kein "-O4" in gcc. – DrYak

+8

@DrYak Ich kompiliere immer mit "-O9999" weil ich den [limit-breaker] (http://finalfantasy.wikia.com/wiki/Break_Damage_Limit) noch nicht gefunden habe ... Natürlich scherze ich. Technisch bedeutet alles über "-O3" "-O3". –

Verwandte Themen