Lambda-Optimierung und Inline-Funktionen: Der Vorteil des Compilers
Die Aussage von Nicolai Josuttis, dass Lambdas im Vergleich zu einfachen Funktionen eine überlegene Compiler-Optimierung aufweisen, hat viele fasziniert Entwickler. Bei der Untersuchung dieser Behauptung versuchen wir, die zugrunde liegenden Gründe für diesen Optimierungsvorteil aufzudecken.
Funktionsobjekte und Inlining
Lambdas, die Funktionsobjekte sind, haben einen entscheidenden Vorteil: sie an weiterzugeben Funktionsvorlagen lösen die Instanziierung einer maßgeschneiderten Funktion speziell für dieses Lambda aus. Dadurch kann der Compiler den Lambda-Aufruf mühelos einbinden.
Im Gegensatz dazu verwenden Funktionen Funktionszeiger, wenn sie an Funktionsvorlagen übergeben werden. Traditionell stoßen Compiler auf Herausforderungen beim Inlining von Aufrufen über Funktionszeiger. Eine Inline-Optimierung ist nur möglich, wenn die einschließende Funktion selbst inline ist.
Vorlageninstanziierungen: Den Unterschied erkunden
Um diese Ungleichheit zu veranschaulichen, betrachten Sie die Map-Funktionsvorlage:
templatevoid map(Iter begin, Iter end, F f) { for (; begin != end; begin) *begin = f(*begin); }
Aufruf mit einem Lambda:
int a[] = { 1, 2, 3, 4 }; map(begin(a), end(a), [](int n) { return n * 2; });
führt zu einer benutzerdefinierten Instanziierung:
template void map(int* begin, int* end, _some_lambda_type f) { for (; begin != end; begin) *begin = f.operator()(*begin); }
Der Compiler identifiziert die Funktion _some_lambda_type::operator() und kann sie direkt inline aufrufen. Jeder einzelne Lambda-Typ führt zu einer neuen Instanziierung der Karte und garantiert so eine Lambda-spezifische Optimierung.
Im Gegensatz dazu führt der Aufruf von Map mit einem Funktionszeiger zur folgenden Instanziierung:
template void map(int* begin, int* end, int (*f)(int)) { for (; begin != end; begin) *begin = f(*begin); }
Hier zeigt der Funktionszeiger f auf unterschiedliche Adressen für jeden Kartenaufruf, was eine Inline-Optimierung verhindert. Der Aufruf von „map“ muss inline erfolgen, damit der Compiler f in eine bestimmte Funktion auflösen kann.
Die Besonderheit von Lambdas als Funktionsobjekte und ihre Fähigkeit, Vorlageninstanziierungen zu erleichtern, ermöglichen Compilern daher größere Optimierungsmöglichkeiten als herkömmliche Funktionsaufrufe durch Zeiger.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3