Vector3 vs. Vector2 - Leistung, Nutzung?

8

Ich spiele gerade mit XNA herum und erstelle einen einfachen 2D-Plattformer. Ich dachte daran, mehrere Ebenen hinzuzufügen, um es ein wenig herausfordernd zu machen.

Anstatt ein Vector2für meine Positionen zu haben, verwende ich jetzt ein Vector3, nur um es Zals Ebenentiefe zu verwenden. Da Sie jedoch keine Operatoren zwischen Vector2und Vector3aus einem unbekannten Grund verwenden können [1] , habe ich letztendlich alle anderen Vector2s in meinem Spiel geändert, z. B. Beschleunigung , Geschwindigkeit und Versatz , damit ich Dinge wie position += offsetohne Fehler tun kann.

Ich habe auch meine Rotationsvariable von floatauf geändert Vector3und verwende den ZWert, um meine Texturen zu drehen. Ich habe vor, meine Texturen mit Xund Yzu skalieren, damit Sie den Super Paper Mario-Effekt erhalten.

Nachdem ich all diese Vector2s in Vector3s geändert hatte, fühlte ich mich ein wenig schlecht dabei. Wie wirkt sich das auf die Leistung von Spielen aus? Ich weiß, ich sollte mir in meinem kleinen Plattformspiel keine Sorgen um die Leistung machen müssen, aber ich bin nur neugierig darauf.

Gibt es eine bemerkenswerte Leistung zwischen Vector2s und Vector3s, zum Beispiel beim Hinzufügen oder Multiplizieren sie, oder wenn Sie anrufen Normalize, Transformoder Distance?


[1] Nur eine Nebenfrage: Warum gibt es keine Operatoren für Berechnungen zwischen Vector3 und Vector2?

Rudey
quelle

Antworten:

13

Gibt es eine bemerkenswerte Leistung zwischen Vector2s und Vector3s, zum Beispiel beim Hinzufügen oder Multiplizieren sie, oder wenn Sie anrufen Normalize, Transformoder Distance?

Ja, Sie haben noch eine Koordinate, sodass Sie mehr CPU-Zyklen verwenden.

Aber es ist sehr unwahrscheinlich, dass es Ihnen jemals Probleme bereiten wird. XNA 4 verwendet SIMD-Erweiterungen für die Vektormathematik (BEARBEITEN: nur unter Windows Phone ), sodass die Implementierung (auf dieser Plattform) sehr optimal ist. Außer wenn Sie sehr viel arbeiten, ist es sehr unwahrscheinlich, dass Sie jemals Probleme bekommen. Sie benötigen Vector3s für Ihre Positionen, da Sie jetzt 3D (oder 2.5D ...) ausführen. Führen Sie daher keine vorzeitige Optimierung durch. Das ist 97% böse 1 .

Nur eine Nebenfrage: Warum gibt es keine Operatoren für Berechnungen zwischen Vector3 und Vector2?

Weil es mathematisch keinen Sinn macht. Was würden Sie von solchen Berechnungen erwarten? Was soll zum Beispiel passieren, wenn Sie versuchen, a Vector3und a hinzuzufügen Vector2:

[ x1, y1, z1 ] + [ x2, y2 ] = [ x1 + x2, y1 + y2, z1 ] oder [ x1, y1 + x2, z1 + y2 ]?

In diesem Fall müssen Sie normalerweise selbst bestimmen, was Sie als dritte Koordinate für die Vector2möchten und wo Sie sie hinzufügen möchten. Zum Beispiel löst dies die Mehrdeutigkeit:

[ x1, y1, z1 ] + [ x2, y2, 0 ] = [ x1 + x2, y1 + y2, z1 ]


Jetzt ist es möglich, dass einige Teile Ihres Spiels nur in 2D funktionieren. Wenn es Fälle gibt , in denen Sie nur 2D - Koordinaten benötigen, und wenn die Rechen tut wirklich schwer bekommen (zB 2D - Physik), können Sie kleben Vector2s in diesem bestimmten Teil des Codes , um einige wertvolle Zyklen zu sparen. Sie können dann bei Bedarf einfach zwischen 2D- und 3D-Koordinaten wechseln (z. B. eine Szenenposition von einer 2D-Physikposition abrufen oder umgekehrt):

ZB von Vector2bis zur Vector3Verwendung dieses Konstruktors :

Vector2 v2;
Vector3 v3(v2, someDepthValue);

Oder von Vector3zur Vector2Verwendung dieses Konstruktors ;

Vector3 v3;
Vector2 v2(v3.X, v3.Y);

1 In Donald Knuths Worten :

Programmierer verschwenden enorm viel Zeit damit, über die Geschwindigkeit unkritischer Teile ihrer Programme nachzudenken oder sich darüber Gedanken zu machen, und diese Effizienzversuche wirken sich tatsächlich stark negativ aus, wenn Debugging und Wartung in Betracht gezogen werden. Wir sollten kleine Wirkungsgrade vergessen, etwa in 97% der Fälle: Vorzeitige Optimierung ist die Wurzel allen Übels . Dennoch sollten wir unsere Chancen bei diesen kritischen 3% nicht verpassen.

Laurent Couvidou
quelle
Wie gesagt, ich weiß, dass ich mich nicht so schnell um die Leistung kümmern muss, aber es war nur meine Neugier, die mich dazu brachte, diese Frage zu stellen. Ich denke, Sie haben Recht mit der Mehrdeutigkeit . Danke für die klare Antwort :)
Rudey
@RuudLenders Ich habe Details hinzugefügt, wie Sie vorgehen können, wenn Sie jemals auf Leistungsprobleme stoßen.
Laurent Couvidou
Ich habe Ihre Antwort so bearbeitet, dass sie einen sehr wichtigen Punkt enthält: SIMD wird nur von XNA unter Windows Phone verwendet! Die .NET-Laufzeit auf dem PC - und damit XNA selbst - unterstützt SIMD nicht. Das Äquivalent wird auch auf Xbox 360 nicht unterstützt.
Andrew Russell
(Auf PC und Xbox 360 ist das Verständnis der XNA Framework-Leistung immer noch der anwendbare Leitfaden zur Optimierung Ihrer Vektoroperationen.)
Andrew Russell
Vorzeitige Optimierung ist nicht böse. Nur nutzlose vorzeitige Optimierung ist. Sie müssen es aus Gründen der Nutzlosigkeit ausschließen , nicht aus Gründen der Frühgeburt.
Sam Hocevar
3

Sie versuchen vorzeitig zu optimieren. Die meisten der von Ihnen erwähnten Operationen (Normalisieren, Transformieren, Distanzieren) sind ziemlich identisch mit denen von vector2D. Wenn Sie sich den Code ansehen, werden Sie feststellen, dass sie praktisch gleich sind. Der einzige Unterschied besteht darin, dass vector3D eine dritte Achse hat. In Bezug auf die Leistung sollte es im Vergleich zu einem Vector2D trivial sein.

Zu Ihrer Nebenfrage:
Weil Sie keine Matrizen / Zeilenvektoren / Spaltenvektoren multiplizieren können, die beide unterschiedliche Größen haben.

Sidar
quelle
1

Einer der größten Leistungseffekte bei Vector3unnötiger Verwendung anstelle von Vector2ist die 50% ige Vergrößerung und die Auswirkung auf den Cache .

Diese unnötigen zusätzlichen Daten müssen aus dem Hauptspeicher in den CPU-Cache geladen werden. Das ist langsam .

Durch das Laden dieser unnötigen Daten erhöhen Sie außerdem die Wahrscheinlichkeit, dass Sie nützliche Daten herausgeben, die dann sofort wieder in den Cache geladen werden müssen .

In einer bescheiden engen Schleife überwältigen die Cache-Effekte alle CPU-Effekte, die durch zusätzliche Operationen entstehen.

Außerdem ist es schneller, die Elemente direkt hinzuzufügen (aufgrund verschiedener Macken von .NET). Wenn Sie also mikrooptimieren, werden Sie die Vektoroperationen sowieso nicht verwenden. Wenn Sie also nur die ersten beiden Elemente eines Vektors hinzufügen müssen, können Sie dies tun:

v1.X += v2.X; v1.Y += v2.Y;

Diese Art von Leistungsüberlegungen gelten jedoch nur für Dinge wie Teilchenmotoren, Physikmotoren usw. Also mach dir nicht zu viele Sorgen!

Andrew Russell
quelle
Ist manuelles Inlining trotz der zusätzlichen Unterstützung von SIMD immer noch der schnellste Weg?
Mikael Högström
1
@ MikaelHögström SIMD wird mit ziemlicher Sicherheit schneller sein - aber es ist nur auf der Windows Phone-Plattform verfügbar (siehe die Bearbeitung und Kommentare, die ich zu Laurent Couvidous Antwort gemacht habe).
Andrew Russell