![]() |
Delphi-Version: 10.2 Tokyo
Verbesserungsvorschläge für Vector3 Class
Ich hatte/habe Probleme eine simple, effiziente Vector3-Klasse zu finden, die außerdem auch zugriff via [] erlaubt. Habe also heute meine eigene geschrieben, habe ein paar Fragen dazu.
1) Ist es möglich Heap/Stack in Delphi immer 16 Byte zu alignen, dass ich movaps anstatt movups nutzen kann? Heap whs. via custom allocator, Stack finde ich gar keine Lösung zu. 2) Um movups überhaupt zu verwenden, musste ich 128 bit (Values: array[0..3] of Single) allocaten. Alternativ hätte ich movq/movss nutzen können, jetzt stellt sich mir allgemein die Frage was schneller ist und ob man das als extrem unschön ansehen sollte dass ich 4 anstatt 3 Singles ;) habe. Ich sehe halt das Problem, wenn man davon ausgeht dass es 3 Werte sind und SizeOf(TVector3) macht man überrascht sein könnte. 3) Kann man das mit dem property access "[]" so wie ich es gemacht habe verbesser? Ich habe extra keinen Index check, ich rede eher von anderen Methoden, wie ich es z.B. aus c++ gewöhnt war mit operator [] überschreiben. 4) In c++ hätte ich die Vectors als const referenz übergeben. Also hier ja dann eigtl. const var? Wie geht das? 5) Allgemeine verbesserungen Weiteres: Ich habe ![]() Danke für die Hilfe!
Delphi-Quellcode:
unit UnitVector3;
interface type TVector3 = record private FValues: array[0..3]of Single; function GetValue(AIndex: Integer): Single; inline; procedure SetValue(AIndex: Integer; AValue: Single); inline; public // properties property X: Single read FValues[0] write FValues[0]; property Y: Single read FValues[1] write FValues[1]; property Z: Single read FValues[2] write FValues[2]; property Values[AIndex: Integer]: Single read GetValue write SetValue; default; // funcs class function Create(const AX, AY, AZ: Single): TVector3; inline; static; procedure SetNormalize; function Normalize: TVector3; function Length: Single; function LengthSquared: Single; function Length2D: Single; function LengthSquared2D: Single; function Dot(const B: TVector3): Single; function Cross(const B: TVector3): TVector3; function Distance(const B: TVector3): Single; function DistanceSquared(const B: TVector3): Single; // operators class operator Negative(const A: TVector3): TVector3; inline; class operator Positive(const A: TVector3): TVector3; inline; class operator Equal(const A, B: TVector3): Boolean; inline; class operator NotEqual(const A, B: TVector3): Boolean; inline; // Vector mit Vector class operator Add(const A, B: TVector3): TVector3; class operator Subtract(const A, B: TVector3): TVector3; class operator Multiply(const A, B: TVector3): TVector3; class operator Divide(const A, B: TVector3): TVector3; // Vector mit Single class operator Add(const A: TVector3; const B: Single): TVector3; class operator Subtract(const A: TVector3; const B: Single): TVector3; class operator Multiply(const A: TVector3; const B: Single): TVector3; class operator Divide(const A: TVector3; const B: Single): TVector3; // Single mit Vector class operator Add(const A: Single; const B: TVector3): TVector3; class operator Subtract(const A: Single; const B: TVector3): TVector3; class operator Multiply(const A: Single; const B: TVector3): TVector3; class operator Divide(const A: Single; const B: TVector3): TVector3; end; implementation { TVector3 } class operator TVector3.Add(const A, B: TVector3): TVector3; assembler; asm movups xmm0, [A] movups xmm1, [B] addps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Add(const A: TVector3; const B: Single): TVector3; assembler; asm movups xmm0, [A] movss xmm1, [B] shufps xmm1, xmm1, 0 addps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Add(const A: Single; const B: TVector3): TVector3; assembler; asm movups xmm0, [B] movss xmm1, [A] shufps xmm1, xmm1, 0 addps xmm0, xmm1 movups [Result], xmm0 end; class function TVector3.Create(const AX, AY, AZ: Single): TVector3; begin Result.X := AX; Result.Y := AY; Result.Z := AZ; end; function TVector3.Cross(const B: TVector3): TVector3; assembler; asm movups xmm0, [Self] movups xmm1, [B] movaps xmm2, xmm0 movaps xmm3, xmm1 shufps xmm0, xmm0, $C9 shufps xmm1, xmm1, $D2 mulps xmm0, xmm1 shufps xmm2, xmm2, $D2 shufps xmm3, xmm3, $C9 mulps xmm2, xmm3 subps xmm0, xmm2 movups [Result], xmm0 end; function TVector3.Distance(const B: TVector3): Single; assembler; asm movups xmm0, [Self] movups xmm1, [B] subps xmm0, xmm1 dpps xmm0, xmm0, $71 sqrtps xmm0, xmm0 movss [Result], xmm0 end; function TVector3.DistanceSquared(const B: TVector3): Single; assembler; asm movups xmm0, [Self] movups xmm1, [B] subps xmm0, xmm1 dpps xmm0, xmm0, $71 movss [Result], xmm0 end; class operator TVector3.Divide(const A: Single; const B: TVector3): TVector3; assembler; asm movups xmm0, [B] movss xmm1, [A] shufps xmm1, xmm1, 0 divps xmm0, xmm1 movups [Result], xmm0 end; function TVector3.Dot(const B: TVector3): Single; assembler; asm movups xmm0, [Self] movups xmm1, [B] dpps xmm0, xmm1, $71 movss [Result], xmm0 end; class operator TVector3.Divide(const A: TVector3; const B: Single): TVector3; assembler; asm movups xmm0, [A] movss xmm1, [B] shufps xmm1, xmm1, 0 divps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Divide(const A, B: TVector3): TVector3; assembler; asm movups xmm0, [A] movups xmm1, [B] divps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Equal(const A, B: TVector3): Boolean; begin Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z); end; function TVector3.GetValue(AIndex: Integer): Single; begin Result := FValues[AIndex]; end; function TVector3.Length: Single; assembler; asm movups xmm0, [Self] dpps xmm0, xmm0, $71 sqrtps xmm0, xmm0 movss [Result], xmm0 end; function TVector3.Length2D: Single; assembler; asm movups xmm0, [Self] dpps xmm0, xmm0, $31 sqrtps xmm0, xmm0 movss [Result], xmm0 end; function TVector3.LengthSquared: Single; assembler; asm movups xmm0, [Self] dpps xmm0, xmm0, $71 movss [Result], xmm0 end; function TVector3.LengthSquared2D: Single; assembler; asm movups xmm0, [Self] dpps xmm0, xmm0, $31 movss [Result], xmm0 end; class operator TVector3.Multiply(const A: Single; const B: TVector3): TVector3; assembler; asm movups xmm0, [B] movss xmm1, [A] shufps xmm1, xmm1, 0 mulps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Multiply(const A: TVector3; const B: Single): TVector3; assembler; asm movups xmm0, [A] movss xmm1, [B] shufps xmm1, xmm1, 0 mulps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Multiply(const A, B: TVector3): TVector3; assembler; asm movups xmm0, [A] movups xmm1, [B] mulps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Negative(const A: TVector3): TVector3; begin Result.X := -A.X; Result.Y := -A.Y; Result.Z := -A.Z; end; function TVector3.Normalize: TVector3; assembler; asm movups xmm0, [Self] movaps xmm1, xmm0 dpps xmm0, xmm0, $7F rsqrtps xmm0, xmm0 mulps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.NotEqual(const A, B: TVector3): Boolean; begin Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z); end; class operator TVector3.Positive(const A: TVector3): TVector3; begin Result := A; end; procedure TVector3.SetNormalize; assembler; asm movups xmm0, [Self] movaps xmm1, xmm0 dpps xmm0, xmm0, $7F rsqrtps xmm0, xmm0 mulps xmm0, xmm1 movups [Self], xmm0 end; procedure TVector3.SetValue(AIndex: Integer; AValue: Single); begin FValues[AIndex] := AValue; end; class operator TVector3.Subtract(const A: Single; const B: TVector3): TVector3; assembler; asm movups xmm0, [B] movss xmm1, [A] shufps xmm1, xmm1, 0 subps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Subtract(const A: TVector3; const B: Single): TVector3; assembler; asm movups xmm0, [A] movss xmm1, [B] shufps xmm1, xmm1, 0 subps xmm0, xmm1 movups [Result], xmm0 end; class operator TVector3.Subtract(const A, B: TVector3): TVector3; assembler; asm movups xmm0, [A] movups xmm1, [B] subps xmm0, xmm1 movups [Result], xmm0 end; end. |
AW: Verbesserungsvorschläge für Vector3 Class
Zur Steuerung der Allokation gibt es die $A Direktive. Schon geschaut, ob die inzwischen auch 16 Byte ALlokation kann?
|
AW: Verbesserungsvorschläge für Vector3 Class
Zitat:
But it had to be multiplattform/CPU and 32/64. Perhaps you like to take a look at ![]() Mavarik |
AW: Verbesserungsvorschläge für Vector3 Class
Warum antwortest du auf englisch? :gruebel:
|
AW: Verbesserungsvorschläge für Vector3 Class
Babylon.
Sieht gar nicht übel aus, aber grade bei so wildem Assembler-Kram - Gibt es keine Tests? |
AW: Verbesserungsvorschläge für Vector3 Class
Nun ja die Grundsatzfrage ist, ob das nur für ihn ist oder auch für andere. Das "und SizeOf(TVector3) macht man überrascht sein könnte." deutet vielleicht eher auf letzteres. Dann fehlt auch noch Doku, unter anderem zuerst was ein Vector3 denn ist. (In unser Software haben wir tausende an Vektor-Rechnungen, der Begriff ist mir noch nicht untergekommen, google hilft auch wenig weiter.)
Was für uns die unit unbrauchbar macht ist, dass die auf Single basiert und nicht auf Double. |
AW: Verbesserungsvorschläge für Vector3 Class
Zitat:
![]() ![]() Ist wohl nicht ganz so unüblich als Benennung. Also ein Vektor im Raum der durch die Koordinaten x, y, z definiert ist. Wie heißen denn eure Vektoren-Datentypen? |
AW: Verbesserungsvorschläge für Vector3 Class
Ich finde Vector3 eigentlich auch eindeutig als Namen.
Nur mir fehlt wirklich Doku, der Quelltext hilft mir leider nicht weiter. Stell es doch auf z.B. Github, der ein oder andere (z.B ich) macht sicher gerne ein paar Tests dafür... |
AW: Verbesserungsvorschläge für Vector3 Class
Hallo,
unter ![]() Nun ja, es gibt schon noch Unterschiede von (v)movups und (v)movaps. In den dort hintelegten Instruction tables von Prof. Agner kannst du das wunderbar für jeden Prozessor nachlesen. Das geht bis zu den Ryzens von AMD. Wahrscheinlich ist das derartig verallgemeinert worden, weil es kaum mehr große Unterschiede macht, ob die Mov-Befehle mit oder oder entsprechendes Alignment benutzt. Zu mindestens bei diesen relativ kleinen Jobs in deinen Routinen. Bei der Bearbeitung riesiger Datenmengen kann das allerdings immer noch einen Unterschied machen. Leider unterstützt Delphi noch immer kein AVX, AVX2, geschweige den AVX5212 mit all seinen Derivaten, direkt, so das man hier zu externen Assemblern greifen muss und dann die entsprechenden Object-Files einbinden muss. Gruß Thomas |
AW: Verbesserungsvorschläge für Vector3 Class
Zitat:
Keinen Plan... Sorry... War sicherlich gerade mit anderen im Chat... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:47 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz