2015-03-19 5 views
5

Bei Objekten (insbesondere Zeichenketten) ist der Aufruf per Verweis schneller als call-by-value, da der Funktionsaufruf keine Kopie des ursprünglichen Objekts erstellen muss. Mit const kann auch sichergestellt werden, dass die Referenz nicht missbraucht wird.Ruft Const als Referenz die Performance auf, wenn sie auf primitive Typen angewendet wird?

Meine Frage ist, ob const call-by-reference auch schneller ist, wenn primitive Typen wie bool, int oder double verwendet werden.

void doSomething(const string & strInput, unsigned int iMode); 
void doSomething(const string & strInput, const unsigned int & iMode); 

Mein Verdacht ist, dass es von Vorteil ist Call-by-Referenz zu verwenden, sobald die primitive Größe des Typs in Bytes die Größe des Adresswert überschreitet. Auch wenn der Unterschied gering ist, würde ich gerne den Vorteil nutzen, da ich einige dieser Funktionen ziemlich oft nenne.

Zusätzliche Frage: Hat Inlining einen Einfluss auf die Antwort auf meine Frage?

+0

Die meiste Zeit sollte es keine Wirkung. Aber das Profiling für einen bestimmten Fall wäre gut. Ich übergebe primitive Typen nach Werten und Objekten durch const Referenz. Inlining sollte nichts ändern. –

+1

Es ist wichtig zu verstehen, dass sie nicht das Gleiche sind (siehe http://stackoverflow.com/questions/4705593/int-vs-const-int zB). Wählen Sie diejenige aus, die Ihren Anforderungen entspricht - wenn die Übergabe an einen Wert ausreichend ist, dann tun Sie dies - wenn eine Weitergabe als Referenz erforderlich ist, tun Sie dies. –

Antwort

2

Mein Verdacht ist, dass es vorteilhaft ist, sobald durch Verweis anruf zu verwenden, wie der primitiven Größe des Typs in Bytes die Größe des Adresswertes überschreitet. Auch wenn der Unterschied gering ist, würde ich gerne den Vorteil nutzen, da ich einige dieser Funktionen ziemlich oft nenne.

Performance-Optimierungen basierend auf Ahnungen arbeitet etwa 0% der Zeit in C++ (das ist ein Bauchgefühl ich über Statistiken haben, es funktioniert in der Regel ...)

Es ist richtig, dass die const T& sein kleiner als die T wenn sizeof(T) > sizeof(ptr), so in der Regel 32-Bit oder 64, je nach System ..

sich jetzt fragen:

1) Wie viele eingebauten Typen sind größer als 64 Bit?

2) Ist das Kopieren von 32 Bit nicht wert, den Code weniger klar zu machen? Wenn Ihre Funktion wesentlich schneller wird, weil Sie keinen 32-Bit-Wert darauf kopiert haben, tut das vielleicht nicht viel?

3) Bist du wirklich so schlau? (Spoileralarm: nein.) Sehen Sie diese großartige Antwort für den Grund, warum es fast immer eine schlechte Idee ist: https://stackoverflow.com/a/4705871/1098041

Letztendlich nur durch den Wert übergeben. Wenn Sie nach der (gründlichen) Profilerstellung feststellen, dass eine Funktion ein Engpass ist, und alle anderen Optimierungen, die Sie versucht haben, nicht genug waren (und Sie sollten die meisten davon schon einmal ausprobieren), pass-by-const-reference.

Dann sehen, dass es nichts ändert. Roll-Over und weinen.

0

wurde I gelehrt:

  • Pass nach Wert wenn ein Argumentvariable eine der grundlegenden integrierten Typen ist, wie bool, int oder float. Objekte dieser Art sind so klein, dass ein Referenzieren nicht zu einem Effizienzgewinn führt. Auch wenn Sie eine Kopie einer Variablen erstellen möchten.

  • Übergeben Sie eine Konstante Referenz, wenn Sie einen Wert effizient übergeben möchten, den Sie nicht ändern müssen.

  • Übergeben Sie eine Referenz nur, wenn Sie den Wert der Argumentvariablen ändern möchten. Aber um zu vermeiden, Argumentvariablen zu ändern, wann immer es möglich ist.

2

const ist ein Schlüsselwort, das bei compiletime ausgewertet wird. Es hat keinen Einfluss auf die Laufzeitleistung. Sie können hier diese etwas mehr über lesen: https://isocpp.org/wiki/faq/const-correctness

+0

const kann keinen negativen Einfluss auf die Leistung haben, da es sich um eine reine Kompilierungszeit handelt. Es kann sich jedoch immer noch positiv auf intelligente Compiler auswirken. – stefan

2

Auf einer 64-Bit-Architektur gibt es keinen primitiven Typ --- zumindest nicht in C++ 11 --- der größer ist als ein Zeiger/Verweis. Sie sollten dies testen, aber intuitiv sollte es die gleiche Menge an Daten geben, die für eine const T& wie für eine int64_t gemischt werden, und weniger für jedes Primitiv, bei dem sizeof(T) < sizeof(int64_t). Daher, soweit Sie einen Unterschied messen können, sollte die Übergabe von Primitiven nach Wert schneller sein wenn Ihr Compiler die offensichtliche Sache tut --- weshalb ich betonen, dass, wenn Sie Sicherheit hier brauchen, sollten Sie einen Testfall schreiben.

Eine weitere Überlegung ist, dass primitive Funktionsparameter in CPU-Registern landen können, was den Zugriff auf sie so schnell macht, wie ein Speicherzugriff möglich ist. Möglicherweise finden Sie mehr Anweisungen für Ihre const T& Parameter als für Ihre T Parameter generiert, wenn T ein primitiv ist. Sie könnten dies testen, indem Sie die Assembler-Ausgabe Ihres Compilers überprüfen.

3

Ich zusätzlich zu den anderen Antworten möchte ich darauf hinweisen, dass, wenn Sie eine Referenz übergeben und verwenden (auch als Dereferenzierung), dass viel in Ihrer Funktion, könnte es langsamer als das Erstellen einer Kopie.

Dies liegt daran, dass lokale Variablen für eine Funktion (normalerweise) zusammen in den Cache geladen werden, aber wenn einer von ihnen ein Zeiger/Verweis ist und die Funktion dies verwendet, könnte dies zu einem Cache-Miss führen. Das bedeutet, dass es in den (langsameren) Hauptspeicher gehen muss, um die Variable auf die Variable zu bringen, die langsamer sein könnte als die Kopie, die zusammen mit der Funktion in den Cache geladen wird.

Also selbst für 'kleine Objekte' könnte es möglicherweise schneller sein, nur nach Wert zu übergeben.

(Ich lese diese im sehr guten Buch: Computer Systems: a programmers perspective)

Einige weitere interessante Diskussion über den gesamten Cache-Hit/Miss-Thema: How does one write code that best utilizes the CPU cache to improve performance?

Verwandte Themen