wake-up-neo.com

Sind Funktoren tatsächlich schneller als Zeiger auf Funktionen?

Laut Scott Meyers ist ein Bereich, in dem C++ über C scheint, dass Funktionsobjekte schneller sind als Funktionszeiger. Er sagt, das liegt daran, dass Funktionsobjekte inline sind, was die Geschwindigkeit erhöht.

Ich habe zwei Fragen dazu:

  1. Wie können wir überprüfen, ob Funktionsobjekte tatsächlich inline sind? Können wir das in der Praxis überprüfen?

  2. Hängt das Inlining von Funktionsobjekten von dem Compiler ab, den wir verwenden, oder verhalten sich alle Compiler so?

58
user7140484

Die Standards C++ und C lassen den Compilern einige Freiheiten. Es steht den Compilern frei, zwischen jeder Anweisung bis zu 1 Milliarde zu zählen, oder dies nur dann, wenn eine Ganzzahl einen Primwert enthält.

Anständige "echte" Compiler machen das nicht. Dies ist eine Frage der Qualität der Implementierung.

Das Inlinen von Funktionsobjekten in etwas wie std::sort Ist etwas, das jeder echte Compiler tut. In diesen Fällen ist es außerordentlich einfach zu erkennen, was inline gesetzt werden muss, da die Typinformationen den Code enthalten, der inline gesetzt werden muss.

Dies mit einem Funktionszeiger zu tun, ist schwieriger. Dies mit einem Funktionszeiger zu tun, bei dem alles in void* Oder char* Zeiger konvertiert wurde, ist noch schwieriger.

Dies hat zur Folge, dass in der Praxis ein C-Style-Aufruf von qsort gegenüber einem C++ - Style-Aufruf von std::sort Zu einem großen Vorteil für std::sort Führen kann.

qsort ist ungefähr 2x langsamer als std::sort, wie gezeigt hier , in einer lächerlich einfachen Situation, in der zufällig angeordnete ganze Zahlen sortiert werden.

Das Überprüfen der tatsächlichen Assembly-Code-Ausgabe ist hauptsächlich ein Detail, und es ist eine Menge Arbeit für wenig Rendite. Anhand konkreter Beispiele aus der Praxis können Sie sich ein Bild davon machen, wie groß die Auswirkungen tatsächlich sind.

Alle 3 von clang, gcc und MSVC waren in der Lage, std::sort Deutlich schneller als ihr qsort zu machen. Und da dies eine einfache Optimierung ist, während das Optimieren von Funktionszeigern in Inline-Aufrufen nicht möglich ist, würden Sie erwarten, dass weniger wichtige Compiler bei qsort nicht besser sind als dies.

  1. Wie können wir überprüfen, ob Funktionsobjekte tatsächlich inline sind? Können wir das in der Praxis überprüfen?

Überprüfen Sie den endgültig ausgegebenen Assembler-Code.

  1. Die Inlining-Funktionsobjekte hängen von dem Compiler ab, den wir verwenden, oder verhalten sich alle Compiler so?

Dies hängt stark von der Implementierung des Compilers und der verwendeten Optimierungsstufe ab.
Also nein, es gibt keine Garantie, dass sich bestimmte Compiler (Linker) so verhalten.

Aufrufe über Funktionszeiger können jedoch nicht eingebunden werden.


Ihm zufolge werden Funktionsobjekte inliniert, so dass sich die Geschwindigkeit erhöht.

IMO "Funktionsobjekte sind inline" sollte besser gelesen werden (oder gehört werden, ich weiß nicht, woher diese Referenz stammt):

funktionsobjekte können inline gesetzt werden während Aufrufe durch Funktionszeiger dies nicht können.

18

Ja, Funktionsobjekte können zu schnellerem Code führen. Der einzige Weg, dies sicherzustellen, ist ein Benchmarking.

  1. Die Dokumentation sagt: " GCC kann eine Funktion aus vielen Gründen möglicherweise immer noch nicht einbinden; die -Winline Option kann verwendet werden, um festzustellen, ob eine Funktion nicht eingebunden wurde und warum nicht. "

  2. Natürlich hängt es von Compiler, Version, Flags usw. ab. Manchmal kann Inlining kontraproduktiv sein (Aufblähen von Code usw.), sodass jeder Compiler seine eigenen Regeln hat, um zu entscheiden, ob eine Funktion inliniert werden soll. Übrigens ist das Schlüsselwort inline nur ein Hinweis, und einige Bibliotheken wie eigen haben Schwierigkeiten, Inlining durchzusetzen.

1
YvesgereY