Sollte ich diese Vektoren Klassen oder Strukturen in C # machen

7

Ich erstelle eine Geometriebibliothek in C # und ich benötige die folgenden unveränderlichen Typen:

  • Vector2f (2 float s - 8 Bytes)
  • Vector2d (2 double s - 16 Bytes)
  • Vector3f (3 float s - 12 Bytes)
  • Vector3d (3 double s - 24 Bytes)
  • Vector4f (4 float s - 16 Bytes)
  • Vector4d (4 double s - 32 Bytes)

Ich versuche herauszufinden, ob ich sie zu Strukturen oder Klassen machen soll. MSDN schlägt vor, nur eine Struktur zu verwenden, wenn die Größe nicht größer als 16 Byte sein soll. Diese Referenz scheint von 2005 zu sein. Sind 16 Bytes immer noch die maximal vorgeschlagene Größe?

Ich bin sicher, dass die Verwendung von Strukturen für die float Vektoren effizienter wäre als die Verwendung einer Klasse, aber was soll ich mit den double Vektoren machen? Soll ich ihnen Strukturen machen, damit sie konsistent sind, oder sollte ich ihnen Klassen geben?

Aktualisiert: Sieht so aus, als würden alle zustimmen, dass sie Strukturen sein sollten. Danke für die tollen Antworten.

    
dewald 18.04.2010, 20:25
quelle

8 Antworten

8

Das Microsoft XNA Framework verwendet Strukturen für sein Vector2 / 3 / 4 Datentypen. Diese enthalten Felder vom Typ float . Ich sehe nichts falsch daran, dasselbe zu tun; Die Verwendung von Feldern vom Typ double sollte keinen großen Unterschied machen.

    
dtb 18.04.2010, 20:32
quelle
4

Ich würde im Allgemeinen Typen wie diese Strukturen machen. Strukturen werden mit größerer Wahrscheinlichkeit auf dem Stapel platziert, und wenn Sie Arrays mit ihnen verwenden, können Sie viel bessere Leistung erzielen, als wenn Sie z. B. eine Liste & lt; & gt; von Objekten. Solange Sie sich von Operationen fernhalten, die dazu führen, dass Ihre Vektorklassen eingerahmt werden, ist die Struktur im Allgemeinen der leistungsfähigere Weg.

    
Dave Markle 18.04.2010 20:30
quelle
4

Unveränderbare Strukturen sind eine gute Wahl. Die Größenempfehlung auf MSDN ist die schwächste, 32 Byte sind nicht wirklich groß.

Das Hauptargument wäre, dass Vektoren wie einfache (numerische) Typen verwendet werden und eine Implementierung als Werttyp am besten geeignet ist.

Eine gute Parallele sind die neuen Komplexe und BigInteger Strukturen in dotNet 4

    
Henk Holterman 18.04.2010 21:25
quelle
3

Structs, definitiv. Warum? Nun, es ist Teil Gefühl, ich denke, ein Vektor fühlt sich einfach und benimmt sich wie ein Wert .

Rico Mariani hier gibt einige Gründe an, warum Werttypen für bestimmte ausgewählt wurden Typen für eine API (ich glaube nicht, dass es XNA ist, über die er spricht).

Und obwohl Effizienz hier eine Rolle spielt, denke ich nicht, dass es um Garbage Collection geht, sondern eher um Datendichte wie Rico sagt. Angenommen, Sie haben auch einen Vertex -Typ, der zwei Vector3 s enthält: a Vector3 für den normalen und% Vector3 für die Weltkoordinaten. Wenn Sie diese Typenklassen erstellt haben, würde ein Array mit 100 Vertex -Elementen bestehen aus:

  • 100 * 8 Bytes (8 Bytes glaube ich, der Overhead einer Klasse im Speicher, 4 Bytes für den Typ-Header und 4 Bytes für etwas anderes, ein GC-Handle?)
  • 100 * 4 Bytes (für die Zeiger im Array auf die Vertex -Elemente)
  • 200 * 4 Bytes (für die Zeiger von jedem Vertex zu den zwei Vector3 Elementen)
  • 200 * 8 Bytes (für den 8-Byte-Overhead, den Sie bezahlen, um Vector3 eine Klasse zu machen)
  • 200 * 12 Bytes (für die tatsächliche Nutzlast von 3 float pro Vector3 )

6000 Bytes (auf einem 32-Bit-System).

Als Werttyp ist es einfach 200 * 12 Bytes = 2400 Bytes. So viel effizienter im Raum, ganz zu schweigen von einem niedrigeren Grad an Indirektion beim Lesen des Arrays.

Wenn Sie jedoch viel Platz einnehmen, wird es nicht unbedingt langsam. Wenn Sie einen Werttyp falsch verwenden, kann das langsamer sein, als wenn Sie ihn zu einer Klasse machen, wie Ich habe es herausgefunden . Sie möchten sie auf jeden Fall so weit wie möglich an ref übergeben, vermeiden Sie es zu kopieren, aber dies gilt nicht für alle Operationen, also messen Sie. Ich denke, ich erinnere mich, dass das Skalarprodukt bei der Weitergabe von ref langsamer berechnet wurde, vielleicht weil es irgendwie eine Neuausrichtung verhinderte, indem es die IL größer machte. Aber nehmen Sie mein Wort dafür nicht, messen Sie einfach.

    
JulianR 18.04.2010 23:58
quelle
2

Meiner Meinung nach würde ich mit Strukturen dafür gehen, da sie am häufigsten auf dem Stapel zugewiesen würden, dies würde den Druck auf den GC reduzieren, so dass Ihre Anwendung reibungsloser laufen sollte.

Ein Tipp, Ihre Methoden, die auf den Strukturen existieren, sollten die Argumente wahrscheinlich als Ref- und Out-Argumente nehmen, dies wird den Umfang des Kopierens der Daten reduzieren, der stattfindet, wenn Strukturen übergeben und zurückgegeben werden.

    
Chris Taylor 18.04.2010 20:33
quelle
2

Wir haben kürzlich einige Mathe-Typen (vec3, vec4, Matrizen usw.) umgestellt, um Structs anstelle von Klassen zu verwenden. Außerdem wurde der GC-Druck etwas reduziert (wir hatten Hunderte von Megabyte Vec3) Zuweisungen über einen relativ kurzen Zeitraum, entdeckt über den CLR-Profiler).

Es ist interessant zu bemerken, dass die XNA-Implementierung von Vektoren & amp; Matrizen werden mit Strukturen erstellt. Sie können immer durch Verweis dorthin gehen, wo es angebracht ist, wenn Sie auch an der Leistung interessiert sind.

    
Mark Simpson 18.04.2010 20:34
quelle
0

Ich nehme an, Sie machen sich Sorgen wegen perf?

Wenn sie unveränderlich sind, sollten sie verhaltensmäßig identisch sein. Gehen Sie einfach mit einem, und wenn es sich herausstellt, dass es ein Perf-Problem gibt, wechseln Sie es später.

Wenn Sie überhaupt auf .NET CE abzielen, sollten Sie die Verwendung von Strukturen in Betracht ziehen, da der GC nicht so effizient ist wie die vollständige .NET-Implementierung.

    
kyoryu 18.04.2010 20:29
quelle
-1

Structs werden (normalerweise) auf dem Stack gespeichert, was sie möglicherweise effizienter macht, aber wahrscheinlich nicht genug, um einen spürbaren Unterschied zu machen.

Ссылка

    
Dave Swersky 18.04.2010 20:31
quelle

Tags und Links