Compiler optimiert nur wenn die Memberfunktion static ist?!
-
Hey Leute,
hab ein komisches Performance-Problem. Ich nutzt Visual C++ 2005 und folgenden Code:#include <boost/array.hpp> typedef boost::array<char, 60000> ArrayType; class Test { public: static ArrayType getArray() { ArrayType arr; return arr; } }; int main() { for(int i = 0; i < 2000000; ++i) { Test test; test.getArray(); } }Wenn die Memberfunktion getArray static ist, ist das Programm innerhalb weniger Millisekunden fertig. Mach ich allerdings das static weg dann braucht der Code ungefähr 1 Minute auf meinem Rechner.

Es hat auch etwas mit der Array-Größe zu tun. Wenn ich das static weglasse und die Größe von 60000 auf z.B. 1000 ändere gehts auch ruck zuck.
Bin auf eine Erklärung gespannt.

-
static member liegen nur ein mal für alle Instanzen von einem Objekt im Speicher. D.h. in dem Fall: Es gibt ein Array für alle Instanzen von Test.
Lässt du das static weg, gibt's halt so viele Arrays, wie du Instanzen von Test anlegst, in dem Fall so an die 2000000.
-
Mach das so:
ArrayType getArray() { return ArrayType(); }und das geht furchbar schnell

BR
Vinzenz
-
GPC: Es geht doch hier um eine static Memberfunktion.
evilissimo: Stimmt, aber das ist nicht wirklich eine Lösung, ich muss das Array ja noch in der Funktion füllen. Hab das Beispiel nur auf allernötigste minimiert.
-
komisch schrieb:
GPC: Es geht doch hier um eine static Memberfunktion.
Ja. (Ich liebe Feststellungen ohne Informationsgehalt und ohne weiterführende Frage
*scnr*)EDIT:
Aber weil ich mal nicht so sein will - ich weiss worauf Du hinaus willst.Interessant ist im VS2005 immer, sich den disassemblierten Code anzuschauen. Im static-Fall wird ein leeres Objekt "test" konstruiert (leer, weil keine Members). Danach wird die Funktion Test::getArray() aufgerufen und der Rückgabewert verworfen. Vermutlich merkt der Optimierer, dass in Test::getArray() auch nichts passiert was auf die Aussenwelt Einfluss hat. Im Disassembly sieht man dann, dass die for-Schleife garnicht erst übersetzt wird.
EDIT2: Diese These lässt sich dadurch untermauern dass wenn man in Test::getArray() eine globale Variable modifiziert, diese nicht wegoptimiert wird.
Ohne static wird ein leeres Objekt "test" konstruiert, danach die Funktion Test::getArray( this:=test ) aufgerufen und der Rückgabewert verworfen. Hier kann man jetzt nur noch raten, aber ich schätze der Optimierer ist hier damit überfordert festzustellen, dass das auch keine Seiteneffekte hat, jedenfalls ist die Schleife in diesem Fall im Disassembly vollständig enthalten.
-
der scheint keine return value optimization zu machen. ich habe mal testweise einen copy-constructor in boost::array eingefügt wo memcpy aufgerufen wird und den optimiert er in der release version weg. vielleicht hat der vc++8 probleme mit der optimierung von default-copy-konstruktoren?

wenn er keine rvo macht dann werden ja gigabyte weise daten kopiert.
-
torstn schrieb:
der scheint keine return value optimization zu machen.
Hast Du dazu auch ein passendes Codebeispiel? Bei dem da oben kann imho garkeine RVO gemacht werden, weil es garkein Empfangsfeld gibt wo der RV hinoptimiert werden könnte...
-
na ja ich denke mal da könnte der compiler ja einfach nen dummy erstellen. aber hier der code.
#include <cstring> // memcpy class Array { public: Array() { } Array(const Array& arr) { std::memcpy(&elements_[0], &arr.elements_[0], sizeof(elements_)); } private: char elements_[60000]; }; class Test { public: Array getArray() { Array arr; return arr; } }; int main() { for(int i = 0; i < 2000000; ++i) { Test test; Array arr = test.getArray(); } }das ist das beispiel wo er optimiert. wenn man jetzt den copy-constructor auskommentiert wirds lahm.