Operatoren langsam, wie so...?
-
orkun schrieb:
Warum sind eigentlich operatoren langsamer als "normale" funktionen...?...
Da Operatoren normale Funktionen sind, sind sie auch nicht langsamer.

Gruß,
Simon2.
-
Okay, dann muss ich wohl meine Frage anders formulieren...
Warum wird in Real Time Rendering oder Physik Engines auf operatoren verzichtet...?
Beispielsweise Havok Vectorklasse sieht so aus:
00001 #ifndef HAK_MATH_VECTOR3_H 00002 #define HAK_MATH_VECTOR3_H 00003 00004 #ifndef HK_MATH_VECMATH_H 00005 #error Include <hk_math/vecmath.h> Do not include this file directly. 00006 #endif // HK_MATH_VECMATH_H 00007 00008 namespace Havok { class Vector3; } 00009 00010 struct hkVector3ExpressionPlus; 00011 struct hkVector3ExpressionMinus; 00012 00013 #define HK_REF & 00014 #define Const //const 00015 #define ConsT const 00016 00017 class hk_Vector3 00018 { 00019 public: 00020 00021 HK_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR(HK_MEMORY_CLASS_CONSTRAINT, hk_Vector3) 00022 00023 inline hk_Vector3(); 00024 inline hk_Vector3(hk_real a, hk_real b, hk_real c); 00025 inline hk_Vector3(const double*); 00026 inline hk_Vector3(const float*); 00027 00028 inline hk_Vector3( const hk_Vector3& v); 00029 inline void operator= (const hk_Vector3& v); 00030 00031 /* expression operators */ 00032 inline hk_Vector3(ConsT hkVector3ExpressionPlus HK_REF v); 00033 inline void operator= (ConsT hkVector3ExpressionPlus HK_REF v); 00034 inline hk_Vector3(ConsT hkVector3ExpressionMinus HK_REF v); 00035 inline void operator= (ConsT hkVector3ExpressionMinus HK_REF v); 00036 00037 /* accumulation operators */ 00038 inline void operator= (const Havok::Vector3&); //<todo> remove me 00039 inline void operator+= (const hk_Vector3& a); 00040 inline void operator-= (const hk_Vector3& a); 00041 inline void operator*= (hk_real a); 00042 00043 inline void set(hk_real a, hk_real b, hk_real c); 00044 inline void set_zero(); 00045 00046 /* arithmetic operations - fast! */ 00047 inline void set_add(const hk_Vector3& a, const hk_Vector3& b); 00048 inline void set_sub(const hk_Vector3& a, const hk_Vector3& b); 00049 inline void set_cross(const hk_Vector3& a, const hk_Vector3& b); 00050 00051 inline void set_mul(hk_real r, const hk_Vector3& a); 00052 inline void set_mul3(const hk_Diagonal_Matrix& a, const hk_Vector3& b); 00053 inline void set_mul3( const hk_Matrix3& a, const hk_Vector3& b ); 00054 inline void add_mul(hk_real r, const hk_Vector3& a); 00055 inline void set_interpolate( const hk_Vector3& a, const hk_Vector3& b, hk_real t); 00056 00057 /* transform */ 00058 void set_rotated_dir (const hk_Rotation& a, const hk_Vector3& b); 00059 void set_rotated_inv_dir(const hk_Rotation& a, const hk_Vector3& b); 00060 00061 void set_transformed_pos (const hk_Transform& a, const hk_Vector3& b); 00062 void set_transformed_inv_pos(const hk_Transform& a, const hk_Vector3& b); 00063 00064 /* inline versions of above */ 00065 inline void _set_rotated_dir (const hk_Rotation& a, const hk_Vector3& b); 00066 inline void _set_rotated_inv_dir(const hk_Rotation& a, const hk_Vector3& b); 00067 00068 inline void _set_transformed_pos (const hk_Transform& a, const hk_Vector3& b); 00069 inline void _set_transformed_inv_pos(const hk_Transform& a, const hk_Vector3& b); 00070 00071 /* length and distance */ 00072 inline hk_real dot(const hk_Vector3& a) const; 00073 inline hk_real length() const; 00074 inline hk_real length_inv() const; 00075 inline hk_real length_squared() const; 00076 00077 inline hk_real distance_squared_to( const hk_Vector3 &) const; 00078 inline hk_real distance_to( const hk_Vector3 &) const; 00079 00080 inline void normalize(); 00081 inline hk_real normalize_with_length(); 00082 //void fast_normalize_e10(); // 10 bits valid 00083 00084 /* element access */ 00085 inline hk_real& operator() (int a); 00086 inline const hk_real& operator() (int a) const; 00087 00088 inline hk_real* get_real_pointer() { return &x; } 00089 inline const hk_real* get_real_pointer() const { return &x; } 00090 00091 public: 00092 00093 hk_real HK_ALIGNED_VARIABLE(x,16); 00094 hk_real y; 00095 hk_real z; 00096 hk_real w; 00097 }; 00098 00099 inline Const hkVector3ExpressionPlus operator+ (const hk_Vector3& a, const hk_Vector3& b); 00100 inline Const hkVector3ExpressionMinus operator- (const hk_Vector3& a, const hk_Vector3& b); 00101 00102 #endif // HAK_MATH_VECTOR3_H
-
was willst du ? hier werden doch genauso operatoren verwendet
Meep Meep
-
orkun schrieb:
...
Warum wird in Real Time Rendering oder Physik Engines auf operatoren verzichtet...?Beispielsweise Havok Vectorklasse sieht so aus:
Also ich sehe da sehr viele Operatoren...
(operator=, operator+=, operator-=, operator*=, operator(), operator+, operator-...)cu André
-
Okay, also ihr denkt der Author hatte langeweile beim implementieren und kommentieren der Methoden:
00046 /* arithmetic operations - fast! */ 00047 inline void set_add(const hk_Vector3& a, const hk_Vector3& b); 00048 inline void set_sub(const hk_Vector3& a, const hk_Vector3& b); 00049 inline void set_cross(const hk_Vector3& a, const hk_Vector3& b); 00050 00051 inline void set_mul(hk_real r, const hk_Vector3& a); 00052 inline void set_mul3(const hk_Diagonal_Matrix& a, const hk_Vector3& b); 00053 inline void set_mul3( const hk_Matrix3& a, const hk_Vector3& b ); 00054 inline void add_mul(hk_real r, const hk_Vector3& a); 00055 inline void set_interpolate( const hk_Vector3& a, const hk_Vector3& b, hk_real t);die sind wohl nur zufällig da... alles klar...
-
Vielleicht solltest du mal die Implementierung der Operatoren und Methoden miteinander vergleichen (da die als 'inline' definiert sind, solltest du sie auch vorliegen haben).
(PS: Vielleicht ist set_add() auch nur schneller, weil es zwei Vektoren auf einen Schlag aufaddieren kann - oder der Autor hatte tatsächlich Langeweile (oder keine Ahnung))
-
Dir ist schon klar, dass diese Funktionen durchwegs 3 Parameter haben während die Operatoren nur 2 Parameter haben?
Ich weiß nicht was ein set_add macht, aber es verlangt 3 hk_Vector3 Objekte. Das geht mit einem + schwer. Dass ein
add(a,b,c)
uU schneller sein kann als ein
add(a, add(b,c))
sollte der Verstand von alleine erklären können.PS:
ein operator ist eine stinknormale funktion die für uns programmierer einfach nur etwas anders aussieht.wir können zwar a+b schreiben, aber der compiler sieht hier ein a.operator+(b) oder ein operator+(a,b) - je nachdem. ersetzen wir den namen "operator+" nun durch "foo":
foo(a,b)
sieht es doch fast wie eine normale funktion aus, oder?
-
orkun schrieb:
Okay, also ihr denkt der Author hatte langeweile beim implementieren und kommentieren der Methoden:
00046 /* arithmetic operations - fast! */...die sind wohl nur zufällig da... alles klar...
Vorab: Meinst DU wirklich, mit einem genervten Grundton läuft die Diskussion besser ?
@Topic: Ich wette, dass dieser Kommentar gar nichts mit Sprachfeatures/Eigenschaften zu tun hat, sondern der Autor (höchstens) eine optimierte Implementierung mit diesen Namen belegt hat.
Genauso könnte da auch stehen:00046 /* arithmetic operations - slow! */...Gruß,
Simon2.
-
orkun schrieb:
Okay, also ihr denkt der Author hatte langeweile beim implementieren und kommentieren der Methoden:
00046 /* arithmetic operations - fast! */ 00047 inline void set_add(const hk_Vector3& a, const hk_Vector3& b); 00048 inline void set_sub(const hk_Vector3& a, const hk_Vector3& b); 00049 inline void set_cross(const hk_Vector3& a, const hk_Vector3& b); 00050 00051 inline void set_mul(hk_real r, const hk_Vector3& a); 00052 inline void set_mul3(const hk_Diagonal_Matrix& a, const hk_Vector3& b); 00053 inline void set_mul3( const hk_Matrix3& a, const hk_Vector3& b ); 00054 inline void add_mul(hk_real r, const hk_Vector3& a); 00055 inline void set_interpolate( const hk_Vector3& a, const hk_Vector3& b, hk_real t);die sind wohl nur zufällig da... alles klar...
Ich glaube du bist ein bisschen doof. Welche dieser Funktionen würdest du denn durch einen überladenen Operator ersetzen? Und welchen? Und wie?
Willst du statt set_add einen operator + (std::pair<hk_Vector3 const&, hk_Vector3 const&>) machen oder wie stellst du dir das vor?
-
hustbaer schrieb:
Ich glaube du bist ein bisschen doof. Welche dieser Funktionen würdest du denn durch einen überladenen Operator ersetzen? Und welchen? Und wie?
Willst du statt set_add einen operator + (std::pair<hk_Vector3 const&, hk_Vector3 const&>) machen oder wie stellst du dir das vor?ich denkmal das 'set_add' den operator+ und den operator= ersetzen soll.
ich glaub der programmierer hat den aufwand mit den funktionen deshalb betrieben, um temporaere objecte zu vermeiden.bin mir fast sicher das das ungefaehr so aussieht:
class hk_Vector3; class hkVector3ExpressionPlus { public: hkVector3ExpressionPlus(const hk_Vector3 &v1, const hk_Vector3 &v2) : vec1(v1), vec2(v2) { } const hk_Vector3 &vec1, &vec2; }; inline const hkVector3ExpressionPlus operator+ (const hk_Vector3& a, const hk_Vector3& b) { return hkVector3ExpressionPlus(a,b); } class hk_Vector3 { public: ... /* expression operators */ inline void operator= (ConsT hkVector3ExpressionPlus HK_REF v) { /* hier kommt der teil den ich mir denke */ set_add(v.vec1, v.vec2); } ... /* arithmetic operations - fast */ ... inline void set_add(const hk_Vector3& a, const hk_Vector3& b) { /* hier wird er wahrscheinlich die addition und die zuweisung machen */ } ... }; /* damit kann man nu folgendes schreiben: */ hk_Vector3 a,b,c; a = b + c; /* <- schlussendlich wird dann hier vom kompiler implizit die 'set_add'-memberfunktion eingesetzt. somit wird das temporaere object, welches von 'b + c' erzeugt werden wuerde, vermieden. deshalb wahrscheinlich der kommentar mit 'fast'*/und nachdem ich grad so schoen am traeumen bin, geh ich jetz schlafen.
gute nacht
Meep Meep
-
@Meep Meep
jep, denke ich auch, die dinger werden ja auch "expression operators" genannt. imho eine sehr geile idee, komplexe operationen auf diese Weise effizient und lesbar zu machen.
-
Hah, hab ich wieder mal das offensichtliche übersehen

Trotzdem würde ich das nicht so machen wenn ich will dass es unbedingt und auf jeden Fall schnell geht... ich persönlich finde da die "set_add" Funktion besser.
-
orkun schrieb:
Warum sind eigentlich operatoren langsamer als "normale" funktionen...?
In der Theorie nicht, in der Praxis leider schon. Das hat vor allem mit den von Meep Meep bereits angesprochenen temporären Objekten zu tun, die Compiler nicht vollständig eliminieren können. Dort gab es immer mal wieder diverse Lösungsansätze. Alexandrescu hat auch mal etwas dazu verfasst, Stichwort Mojo. Ein bekannte Lösung für binäre Operatoren sind Expression Templates. Allerdings ist sowas weder elegant zu implementieren, noch einfach zu warten. Jedenfalls kann das ziemlich komplexe Ausmasze annehmen.
Sry wenn dich einige hier anmachen, aber deine Frage ist durchaus berechtigt.
orkun schrieb:
ich möchte eine eine 3D Vectorklasse schreiben, lohnt es sich mit SSE oder mit 3DNow! zu implementieren?
SSE bzw. 3DNow lohnt sich immer. Ob man das selber implementiert, hängt von den Fähigkeiten deines Compilers ab.
orkun schrieb:
Welche operationen sollte ich als inline assembler implementieren?
Gar keine. Aktuelle Compiler sollten entsprechende Intrinsics kennen.
-
groovemaster schrieb:
orkun schrieb:
Warum sind eigentlich operatoren langsamer als "normale" funktionen...?
In der Theorie nicht, in der Praxis leider schon. Das hat vor allem mit den von Meep Meep bereits angesprochenen temporären Objekten zu tun, die Compiler nicht vollständig eliminieren können. Dort gab es immer mal wieder diverse Lösungsansätze. Alexandrescu hat auch mal etwas dazu verfasst, Stichwort Mojo. Ein bekannte Lösung für binäre Operatoren sind Expression Templates. Allerdings ist sowas weder elegant zu implementieren, noch einfach zu warten. Jedenfalls kann das ziemlich komplexe Ausmasze annehmen.
Sry wenn dich einige hier anmachen, aber deine Frage ist durchaus berechtigt.
Ist sie finde ich nicht. (Ich vor allem habe mich auch am Ton des OP mehr gestossen als an seiner Frage. Etwas nicht zu wissen und zu fragen ist OK, auf richtige Antworten dann aber patzig zu werden ... vertrage ich nicht ganz.)
Ein überladener Operator ++ ist nicht langsamer als eine "increment" Memberfunktion.
Ein überladener Operator += ist auch nicht langsamer als eine "add" Memberfunktion.
Beides sind üblicherweise Memberfunktionen und werden ganz genau gleich aufgerufen.D.h. solange man nicht anfängt Äpfel mit Birnen zu vergleichen...
Ein Aufruf von Operator + der ein Temporary zurückliefert + ein Aufruf von Operator = mit diesem Temporary als Argument, dann vielleicht noch darauf besteht dass Operator = eine Referenz auf *this zurückliefert ... wenn du das mit dem Aufruf einer einzigen Funktion die void zurückliefert vergleichen willst ... ich finde den Vergleich auf jeden Fall unsinnig.
----
Wo ich dir natürlich zustimme: mit überladenen Operatoren kann man schwerer optimieren als mit Memberfunktionen. Was aber einfach daran liegt dass Operatoren eine vorgegebene Anzahl an Parametern haben, und Memberfunktionen nicht. Wo wir dann auch wieder bei den Äpfeln und Birnen wären, man soll eben keinen Apfel den Job einer Birne machen lassen.

-
Es geht in diesem Thread um Optimierungstechniken von Funktionen und Operatoren (auch mit SSE, MMX etc.) Ich habe behauptet, dass man Operatoren nur schwer optimieren kann und dass sie deshalb langsam sind.
Der Code war nur ein Beispiel für eine Optimierungstechnik. (meine Meinung nach eine schöne UND aufwendige Technik)
Ich habe genervt beantwortet, weil die Optimierungstechnik, die da benutzt wird, ignoriert wurde. Man muss ja nicht unbediengt die ganze Implementierung sehen, um zu wissen was die Klasse macht.Jetzt habe ich noch eine Frage an die jenigen die Sachlich diskutieren können und mir bei meinem Problem helfen wollen:
Was genau ist der Unterschied zwischen Inline-Assembler-Code und Verwendung von Intrinsics.
Inline-Assembler, wird ja immer noch benutzt, obwohl es mit Intrinsics einfacher geht.PS: Ich werde jetzt dafür kein Beispielcode verwerden, ihr wisst schon warum...
-
wenn du inline assembler verwendest hast du die komplette kontrolle ueber den generierten code, aber auch die komplette verantwortung dafuer.
meines wissens kann der kompiler jedoch selbst keine optimierungen mehr an dem code vornehmen.intrinsics erscheinen wie normale funktionen, werden jedch direkt in maschinencode umgesetzt.
ob der kompiler damit noch optimieren kann entzieht sich meinem wissen.
hab auch irgendwo im internet mal gelesen, das mit VC auf nem 64-bit windows kein inline assembler mehr moeglich sein soll. kann jetzt aber die quelle dazu nicht angeben. schon zu lange her. also mit vorsicht zu geniesen.Meep Meep
-
orkun schrieb:
Es geht in diesem Thread um Optimierungstechniken von Funktionen und Operatoren (auch mit SSE, MMX etc.) Ich habe behauptet, dass man Operatoren nur schwer optimieren kann und dass sie deshalb langsam sind.
sah fuer mich nicht so aus
orkun schrieb:
Warum sind eigentlich operatoren langsamer als "normale" funktionen...?
orkun schrieb:
Man muss ja nicht unbediengt die ganze Implementierung sehen, um zu wissen was die Klasse macht.
haette die sache aber unter umstaenden vereinfacht
Meep Meep
-
orkun schrieb:
...Ich habe behauptet, dass man Operatoren nur schwer optimieren kann und dass sie deshalb langsam sind....
Ist trotzdem Quatsch !
Was Du vielleicht meinst, ist, dass bestimmte Aufrufsemantiken weniger Optimierungstechniken zulassen als andere. Ob diese in f() oder in operator_() umgesetzt wird, spielt keine Rolle.Gruß,
Simon2.
-
orkun schrieb:
Es geht in diesem Thread um Optimierungstechniken von Funktionen und Operatoren (auch mit SSE, MMX etc.) Ich habe behauptet, dass man Operatoren nur schwer optimieren kann und dass sie deshalb langsam sind.
Nein, hast du nicht.
du hast neben dem von Meep meep zitiertem teil auch folgendes geschrieben:
Warum wird in Real Time Rendering oder Physik Engines auf operatoren verzichtet...?
Beispielsweise Havok Vectorklasse sieht so aus:
und pastest danach einen code, der ganz offensichtlich auf operatoren aufbaut, nur dass er sie intelligent nutzt, und nachdem wir den code mühevoll aufdröseln, wirst du patzig und behauptest "Das hab ich doch alles schon gewusst".
<°(((><
-
Oh man, ohne deine Hilfe hätte ich eine Woche lang auf die Implementierung der Methoden gestart und nicht gewusst was die Klasse macht, danke dass du mir alles erklärt hast...
Jetzt mal im Ernst:
Okay, ich bin Student und lebe seit einpaar Jahren in Deutschland. Ich habe meine Frage sehr schlecht formulieren(auch überschrift schlecht formuliert). Ich wollte eigentlich mehr über Optimierungstechniken wissen ...und worum geht's denn jetzt in diesem Thread...???
Naja egal... Nachdem mehrmals geschrieben wurde, dass ein Operator auch eine Funktion ist, habe ich geschrieben, dass in 3D engines auf operatoren verzichtet wird, deshalb die Behauptung, dass Operatoren langsam sind. Ich habe versucht, auf die schwerige(!) Optimierung von Operatoren aufmerksam zu machen. Ich dachte Headerdatei reicht, weil da auch die expression structs und die arithmetic operationen deklariert sind. Es war ein Beispiel......und ich behaupte nicht, dass ich Ahnung habe... im Gegenteil, ich habe Frage gestellt, weil ich mehr wissen möchte. Mit Sachliche Diskusion meine ich, dass man über das Thema diskutiert und nicht über meine genervte Ton, über meine Sprachkenntnisse etc...
Kurz:
Es ging in diesem Thread um Optimierungstechniken, um eine Vectorklasse mit optimierte Operationen, wie man am besten arithmetic operationen optimieren kann... Sollte man vielleicht doch operatoren benutzten. Oder lieber so was machen:http://www.cortstratton.org/articles/OptimizingForSSE.php
So missverständlich war der Anfangspost nun wieder auch nicht...