Template und Geschwindigkeit
-
Hallo,
dank der sehr guten Hilfe in diesem Forum, habe ich eine Template-Klasse eines Vectors (3D) erstellt. Nun frage ich mich, ob ich auch darauf geachtet habe, möglichst viel Geschwindigkeit, alleine durch die entsprechende Deklaration der Funktionen und Operatoren, herauszuholen?
Gibt es einen eleganteren Weg an das Array (Pointer) des Vectors heranzukommen, als mit der Funktion array()?
Hier nun mein Header:
#ifndef VECTOR3D_H_ #define VECTOR3D_H_ template<class T> class Point3D; template<class T> class Vector3D { private: //-(Variablen)---------------------------------------------------------- T n[3]; // x, y, z public: //-(Konstruktoren)------------------------------------------------------ inline Vector3D(); // Vektor mit (0,0,0) inline Vector3D(const T x, const T y, const T z); // Vektor mit (x,y,z) inline Vector3D(const Vector3D<T>& v); // Vektor mit (v.x, v.y, v.z) inline Vector3D(const Point3D<T>& a, const Point3D<T>& b); // Erstellt einen Vektor der von a nach b zeigt. //-(Überladene Operatoren)---------------------------------------------- inline T& operator[] (int i); inline T operator[] (int i) const; inline Vector3D<T>& operator+=(const Vector3D<T>& v); inline Vector3D<T>& operator-=(const Vector3D<T>& v); inline Vector3D<T>& operator*=(const T s); inline Vector3D<T>& operator/=(const T s); inline Vector3D<T>& operator+() const; // keine notwendige Funktion inline Vector3D<T>& operator-() const; // Invertierung friend Vector3D<T>& operator+ <>(const Vector3D<T>& a, const Vector3D<T>& b); friend Vector3D<T>& operator- <>(const Vector3D<T>& a, const Vector3D<T>& b); friend Vector3D<T>& operator* <>(const T s, const Vector3D<T>& v); friend Vector3D<T>& operator* <>(const Vector3D<T>& v, const T s); friend Vector3D<T>& operator/ <>(const Vector3D<T>& v, const T s); friend T operator* <>(const Vector3D<T>& a, const Vector3D<T>& b); friend Vector3D<T>& operator^ <>(const Vector3D<T>& a, const Vector3D<T>& b); friend bool operator== <>(const Vector3D<T>& a, const Vector3D<T>& b); friend bool operator!= <>(const Vector3D<T>& a, const Vector3D<T>& b); //-(Methoden)----------------------------------------------------------- inline T* array(void) const; // Gibt einen Pointer auf das Array zurück inline T norm(void) const; // Berechnet die Norm |x²+y²+z²| inline T length(void) const; // Berechnet die Länge sqrt(x²+y²+z²) }; #include "vector3d.cpp" // wegen eines Templatebugs in verschiedenen Compilern. #endif // VECTOR3D_H_
-
Hi,
Während des Schafkopfspielens fällt oft der Satz "Es hat sich schon mal jemand totgemischt", wenn jemand zu lange die Karten mischt. Genauso gut kann man sagen "Es hat sich schon mal jemand totoptimiert"
Zerbrich dir nicht den Kopf darüber die perfekte Vektorklasse hinzukriegen. Bist du schon bei solch "kleinen" Klassen überperfektionistisch, gelingen größere wohl kaum.Tschau
-
Es geht mir hier ja eigentlich nicht darum diese Klasse nun auf das Optimum zu tunen. Sondern darum, welche Möglichkeiten es überhaupt gäbe um es zu tun, falls es mal wirklich darauf ankommt. Die hier von mir verwendete Klasse ist ja eigentlich nur ein Beispiel, an dem ich herausfinden möchte was überhaupt möglich ist.

-
Tobain schrieb:
Nun frage ich mich, ob ich auch darauf geachtet habe, möglichst viel Geschwindigkeit, alleine durch die entsprechende Deklaration der Funktionen und Operatoren, herauszuholen?
sehr gut. Schafkopfspieler unterschätzt, wie wichtig es ist, an kleinen klassen zu üben. natürlich macht man so eine kleine klasse so gut, wie es geht.
Gibt es einen eleganteren Weg an das Array (Pointer) des Vectors heranzukommen, als mit der Funktion array()?
ja. return *this;
keine ahnung, weshalb du zeiger auf internre daten veröffentlichen willst. kannst auch nen op[] überladen.#ifndef VECTOR3D_H_ #define VECTOR3D_H_ template<class T> class Point3D;//warm denn forward-deklarieren? weg mit dieser zeile! template<class T> class Vector3D { private: //-(Variablen)---------------------------------------------------------- //nutloser kommentar. weg! T n[3]; // x, y, z //zu überlegen ist, ob nicht T x,y,z; gemeint war, wenn du schon y,x,z als kommentar dazuschreibst. //lieber gute namen und weg mit dem kommentar! public: //-(Konstruktoren)------------------------------------------------------ //nutzloser kommentar. weg! inline Vector3D(); // Vektor mit (0,0,0) //inline Vector3D(int _x=0,int _y=0,int _z=0); //und der kommentar kann weg! schreib doch bitte die inhalte in //lesbarem c++statt in kommentaren hin. //außerdem muss jedes inline weg. kein witz. inline Vector3D(const T x, const T y, const T z); // Vektor mit (x,y,z) //der kommentar bringt nix. weg! //const bringt hier auch nix. weg! inline Vector3D(const Vector3D<T>& v); // Vektor mit (v.x, v.y, v.z) //<T> bringt nix. weg! dkbnw! inline Vector3D(const Point3D<T>& a, const Point3D<T>& b); // Erstellt einen Vektor der von a nach b zeigt. //dieser kommentar bringt was! also ist der code schlecht. //so muß die heißen: operator- //und dann natürlich ohne kommentar, weil klar ist, was sie macht. einen vector erstellen, der von b nach a zeigt. //-(Überladene Operatoren)---------------------------------------------- //dkbnw! inline T& operator[] (int i); inline T operator[] (int i) const; //muss das wirklich sein? würd ich erstmal wegmachen und drauf warten, bis einer das braucht. inline Vector3D<T>& operator+=(const Vector3D<T>& v); inline Vector3D<T>& operator-=(const Vector3D<T>& v); inline Vector3D<T>& operator*=(const T s); inline Vector3D<T>& operator/=(const T s); //ok inline Vector3D<T>& operator+() const; // keine notwendige Funktion //dann weg damit inline Vector3D<T>& operator-() const; // Invertierung //dkbnw! friend Vector3D<T>& operator+ <>(const Vector3D<T>& a, const Vector3D<T>& b); friend Vector3D<T>& operator- <>(const Vector3D<T>& a, const Vector3D<T>& b); friend Vector3D<T>& operator* <>(const T s, const Vector3D<T>& v); //s muss nicht const sein, nur zur wiederholung. und mach jedes inline weg. friend Vector3D<T>& operator* <>(const Vector3D<T>& v, const T s); friend Vector3D<T>& operator/ <>(const Vector3D<T>& v, const T s); friend T operator* <>(const Vector3D<T>& a, const Vector3D<T>& b); friend Vector3D<T>& operator^ <>(const Vector3D<T>& a, const Vector3D<T>& b); //hier müßte ein kommentar hin, denn was soll ^ auf vektoren sein? oder besser, lösch den op und mach ne funktion mit sprechendem namen. friend bool operator== <>(const Vector3D<T>& a, const Vector3D<T>& b); friend bool operator!= <>(const Vector3D<T>& a, const Vector3D<T>& b); //-(Methoden)----------------------------------------------------------- //dkbnw! inline T* array(void) const; // Gibt einen Pointer auf das Array zurück //glaub nicht, daß die gut ist. inline T norm(void) const; // Berechnet die Norm |x²+y²+z²| //ok inline T length(void) const; // Berechnet die Länge sqrt(x²+y²+z²) //ok //lecker wäre eine, die das quadrat der länge berechnet, damit du in vielen zusammenhängen das radizieren sparen kannst. }; #include "vector3d.cpp" // wegen eines Templatebugs in verschiedenen Compilern. //glaub ich nicht. zeig den bug. und inkludiere nie wieder *.cpp. #endif // VECTOR3D_H_und nu zu
T* array(void);
gib doch ein array mit 3 elemeten zurück.
T array(void)[3];
oder mußte das eher ne referenz auf ein array mit 3 elementen sein?
T (&array(void))[3];
zu komisch schreibweise, also vereinfachen mit typedef
typedef T (&rarr3)[3];
rarr3 array(void);
zu komisch schreibweise, also vereinfachen mit typedef
typedef T arr3[3];
typedef arr3 &rarr3;
rarr3 array(void);
aber ich kette mich damit an die interne implemetierung als array und verbiete mir, x,y,z zu schreiben. also lieber
Vector3D& array(void);
und Vector3D hat ja den op[]
oder hatte array() am ende den zweck, es in diverse ogl-funktionen zuz stopfen? für den fall, würde ich wieder einen kommentar opfern:
//schmonzes für ogl
und unterhalb sowas machen und das ganz am ende der klasse.und nochwas: schreib in parameterlisten nie wieder (void) statt ().
-
und nochwas: schreib in parameterlisten nie wieder (void) statt ()
Warum?
-
"int f(void)" ist ein Relikt aus C-Zeiten (da stand "int f()" noch für "beliebig viele Parameter").
-
volkard schrieb:
keine ahnung, weshalb du zeiger auf internre daten veröffentlichen willst. kannst auch nen op[] überladen.
der umgang mit gl funktionen wird einfacher.
bsp:Vector3D<float> v1(5, 70, 0.3); glVertex3fv(v1.array());deswegen auch das array statt x, y, z
-
warum nicht
Vector3D<float> v1(5, 70, 0.3);
glVertex3fv(v1);
?
-
volkard schrieb:
warum nicht
Vector3D<float> v1(5, 70, 0.3);
glVertex3fv(v1);
?gehe davon aus das du den umwandlungsoperator meinst. ich muss zugeben das ich nicht so der freund davon bin.

-
miller_m schrieb:
gehe davon aus das du den umwandlungsoperator meinst. ich muss zugeben das ich nicht so der freund davon bin.

nein. ich meine eine überladene glVertex3fv(Vector3D)
-
volkard schrieb:
miller_m schrieb:
gehe davon aus das du den umwandlungsoperator meinst. ich muss zugeben das ich nicht so der freund davon bin.

nein. ich meine eine überladene glVertex3fv(Vector3D)
so habe ich es auch gemacht ;), ala
// aus meinem opengl wrapper void OglTranslate(float x, float y, float z) { glTranslatef(x, y, z); } void OglTranslate(double x, double y, double z) { glTranslated(x, y, z); } template< class Vector_> void OglTranslate(const Vector_ &v) { OglTranslate(v[0], v[1], v[2]); }
-
miller_m schrieb:
template< class Vector_> void OglTranslate(const Vector_ &v) { OglTranslate(v[0], v[1], v[2]); }ach, man muß gar kein array benutzen, es geht auch mit drei parametern?
ist dann das nicht viel besser und die array-version viel schlechter?
also netter zum verwenden ist die array-version allemal nicht.
was ist schneller. sei mir erlaubt, daß ich nur ein klitzebisschen in die zukunft gucke auf den ia-64 mit registerstack. da kosten übergaben herzlich wenig. und ram ist wie gehabt teuer. mir scheinen die drei parameter auch schneller.
vielleicht sollten wir den vector3d umstellen wollen auf die 3-parameter-version?@miller_m: du hast ja bereits sowas gemacht und mehr erfahrung als wir. warum hast du im Vector die daten als array und nicht als x,y,z?
-
volkard schrieb:
@miller_m: du hast ja bereits sowas gemacht und mehr erfahrung als wir. warum hast du im Vector die daten als array und nicht als x,y,z?
ironie?
wenn nicht. ich ging davon aus das der thread ersteller seine gründe hat, etvl vielleicht auch irgendwelche dx funktionen.
in meiner vektorklasse verwende ich noch ein array wegen vertexarrays und weil ich es früher auch so gemacht habe wie der thread ersteller
. da ich diese auch irgendwann mal verbessern möchte fliegt vermutlich das array in der vektorklasse auch raus. aber einen triftigen grund gibt es afaik nicht.volkard schrieb:
ach, man muß gar kein array benutzen, es geht auch mit drei parametern?
ist dann das nicht viel besser und die array-version viel schlechter?
vielleicht sollten wir den vector3d umstellen wollen auf die 3-parameter-version?ich habe auch nie behauptet das sie besser oder schlechter sind, ich kann nur ganz gut nachvollziehen was er sich dabei gedacht hat

-
Mensch da habe ich ja was losgetreten...
Nun stelle ich mir wirklich die Frage was davon nun besser ist, einzelne Variablen oder das Array? Vor allem sehe ich da keinen Vorteil wenn man ein Array verwendet und dann die Funktion mit den Parametern aufruft, anstell das Array zu übergeben.
// aus meinem opengl wrapper void OglTranslate(float x, float y, float z) { glTranslatef(x, y, z); } void OglTranslate(double x, double y, double z) { glTranslated(x, y, z); } template< class Vector_> void OglTranslate(const Vector_ &v) { OglTranslate(v[0], v[1], v[2]); }Aber wenn man nun das Array nicht verwendet, dann kann man doch nur sehr schwerlich eine Arrayindizierung vornehmen ( Operator[] )?
float operator[] (int i) { switch(i) { case 0 : return x; case 1 : ... } }Das ist doch sicherlich dann keine tolle Lösung oder? Irgendwie verwirrt mich das

@volkard Danke für die Hinweise bei meiner Headerdatei

-
Tobain schrieb:
Nun stelle ich mir wirklich die Frage was davon nun besser ist, einzelne Variablen oder das Array?
Da gibt es leider keine Universallösung. Wenn dich die einzelnen Komponenten getrennt interessieren, ist es wohl besser, sie in getrennte Member zu packen. Wenn du den Vektor als Einheit siehst und (z.B.) die Komponenten in Serie (Schleifen o.ä.) abarbeiten willst, bietet sich das Array an.
-
Tobain schrieb:
Aber wenn man nun das Array nicht verwendet, dann kann man doch nur sehr schwerlich eine Arrayindizierung vornehmen ( Operator[] )?
float operator[] (int i) { switch(i) { case 0 : return x; case 1 : ... } }wozu wird der op[] gebraucht?
-
wozu wird der op[] gebraucht?
Ich benötige ihn um ab und zu eine einzelne Komponente des Vektors auszulesen, da z.B. manchmal nur der z-Wert interressant ist.
Des weiteren möchte ich schon per Schleife über die Elemente iterieren können (für manche Algorithmen ist das ganz sinnvoll).
@volkard
Warum soll ich eigentlich das "inline" weglassen?
Also ohne das include "*.cpp" am Ende der Headerdatei will er mir den Code nicht kompilieren und haut so etwas raus:g++.exe -c main.cpp -o main.o -I"D:/Dev-Cpp/include/c++" -I"D:/Dev-Cpp/include/c++/mingw32" -I"D:/Dev-Cpp/include/c++/backward" -I"D:/Dev-Cpp/include" vector3d.h: In instantiation of `Vector3D<float>': main.cpp:23: instantiated from here vector3d.h:68: error: template-id `operator+<>' for `Vector3D<float>& operator+(const Vector3D<float>&, const Vector3D<float>&)' does not match any template declaration vector3d.h:69: error: template-id `operator-<>' for `Vector3D<float>& operator-(const Vector3D<float>&, const Vector3D<float>&)' does not match any template declaration vector3d.h:70: error: `operator*' not defined vector3d.h:71: error: `operator*' not defined vector3d.h:72: error: `operator/' not defined vector3d.h:73: error: `operator*' not defined vector3d.h:74: error: template-id `operator^<>' for `Vector3D<float>& operator^(const Vector3D<float>&, const Vector3D<float>&)' does not match any template declaration vector3d.h:76: error: template-id `operator==<>' for `bool operator==(const Vector3D<float>&, const Vector3D<float>&)' does not match any template declaration vector3d.h:77: error: template-id `operator!=<>' for `bool operator!=(const Vector3D<float>&, const Vector3D<float>&)' does not match any template declaration vector3d.h:20: warning: inline function `Vector3D<T>::Vector3D() [with T = float]' used but never defined
-
Tobain schrieb:
@volkard
Warum soll ich eigentlich das "inline" weglassen?"inline" gehört an die Funktionsdefinition, nicht an die Deklaration. (und die meisten Compiler entscheiden sowieso selbständig, welche Funktionen sie inline erweitern wollen).
(und Templates und Übersetzungseinheiten sind sowieso ein Thema für sich ;))
-
Tobain schrieb:
wozu wird der op[] gebraucht?
Ich benötige ihn um ab und zu eine einzelne Komponente des Vektors auszulesen, da z.B. manchmal nur der z-Wert interressant ist.
da geht auch T getZ(){return z};
Des weiteren möchte ich schon per Schleife über die Elemente iterieren können (für manche Algorithmen ist das ganz sinnvoll).
bleib mal ernsthaft. du wirst nicht eine schleife bauen, die über drei elemente iterieret und dir gleichzeitig woanders gedanken um speed machen.
@volkard
Warum soll ich eigentlich das "inline" weglassen?wels der compiler innherhalb von klassen selber hinschreibt.
und außerhalb schreibt er's da hin, wo es seinermeinung nach sinnvoll ist. und er hat ne gute einschätzung der lage. ja, in der tat. bei mir ist der resultierende code eigentlich immer schneller, wenn ich ihm freie hand lasse. manchmal ist ja kleinerer code schneller, weil caches besserausgenutzt werden und branch-precognition.Also ohne das include "*.cpp" am Ende der Headerdatei will er mir den Code nicht kompilieren und haut so etwas raus:
trotzdem nicht *.cpp includen. nenn sie um in *.inc oder *.imp, oder *_cpp.h oder so.
makefiles und so müssen sich drauf verlassen können, daß alle *.cpp durchcompiliert werden können.außerdem schreibt man die implemetierungen von template-funktionen eh normalerweise in den header.
-
Man das ist irgendwie alles nicht so durchsichtig, ich bräuchte mal das "perfekte Beispiel" mit ner guten Erklärung. Leider wird immer nur ein Aspekt behandelt und wenn 2 Aspekte zusammenkommen, dann ist eh alles wieder fürn Ar***.
Ein großes Danke an alle die sich bis jetzt bemüht haben mir zu helfen
