AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

PhysicEngine, Fragen zur Datenstruktur

Ein Thema von dmdjt · begonnen am 21. Aug 2014 · letzter Beitrag vom 21. Aug 2014
Antwort Antwort
Seite 2 von 2     12   
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#11

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 17:54
Au0erdem - "x, y, z: Array of Double" ist totaler Quatsch! Bitte nimm den "TPunkt" Datentyp.
Bei dieser Art der Verarbeitung ist es kein Quatsch. Das wichtigste ist dabei, dass man so schnell wie nur möglich durch alle Punkte durchrauschen kann, und wenn man sich dabei die Dereferenzierung zu Records spart, ist gar nicht mal so wenig gewonnen. Ich hatte mal aus Spaß eine Stoff-Simulation gebaut (ich komm gerade ums Verrecken nicht mehr auf den Namen vom Algo), und bin am Ende ebenfalls bei Arrays für X und Y (war nur 2D) gelandet, und habe die Relationen mittels Pointern hergestellt. Damit war dann auch ein "Kreuz-Verfedertes" Tuch mit 80x80 Vertices noch schnell genug auf dem Core2Duo damals für ~30fps.
Die "saubere" Vorversion mit Kapeslung und allem ganz hübsch in Hochglanz kam da bei weitem nicht hinter her. So lange man nachher nach aussen alles schön verpackt, finde ich es hier ausnahmsweise mal okay die Datentypen dem Zweck unterzuordnen.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
dmdjt

Registriert seit: 19. Jul 2009
37 Beiträge
 
Delphi 2007 Enterprise
 
#12

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 18:04
Aphton:

Mir ist klar, wie das aussieht und dass es wirklich, wirklich nicht schön ist. Aber wenn ich die so anlege und nicht in einem Record, scheint es zumindest in meinem Test etwa 10% schneller zu sein.
Delphi-Quellcode:
x,y,z : array of double;
z[i] := x[i]*y[i];

//vs.
a: array of TPoint;
a[i].z := a[i].x*a[i].y;
Anstatt das letzte Element zu verschieben, will ich es ja eh einfach nur als gelöscht markieren und dann beim Erstellen eines neuen Elements neu befüllen und reaktivieren. Davor hatte ich vor Namenlosers Einwand irgendwie ein ungutes Gefühl... aber eigentlich ist es eh ganz klar.
Auf die Art hab ich auch von außerhalb der Engine eine immer gültige Adresse für ein bestimmtes Element und kann dort so tun, als würde ich mit Objekten hantieren.

Dejan Vu:

Danke für die Tipperei!

Vom Prinzip her werde ich es ganz ähnlich aufbauen.

Ich hab weniger ein Problem das ganze umzusetzen, als dass ich mich vor ein paar Problemen beim Design wiedergefunden habe.

Danke übrigens an alle
  Mit Zitat antworten Zitat
dmdjt

Registriert seit: 19. Jul 2009
37 Beiträge
 
Delphi 2007 Enterprise
 
#13

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 18:07
Der Algo hieß ziemlich sicher Verlet Integration

Habs davor einfach per Euler versucht, aber das wird einfach zu instabil. Deswegen muss man Dämpfungen unnatürlich hoch einstellen und alles wirkt wie unter Wasser oder Honig
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#14

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 18:30
Ok, meinetwegen...
Aber in 98% aller Fälle ist das Unfug, da es nicht notwendig ist, solche Optimierungen bereits zu machen. Erst makro, dann micro - vlt habe ich mich beim TE auch nur vertan und er ist auch schon soweit und hat alle Makro-Probleme optimiert..

Edit: Ok, nochmal zurück zu dem; so ganz überzeugt bin ich nicht.
Die Verwendung von Structs/Records sollte in deinem Fall schon schneller sein, wenn man überlegt..:
Array[INDEX] ==> <Größe_Array_Datentype> * Index
--> 3 Multiplikationen schon allein für die Indizierung von x, y und z..
Hätte man stattdessen vergleichsweise ein Record benützt, so hätte man nur 1x Multiplikation für die Indizierung und 2x Additionen für die Offsets im Record/Struct (für x wird nichts addiert, da es sich am Anfang befindet).
Jetzt sagt bloß nicht, dass 1x Mul & 2x Add langsamer ist als 3x Mul
oO

Hab hier kein Delphi zur Hand, deshalb weiß ich leider ned, was der genau für nen Assembler Code ausspuckt, könnte das ganze aber mit C++ testen..
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (21. Aug 2014 um 18:42 Uhr)
  Mit Zitat antworten Zitat
dmdjt

Registriert seit: 19. Jul 2009
37 Beiträge
 
Delphi 2007 Enterprise
 
#15

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 18:57
Das würde mich ziemlich interessieren!

Assembler verstehe ich zu wenig... und das beißt mir jetzt ein wenig in den A****. Meine Erfahrungen sind leider nie über PIC-Assembler gestiegen. Insofern würde mich das wirklich sehr interessieren!
Von dem her, was Du da schreibst, klingt es mehr als logisch.

Ich bilde mir ein, im Laufe meiner Recherchen gelesen zu haben, dass dieser Aufbau dem Prozessor/Pipeline/ka was entgegenkommt. Aber das habe ich zu wenig verstanden und eher überlesen. Wenn ich es wieder finde, poste ich es.

Ich kann mir allerdings sehr gut vorstellen, dass der Compiler nur eine einzelne Multiplikation daraus macht, weil die Array-Elemente alle double sind und der index auch überall der gleiche ist.
Falls er das so optimiert, dann wäre es auch nur eine Multiplikation + 2x Add.
Vielleicht gleicht sich dann das eine Add durch die Dereferenzierung und weil er die Abstände fürs struct (für die 2 Add) mittragen muss aus?

Geändert von dmdjt (21. Aug 2014 um 18:59 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#16

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 19:04
Verlet! Danke

Ich vermute fast, das bei Arrays der schwerer wiegende Anteil ist, dass diese hübsch am Stück im Speicher liegen und nacheinander sehr effizient abgefuttert werden können, auch wenn die Referenzierung am Ende vielleicht mehr Aufwand ist. (Wen das stört, der kann über ein Array auch noch mit Pointer-Arithmetik iterieren, wieder ein Sparpotenzial, dass eine Sammlung von "losen" Records nicht böte.)

Ich will das auch gar nicht beschönigen, das sieht am Ende etwas aus wie Code aus den 80ern. Aber das ist einer der seltenen Fälle, wo ich es aus eigener Erfahrung mit Ausprobieren mehrerer Varianten gerechtfertigt finde. (Grafikkarten legen sich ihre Streams intern nach Möglichkeit nicht ohne Grund aehr ähnlich aus. Stream-Processing macht bei den üblichen Architekturen einfach was aus.)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
dmdjt

Registriert seit: 19. Jul 2009
37 Beiträge
 
Delphi 2007 Enterprise
 
#17

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 19:20
Das komische ist, dass p: array of Tpoint langsamer als x,y,z: of double ist. Zumindest bei dem oben beschrieben Test.

Ich verstehe davon leider zu wenig und hab nie den richtigen Zugang gefunden. Da fehlt mir einiges...
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#18

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 19:28
Verlet! Danke

Ich vermute fast, das bei Arrays der schwerer wiegende Anteil ist, dass diese hübsch am Stück im Speicher liegen und nacheinander sehr effizient abgefuttert werden können, auch wenn die Referenzierung am Ende vielleicht mehr Aufwand ist.
Das ist genauso auch bei Array of Record's der Fall.
Ein Rekord gibt ja nur an, wie viel Speicher benötigt wird und wie man an die einzelnen Elemente rankommt (Delphi-Record <> Delphi-Class)

Ich habs nun getestet und erstaunlicherweise ist deine Variante doch schneller..
Code:
#define ARR_SIZE 1024 * 1024 /* 1mb */
#define REPETITIONS   3000

double x[ARR_SIZE];
double y[ARR_SIZE];
double z[ARR_SIZE];
point xyz[ARR_SIZE];

int main(int argc, char **args) {
   const double val = 123.456;

   // cpu-warmup
   for (int i = 0; i < REPETITIONS; i++) { }

   // test #1
   int t = get_tick_count_ms();
   for (int i = 0; i < REPETITIONS; i++)
      for (int j = 0; j < ARR_SIZE; j++)
         x[j] = y[j] = z[j] = val;
   t = get_tick_count_ms() - t;
   printf("Test #1\t %dms\t x[], y[], z[]\n", t);

   // test #2
   t = get_tick_count_ms();
   for (int i = 0; i < REPETITIONS; i++) {
      double *x_ptr = &x[0];
      double *y_ptr = &y[0];
      double *z_ptr = &z[0];
      for (int j = 0; j < ARR_SIZE; j++)
         *x_ptr++ = *y_ptr++ = *z_ptr++ = val;
   }
   t = get_tick_count_ms() - t;
   printf("Test #2\t %dms\t x_ptr, y_ptr, z_ptr\n", t);

   // test #3
   t = get_tick_count_ms();
   for (int i = 0; i < REPETITIONS; i++) {
      for (int j = 0; j < ARR_SIZE; j++)
         xyz[j].x = xyz[j].y = xyz[j].z = val;
   }
   t = get_tick_count_ms() - t;
   printf("Test #2\t %dms\t xyz[]\n", t);

   // test #4
   t = get_tick_count_ms();
   for (int i = 0; i < REPETITIONS; i++) {
      point *xyz_ptr = &xyz[0];
      for (int j = 0; j < ARR_SIZE; j++)
         xyz_ptr++->x = xyz_ptr->y = xyz_ptr->z = val;
   }
   t = get_tick_count_ms() - t;
   printf("Test #2\t %dms\t xyz_ptr\n", t);
}
Code:
Test #1    12338ms    x[], y[], z[]
Test #2    11623ms    x_ptr, y_ptr, z_ptr
Test #2    17074ms    xyz[]
Test #2    13396ms    xyz_ptr
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (21. Aug 2014 um 19:31 Uhr)
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#19

AW: PhysicEngine, Fragen zur Datenstruktur

  Alt 21. Aug 2014, 19:30
@Aphton: Ich weiß nicht mehr genau, wo ich es ursprünglich gelesen hatte, aber für hohe Performance wird soweite ich weiß gerade empfohlen, Structs of Arrays zu verwenden statt Arrays of Structs. Den genauen Grund weiß ich nicht mehr, aber es hatte glaube ich irgendwas mit Cache und Vectorization zu tun (wobei der Delphi-Compiler letzteres wohl sowieso nicht unterstützt).
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:55 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz