2012-05-04 21 views
5

Wenn ich auto_ptr als Rückgabewert einer Funktion, die große Vektoren auffüllt, verwendet, macht dies die Funktion eine Quelle Funktion (es wird eine interne Auto_ptr erstellen und Übergabe übergeben, wenn es ein Non zurückgibt) const auto_ptr). Ich kann diese Funktion jedoch nicht mit STL-Algorithmen verwenden, da ich für den Zugriff auf die Daten auto_ptr ignorieren muss. Ein gutes Beispiel wäre ein Feld von Vektoren der Größe N, wobei jeder Vektor 100 Komponenten hat. Ob die Funktion jeden 100-Komponenten-Vektor nach Wert oder ref zurückgibt, ist nicht der gleiche, wenn N groß ist.Rückgabewertoptimierung vs auto_ptr für große Vektoren

Auch wenn ich diesen sehr grundlegenden Code versuchen:

class t 
{ 
    public: 
     t() { std::cout << "ctor" << std::endl; } 
     ~t() { std::cout << "dtor" << std::endl; } 
}; 

t valueFun() 
{ 
    return t(); 
} 

std::auto_ptr<t> autoFun() 
{ 
    return std::auto_ptr(new t()); 
} 

beide autoFun und Spaß Anrufe führen mit dem Ausgang

Ctor Dtor

so kann ich nicht wirklich die automatische Variable sehen, welche wird erstellt, um an die return-Anweisung weitergegeben zu werden. Bedeutet dies, dass die Rückgabewert-Optimierung für den Aufruf wertFunktion gesetzt ist? Erzeugt ValueFun in diesem Fall überhaupt zwei automatische Objekte?

Wie optimiere ich dann eine Population von solch einer großen Datenstruktur mit einer Funktion?

+0

Fragen Sie, ob RVO auch für Ihre großen Vektoren funktioniert? Wenn ja, kannst du es nicht einfach mit einem Beispiel wie oben testen? – juanchopanza

+0

Wenn ich es teste, heißt das, dass es für alle Compiler/Plattformen funktioniert? Woher weiß ich, dass RVO überhaupt enthalten ist, sollte ich die Compiler-Spezifikationen lesen? Was passiert, wenn der Code in einem HPC-Cluster mit einem anderen Compiler kompiliert wird und die Bibliothek groß ist? – tmaric

+0

Ja, ich verstehe deinen Standpunkt. Es ist eines dieser Dinge, die der Compiler erlaubt, aber nicht benötigt, so dass Sie nie sicher sein können. BTW haben Sie C++ 11 Unterstützung? – juanchopanza

Antwort

4

es gibt Optionen dafür und dynamische Zuordnung möglicherweise nicht die beste.


Bevor wir uns in diese Diskussion vertiefen: Ist das ein Flaschenhals?

Wenn Sie nicht profiliert und sichergestellt haben, dass es ein Flaschenhals war, dann könnte diese Diskussion komplett aus sein ... Denken Sie daran, als Debugging-Builds Profilerstellung ist ziemlich nutzlos.


nun in C++ 03 gibt es mehrere Optionen, von den schmackhaft zu dem mindestens ein:

  • Vertrauen der Compiler: unnamed Variablen verwenden RVO auch in Debug baut in gcc, für Beispiel.
  • ein "out" Parameter verwenden (durch Verweis übergeben)
  • auf dem Heap reservieren und einen Zeiger (Smart oder nicht)
  • Prüfung der Compiler Ausgabe

Persönlich würde ich meinen Compiler vertrauen wenn ein Profiler nicht beweist, dass ich falsch liege.

In C++ 11, bewegen Semantik uns hilft, mehr Vertrauen bekommen, weil, wenn es eine return Aussage ist, wenn RVO nicht kicken kann, dann ein Schritt Konstruktor (falls vorhanden) automatisch verwendet werden; und bewegen Konstruktoren auf vector sind spottbillig.

So wird es:

  • Vertrauen der Compiler: entweder RVO oder verschieben Semantik
  • auf dem Heap zuweisen und gibt ein unique_ptr

aber wirklich den zweiten Punkt sollte nur verwendet wird für Die wenigen Klassen, in denen die Semantik der Bewegung nicht viel hilft: Die Kosten für die Semantik der Verschiebung sind normalerweise proportional zur Rückgabe von sizeof, zum Beispiel hat eine std::array<T,10> eine Größe, die 10*sizeof(T) entspricht, also ist es nein t so gut und könnte von Heap Allokation + unique_ptr profitieren.


Tangente: Sie vertrauen Ihrem Compiler bereits. Sie vertrauen darauf, Sie vor Fehlern zu warnen, Sie vertrauen darauf, Sie vor gefährlichen/wahrscheinlich falschen Konstrukten zu warnen, Sie vertrauen darauf, Ihren Code korrekt in Maschinen zu übersetzen, Sie vertrauen darauf, sinnvolle Optimierung anzuwenden, um eine ordentliche Beschleunigung zu erzielen. Wenn man einem Compiler nicht zutraut, um RVO in offensichtlichen Fällen anzuwenden, ist es nicht so, dass man seinem Herzchirurgen mit einer Rechnung von 10 Dollar vertraut: Es ist die geringste Ihrer Sorgen. ;)

+1

Vielen Dank für die Tangente! :) – tmaric

1

Ich bin ziemlich sicher, dass der Compiler Return Value Optimization für valueFun tun wird. Die wichtigsten Fälle, in denen Rückgabewert Optimierung kann nicht durch den Compiler verwendet werden, sind:

  • Rückkehr Parameter
  • ein anderes Objekt auf der Basis eines bedingten

Rückkehr So ist die auto_ptr nicht notwendig ist, und wäre noch langsamer, da der Heap verwendet werden muss.

Wenn Sie immer noch besorgt über die Kosten der Bewegung um solch einen großen Vektor sind, möchten Sie möglicherweise in die Bewegungssemantik (std::vector aCopy(std::move(otherVector)) von C++ 11) schauen. Diese sind fast so schnell wie RVO und können verwendet werden überall (es ist auch für die Rückgabewerte verwendet werden garantiert, wenn RVO nicht in der Lage ist, verwendet werden.)

ich modernsten Compiler convoy Semantik (oder rvalue Referenzen technisch) glauben viele an dieser Stelle

+0

Das "ziemlich sicher" stört mich ein bisschen. :) Von meinem Standpunkt aus, wenn ich diese Sache auf 100s von Kernen laufen lasse und wenn es mit der Zeit wachsen wird, muss ich 100% sicher sein, was der Code tut. – tmaric