Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Jul 05, 2025 11:11

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 22 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: C++ Performance fragen
BeitragVerfasst: Mo Feb 09, 2009 03:29 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Hi,

ich hab noch ein paar performance fragen bezüglich C++.
Zur info, hier geht es mehr oder weniger um millisekunden, bzw noch weniger.. aber in meinem fall ist jede millisekunde wichtig! :)

1)
Ich habe eine funktion die eine Farbe (ein Struct aus 4 Floats) zurückliefern muß. Diese wird mehrere millionen mal aufgerufen, etwa so:

Code:
  1. CColor doSomething() {
  2.   CColor result;
  3.   result = something();
  4.   retur result;
  5. }
  6.  
  7. [....]
  8. CColor c;
  9. for (int i = 0; i < 10000000; i++)
  10.   c += doSomething();



Ist es da ein geschwindigkeits unterschied wenn ich das ganze so umstelle?

Code:
  1. void doSomething(CColor &c) {
  2.   c = something();
  3. }
  4.  
  5. [....]
  6. CColor c, x;
  7. for (int i = 0; i < 10000000; i++) {
  8.   doSomething(x);
  9.   c += x;
  10. }


Sprich, macht es einen geschwindigkeits unterschied ob ich in jedem funktionsaufruf eine neue CColor erstelle oder eine übernehme die ich als reference-parameter bekomme? Oder optimiert der compiler das eh weg?


2)
Macht es einen geschwindigkeitsunterschied ob ich einer funktion parameter als referenz oder als pointer übergebe?

Code:
  1. void doSomething(CColor &c) {
  2.   c.bla();
  3. }


oder:

Code:
  1. void doSomething(CColor *c) {
  2.   c->bla();
  3. }



3)
Ähnlich wie erstens, ist hier ein unterschied?

Code:
  1. CColor x;
  2. for (int i = 0; i < 10000; i++) {
  3.   CColor c = bla();
  4.   x += c;
  5. }


und:

Code:
  1. CColor x, c;
  2. for (int i = 0; i < 10000; i++) {
  3.   c = bla();
  4.   x += c;
  5. }


Das ich hier nicht diret "x += bla()" mache liegt nur am beispiel, es geht nur um das erstellen eines neuen color-objekts in der for-schleife.. oder wird das sowieso wegoptimiert?


Aya


PS: Hab das gleiche auch im Delphi-Forum gefragt: http://www.delphi-forum.de/viewtopic.php?p=548613


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 08:49 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
Could you benchmark it? And does not c++ (or at least the gnu version) have an option where you can set the optimisation level. Also i believe you are able to target i386 vs i686 even that could have impact.

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 11:05 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
zu 1)
Die zweite Variante ist schneller. Speicher reservieren ist eine relative langsame Operation.
Noch schneller wäre es aber,, wenn du die Funktion doSomething() als inline definieren würdest. Sofern du die Funktion nirgendwo sonst (oder nur an wenigen Stellen) benutzt kann der Compiler den gesamten Funktionsaufruf weg optimieren.

Folgendes wäre vielleicht auch noch eine Alternative:
Code:
  1. CColor doSomething() {
  2.   return something();
  3. }


zu 2)
Referenz dürfte schneller sein. Vermutlich optimiert der Compiler das sowieso.

zu 3)
Wie bei erstens, Speicher reservieren dauert. Vermutlich optimiert der Compiler aber auch hier.


Allgemein:
Viel wichtiger als solche Kleinigkeiten ist aber, dass du einen für deinen Zweck optimalen Algorithmus wählst! Also überlege ob du es irgendwie vermeiden kannst diese Operation millionenmal auszuführen. Klassisches Beispiel sind Sortieralgorithmen. Wenn du da naiv ran gehst wirst du entweder Insertion-Sort, Selection-Sort oder Bubble-Sort implementieren. Das sind die drei Algorithmen auf die man ohne viel nachdenken kommt. Diese Algortihmen haben eine Laufzeit von O(n*n), du brauchst also um 10.000 Zahlen zu sortieren 100 Mio. Operationen. Setzt man etwas mehr Grips ein implementiert man dann vielleicht den Quicksort-Algorithmus, Merge-Sort oder vielleicht auch Intro-Sort. Diese haben eine erwartete Laufzeit von O(n*log(n)). Bei 10.000 Zahlen brauchst du also nur etwa 130.000 Operationen.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 12:35 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Da es gerade bei C mehrere durchaus verschiedene Compiler gibt, würde ich mich nicht allein auf die optimierung verlassen, sondern erstmal versuchen, ohne irgendwelche Optimierungen das beste rauszuholen.

zu 1: Ich stimme mit Coolcat überein, ich würde da ein Inline versuchen.

zu 2: Ich kenne jetzt den Unterschied bei C zwischen Referenz und Pointer nicht... Müsste das nicht das gleich sein? Ein Pointer ist doch ein Verweis, eine Referenz, auf einen Speicherbereich?

zu 3: Im worst case muss er den Stack da bei jedem Schleifendurchlauf erhöhen und senken, sowie das Objekt reinlegen. Ich würde sagen, du solltest bei der Variante bleiben, wo du das außerhalb deklarierst.

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 13:23 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
zu 2: Ich kenne jetzt den Unterschied bei C zwischen Referenz und Pointer nicht... Müsste das nicht das gleich sein? Ein Pointer ist doch ein Verweis, eine Referenz, auf einen Speicherbereich?

Bei einer Referenz kann der Compiler optimieren. Eine Referenz ist einfach nur ein Aliasname. Er greift einfach direkt auf die referenzierte Speicherstelle zu ohne erst den Pointer zu lesen und die entsprechende Speicherstelle zu suchen.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 14:11 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Danke für die antworten,

bestätigt das was ich mir schon gedacht hatte :) Wollte nur sicher gehen.


Coolcat hat geschrieben:
Allgemein:
Viel wichtiger als solche Kleinigkeiten ist aber, dass du einen für deinen Zweck optimalen Algorithmus wählst! Also überlege ob du es irgendwie vermeiden kannst diese Operation millionenmal auszuführen. Klassisches Beispiel sind Sortieralgorithmen. Wenn du da naiv ran gehst wirst du entweder Insertion-Sort, Selection-Sort oder Bubble-Sort implementieren. Das sind die drei Algorithmen auf die man ohne viel nachdenken kommt. Diese Algortihmen haben eine Laufzeit von O(n*n), du brauchst also um 10.000 Zahlen zu sortieren 100 Mio. Operationen. Setzt man etwas mehr Grips ein implementiert man dann vielleicht den Quicksort-Algorithmus, Merge-Sort oder vielleicht auch Intro-Sort. Diese haben eine erwartete Laufzeit von O(n*log(n)). Bei 10.000 Zahlen brauchst du also nur etwa 130.000 Operationen.


Das ist klar ;)
Bei mir geht's hier grad um einen Software Rasterizer, und im speziellen um die shader-fuktionen.
Es ging auch "nur" darum den code von 15ms pro frame auf noch weniger runter zu bekommen. Bin jetzt bei 8ms pro Frame (bei 800x600 mit ca. 20.000 Triangles die etwa 2/3tel des bildes füllen)

Aya~


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 17:05 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Dann solltest du auf jeden fall auch mal in die verschiedenen Assembleranweisungen für das gleichzeitige (wirklich gleichzeitig) bearbeiten von drei oder vier Floats mit einer Rechenoperation. Dürfte für Vektoren und Farben, speziell Blending, Gold beziehnungsweise Millisekunden wert sein.

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 17:18 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Lord Horazont hat geschrieben:
Dann solltest du auf jeden fall auch mal in die verschiedenen Assembleranweisungen für das gleichzeitige (wirklich gleichzeitig) bearbeiten von drei oder vier Floats mit einer Rechenoperation. Dürfte für Vektoren und Farben, speziell Blending, Gold beziehnungsweise Millisekunden wert sein.

Gruß Lord Horazont


Huh? Davon hör ich zum ersten mal, magst du das kurz etwas genauer erklären? :)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 17:30 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Hab mich noch nicht ernsthaft damit beschäftigt, aber hier ein Ansatz:
http://de.wikipedia.org/wiki/3DNow
http://de.wikipedia.org/wiki/Streaming_SIMD_Extensions

Du musst natürlich bedenken das du dich so möglicherweise auf einen bzw. eine Gruppe von CPUs festlegst.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 18:45 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Hui,

hab das grad mal nur testweise ausprobiert und damit lässt sich tatsächlich nochmal alles bis um das 4-fache schneller machen, danke :)

Aya~


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 09, 2009 23:55 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
So,

das ganze mit SSE hat nochmal ordentlich was gebracht :)
Man muß nur erstmal drauf kommen das man das nicht in einem union benutzen darf, da sonst wieder performance verloren geht :p

Hab jetzt allerdings erstmal nur meine Color4f-Klasse umgestellt, für die Vector3f-Klasse wäre es eigentlich auch perfekt, allerdings frage ich mich hier ob es lohnt..

Ich müßte bei jeder rechnung die ich mache dann ein neues objekt von __m128 (die 128bit variable von SSE) erstellen und da die ersten 3 floats auf meine werte setzen, dann wieder zurücklesen etc... die frage wäre ob das dann noch schneller ist als einfach die floats von hand zusammen zurechnen (geht ja nur um operationen wie +, -, * und /)..

Dem Vektor einfach nen vierten float wert (w) dazu zu geben geht aus vielen anderen gründen nicht :)

Aya~


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 10, 2009 00:26 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Color4f Klasse?
Kannst du die mal zeigen? Am besten auch, was du jetzt genau mit SSE gemacht hast.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 10, 2009 01:27 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Flash hat geschrieben:
Color4f Klasse?
Kannst du die mal zeigen? Am besten auch, was du jetzt genau mit SSE gemacht hast.


Umh, das ist bei mir die "chaotischte" klasse. Mein ziel war es beliebig viele farb-kanäle (auch mehr als nur RGBA) und verschiedene datentypen (float, double, unsigned char etc) zu unterstüzen.. Das ganze ist dadurch zu einem ziemlich komplexen template konstrukt geworden.

Im grundprinzip kann die Klasse aber auch nicht mehr als farb-daten halten (im normalfall RGB(A) in float) und bietet halt die standard rechenoperationen für farben (+, -, *, /, +=, -=, *=, /= etc) als überladene operatoren.

Durch das multi-channel prinzip mußte ich früher z.B. bei der Color4f bei der multiplikation soetwas schreiben:

Code:
  1. CIColor4f r;
  2. for (int i = 0; i < numChannels(); i++) // numChannels() wird bei Color4f durch einen Templateparameter festgelegt.
  3.   r[i] = channel[i] + otherColor[i];
  4. return r;


Jetzt nach der umstellung auf SSE habe ich einfach für Color4f das template spezialisiert und als datentyp folgendes verwendet:

Code:
  1.     struct CIColorChannelsSSEFloatData {
  2.         __m128 sse;
  3.         float& operator[](unsigned int i) {
  4.             return ((float*)&sse)[i];
  5.         }
  6.  
  7.         float* getPointer() {
  8.             return (float*)&sse;
  9.         }
  10.     };


durch den [] operator und getPointer() bleibe ich kompatibel zu meinen anderen Farb-Formaten. (z.B. um sie in OpenGL zu benutzen: glColor4fv(myColor.getPointer()); bzw wird das auch von meiner klasse gehandhabt -> myColor.bind(); (natürlich inline) ;)

so, und um jetzt 2 Farben via SSE zu multiplizieren:


Code:
  1.     inline CIColorChannelsSSEFloat CIColorChannelsSSEFloat::operator*(CIColorChannelsSSEFloat p)
  2.     {
  3.         return _mm_mul_ps(channelData.sse, p.channelData.sse);
  4.     }


Das ist alles.. :)

Aya~

PS: Das ist übrigens wieder einer der Momente wo ich froh darüber bin auf C++ umgestiegen zu sein.
Ich programmiere den Rasterizer mehr oder weniger Parallel mit nem Freund (er in Java), sprich wir benutzen für den Rasterizer die gleichen algorithmen etc... wir haben es auch bei ihm schon bist zum geht nicht mehr optimiert, aber meine C++ lösung läuft etwa doppelt so schnell wie seins in Java (die reine renderzeit, ohne darstellung etc gemessen).


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 10, 2009 09:42 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Apr 25, 2005 17:51
Beiträge: 464
Da du C++ magst und nicht C, nimm doch lieber auch die C++ Casts :D

_________________
__________
"C++ is the best language for garbage collection principally because it creates less garbage." Bjarne Stroustrup


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 10, 2009 10:04 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Weißt du in welchem "Modus" SSE bei dir arbeitet? SSE hat 2 Funktionen zum Laden von Daten in ein XMM Register. Eine für 16 Byte Alligned Daten und eine für nicht Aligned Daten. Die für 16 Byte Aligned ist ein gutes Stück schneller als die Andere. Also wenn du da eine Möglichkeit hast so etwas irgendwie einzustellen, dann solltest du davon Gebrauch machen.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 22 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 15 Queries | GZIP : On ]