Difference between revisions of "SSE/de"

From Free Pascal wiki
Jump to navigationJump to search
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Translate}}
+
{{LanguageBar}}
  
 
== SSE ==
 
== SSE ==
Mit der SSE-Erweiterung der Modernen CPUs, kann bis zu 8-9fache Geschwindigkeitssteigerung erzielen, gegenüber klassischen FPU-Operationen.<br>
+
 
Am besten werden 4x Vektoren und 4x4 Matrizen unterstützt, dies wird sehr viel bei OpenGL gebraucht. <br>
+
Mit der SSE-Erweiterung der Modernen CPUs, kann bis zu 8-9fache Geschwindigkeitssteigerung erzielen, gegenüber klassischen FPU-Operationen.
Die Assembler-Blöcke sind so angepasst, das sie auf 32Bit und 64Bit CPU laufen, vorausgesetzt, sie sind Intel kompatibel ARM (Raspberry) geht nicht, die haben einen anderen Befehlssatz.<br>
+
 
Folgende Beipiele sollte alle ab Intel-Core laufen.
+
Am besten werden 4x Vektoren und 4x4 Matrizen unterstützt, dies wird sehr viel bei OpenGL gebraucht.  
 +
 
 +
Die Assembler-Blöcke sind so angepasst, das sie auf 32Bit und 64Bit CPU laufen, vorausgesetzt, sie sind Intel kompatibel ARM (Raspberry) geht nicht, die haben einen anderen Befehlssatz.
 +
 
 +
Folgende Beispiele sollten alle ab Intel-Core laufen.
 +
 
 +
 
 +
Teilweise, kann Lazarus von Haus auf SSE und AVX verwenden, dafür muss folgendes unter ''"Projekt --> Projekteinstellungen... --> Benutzerdefinierte Einstellungen"'' ergänzt werden:
 +
<pre>
 +
-al
 +
-CfAVX2
 +
-CpCOREAVX2
 +
-O3
 +
-Sv
 +
-OpCOREAVX2
 +
-OoFASTMATH
 +
</pre>
 +
 
 +
Dies hat auf die direkten Assembler Funktionen keinen Einfluss.
  
 
=== Hilfs- Deklarationen und Funktionen ===
 
=== Hilfs- Deklarationen und Funktionen ===
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
{$asmmode intel}
 
{$asmmode intel}
  
Line 23: Line 42:
 
procedure WriteVector(v: TVector4f);
 
procedure WriteVector(v: TVector4f);
 
begin
 
begin
   WriteLn(v[0]: 8: 4, '  ', v[1]: 8: 4, '  ', v[2]: 8: 4, '  ', v[3]: 8: 4, '  ');
+
   WriteLn(v[0]: 8: 4, '  ', v[1]: 8: 4, '  ', v[2]: 8: 4, '  ', v[3]: 8: 4);
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 30: Line 49:
  
 
==== Vektoren Addieren ====
 
==== Vektoren Addieren ====
 +
 
Klassisch:
 
Klassisch:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
Result[0] := v0[0] + v1[0];
 
Result[0] := v0[0] + v1[0];
 
Result[1] := v0[1] + v1[1];
 
Result[1] := v0[1] + v1[1];
Line 39: Line 60:
  
 
SSE beschleunigt:
 
SSE beschleunigt:
<syntaxhighlight>
+
 
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler;  
+
<syntaxhighlight lang="pascal">
 +
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;  
 
asm
 
asm
 
         Movups  Xmm0, [v0]
 
         Movups  Xmm0, [v0]
Line 50: Line 72:
  
 
==== Vektoren Subtrahieren ====
 
==== Vektoren Subtrahieren ====
 +
 
Klassisch:
 
Klassisch:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
Result[0] := v0[0] - v1[0];
 
Result[0] := v0[0] - v1[0];
 
Result[1] := v0[1] - v1[1];
 
Result[1] := v0[1] - v1[1];
Line 59: Line 83:
  
 
SSE beschleunigt:
 
SSE beschleunigt:
<syntaxhighlight>
+
 
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler;  
+
<syntaxhighlight lang="pascal">
 +
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register; 
 
asm
 
asm
 
         Movups  Xmm0, [v0]
 
         Movups  Xmm0, [v0]
Line 70: Line 95:
  
 
==== Vektoren Multiplizieren ====
 
==== Vektoren Multiplizieren ====
 +
 
Klassisch:
 
Klassisch:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
Result[0] := v0[0] * v1[0];
 
Result[0] := v0[0] * v1[0];
 
Result[1] := v0[1] * v1[1];
 
Result[1] := v0[1] * v1[1];
Line 79: Line 106:
  
 
SSE beschleunigt:
 
SSE beschleunigt:
<syntaxhighlight>
+
 
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler;
+
<syntaxhighlight lang="pascal>
 +
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;  
 
asm
 
asm
 
         Movups  Xmm0, [v0]
 
         Movups  Xmm0, [v0]
Line 90: Line 118:
  
 
==== Vektoren Dividieren ====
 
==== Vektoren Dividieren ====
 +
 
Klassisch:
 
Klassisch:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
Result[0] := v0[0] / v1[0];
 
Result[0] := v0[0] / v1[0];
 
Result[1] := v0[1] / v1[1];
 
Result[1] := v0[1] / v1[1];
Line 99: Line 129:
  
 
SSE beschleunigt:
 
SSE beschleunigt:
<syntaxhighlight>
+
 
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler;
+
<syntaxhighlight lang="pascal">
 +
function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;  
 
asm
 
asm
 
         Movups  Xmm0, [v0]
 
         Movups  Xmm0, [v0]
Line 110: Line 141:
  
 
==== Vektoren Tauschen ====
 
==== Vektoren Tauschen ====
 +
 
Klassisch:
 
Klassisch:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
Result[0] := v[3];
 
Result[0] := v[3];
 
Result[1] := v[2];
 
Result[1] := v[2];
Line 119: Line 152:
  
 
SSE beschleunigt:
 
SSE beschleunigt:
<syntaxhighlight>
+
 
function Vec_Swap(const v: TVector4f): TVector4f; assembler;
+
<syntaxhighlight lang="pascal">
 +
function Vec_Swap(const v: TVector4f): TVector4f; assembler; nostackframe; register;  
 
asm
 
asm
 
         Movups  Xmm0, [v]
 
         Movups  Xmm0, [v]
Line 129: Line 163:
  
 
==== Vektoren Skalieren ====
 
==== Vektoren Skalieren ====
 +
 
Klassisch:
 
Klassisch:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
Result[0] := v[0] * f;
 
Result[0] := v[0] * f;
 
Result[1] := v[1] * f;
 
Result[1] := v[1] * f;
Line 138: Line 174:
  
 
SSE beschleunigt:
 
SSE beschleunigt:
<syntaxhighlight>
+
 
function Vec_Multiply_All(const v: TVector4f; f: Single): TVector4f; assembler; inline;
+
<syntaxhighlight lang="pascal">
 +
function Vec_Multiply_All(const v: TVector4f; f: Single): TVector4f; assembler; nostackframe; register;  
 
asm
 
asm
 
Movss  Xmm0, f
 
Movss  Xmm0, f
Line 151: Line 188:
 
=== Beispiele ===
 
=== Beispiele ===
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 
procedure TForm1.Button1Click(Sender: TObject);
 
procedure TForm1.Button1Click(Sender: TObject);
 
var
 
var
Line 196: Line 233:
  
 
=== Vektoren multiplizieren ===
 
=== Vektoren multiplizieren ===
 +
 
Vektor mit einer Matrix multiplizieren.
 
Vektor mit einer Matrix multiplizieren.
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
  
 
{$asmmode intel}
 
{$asmmode intel}
  
function VectorMultiplySSE(const mat: TMatrix; const vec: TVector4f): TVector4f; assembler;
+
function VectorMultiplySSE(const mat: TMatrix; const vec: TVector4f): TVector4f; assembler; nostackframe; register;  
 
asm
 
asm
 
         Movups Xmm4, [mat + $00]
 
         Movups Xmm4, [mat + $00]
Line 234: Line 272:
  
 
=== Matrizen multiplizieren ===
 
=== Matrizen multiplizieren ===
2 Matrizen mutiplizieren.<br>
+
 
 +
2 Matrizen mutiplizieren.
 +
 
 
Für eine Matrix-Multiplikation, hat man mit SSE etwa 8-9fache Geschwindigkeitssteigerung, gegenüber klassichen Single-Multiplikationen.
 
Für eine Matrix-Multiplikation, hat man mit SSE etwa 8-9fache Geschwindigkeitssteigerung, gegenüber klassichen Single-Multiplikationen.
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
  
 
{$asmmode intel}
 
{$asmmode intel}
  
function MatrixMultiplySSE(const M0, M1: TMatrix): TMatrix; assembler;
+
function MatrixMultiplySSE(const M0, M1: TMatrix): TMatrix; assembler; nostackframe; register;  
 
asm
 
asm
 
         Movups Xmm4, [M0 + $00]
 
         Movups Xmm4, [M0 + $00]
Line 336: Line 376:
  
 
[[Category:Free Pascal Programmers Guide/de]]
 
[[Category:Free Pascal Programmers Guide/de]]
 +
{{AutoCategory}}

Latest revision as of 08:24, 19 January 2020

Deutsch (de)

SSE

Mit der SSE-Erweiterung der Modernen CPUs, kann bis zu 8-9fache Geschwindigkeitssteigerung erzielen, gegenüber klassischen FPU-Operationen.

Am besten werden 4x Vektoren und 4x4 Matrizen unterstützt, dies wird sehr viel bei OpenGL gebraucht.

Die Assembler-Blöcke sind so angepasst, das sie auf 32Bit und 64Bit CPU laufen, vorausgesetzt, sie sind Intel kompatibel ARM (Raspberry) geht nicht, die haben einen anderen Befehlssatz.

Folgende Beispiele sollten alle ab Intel-Core laufen.


Teilweise, kann Lazarus von Haus auf SSE und AVX verwenden, dafür muss folgendes unter "Projekt --> Projekteinstellungen... --> Benutzerdefinierte Einstellungen" ergänzt werden:

-al
-CfAVX2
-CpCOREAVX2
-O3
-Sv
-OpCOREAVX2
-OoFASTMATH

Dies hat auf die direkten Assembler Funktionen keinen Einfluss.

Hilfs- Deklarationen und Funktionen

{$asmmode intel}

type
  TVector4f = array[0..3] of Single;
  TMatrix   = array[0..3] of TVector4f;

var
  a: TVector4f = (1.0, 2.0, 3.0, 4.0);
  b: TVector4f = (5.0, 6.0, 7.0, 8.0);
  c: TVector4f;
  f: single    = 2.0;

procedure WriteVector(v: TVector4f);
begin
  WriteLn(v[0]: 8: 4, '  ', v[1]: 8: 4, '  ', v[2]: 8: 4, '  ', v[3]: 8: 4);
end;

Die wichtigsten Vektor-Operationen

Vektoren Addieren

Klassisch:

Result[0] := v0[0] + v1[0];
Result[1] := v0[1] + v1[1];
Result[2] := v0[2] + v1[2];
Result[3] := v0[3] + v1[3];

SSE beschleunigt:

function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register; 
asm
         Movups  Xmm0, [v0]
         Movups  Xmm1, [v1]
         Addps   Xmm1, Xmm0
         Movups  [Result], Xmm1
end;

Vektoren Subtrahieren

Klassisch:

Result[0] := v0[0] - v1[0];
Result[1] := v0[1] - v1[1];
Result[2] := v0[2] - v1[2];
Result[3] := v0[3] - v1[3];

SSE beschleunigt:

function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;  
asm
         Movups  Xmm0, [v0]
         Movups  Xmm1, [v1]
         Subps   Xmm1, Xmm0
         Movups  [Result], Xmm1  
end;

Vektoren Multiplizieren

Klassisch:

Result[0] := v0[0] * v1[0];
Result[1] := v0[1] * v1[1];
Result[2] := v0[2] * v1[2];
Result[3] := v0[3] * v1[3];

SSE beschleunigt:

function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register; 
asm
         Movups  Xmm0, [v0]
         Movups  Xmm1, [v1]
         Mulps   Xmm1, Xmm0
         Movups  [Result], Xmm1  
end;

Vektoren Dividieren

Klassisch:

Result[0] := v0[0] / v1[0];
Result[1] := v0[1] / v1[1];
Result[2] := v0[2] / v1[2];
Result[3] := v0[3] / v1[3];

SSE beschleunigt:

function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register; 
asm
         Movups  Xmm0, [v0]
         Movups  Xmm1, [v1]
         Divps   Xmm1, Xmm0
         Movups  [Result], Xmm1  
end;

Vektoren Tauschen

Klassisch:

Result[0] := v[3];
Result[1] := v[2];
Result[2] := v[1];
Result[3] := v[0];

SSE beschleunigt:

function Vec_Swap(const v: TVector4f): TVector4f; assembler; nostackframe; register; 
asm
         Movups  Xmm0, [v]
         Pshufd  Xmm1,Xmm0, $1b
         Movups  [Result], Xmm1
end;

Vektoren Skalieren

Klassisch:

Result[0] := v[0] * f;
Result[1] := v[1] * f;
Result[2] := v[2] * f;
Result[3] := v[3] * f;

SSE beschleunigt:

function Vec_Multiply_All(const v: TVector4f; f: Single): TVector4f; assembler; nostackframe; register; 
asm
Movss   Xmm0, f
Pshufd  Xmm0, Xmm0, $00
Movups  Xmm1, [v]
Mulps   Xmm1,Xmm0
Movups  [Result], Xmm1
end;

Beispiele

procedure TForm1.Button1Click(Sender: TObject);
var
  a: TVector4f = (1.0, 2.0, 3.0, 4.0);
  b: TVector4f = (5.0, 6.0, 7.0, 8.0);
  c: TVector4f;

  f: single = 2.0;

begin
  WriteLn('Addieren');
  c := Vec_Add(a, b);
  WriteVector(c);
  WriteLn();

  WriteLn('Subtrahieren');
  c := Vec_Sub(b, a);
  WriteVector(c);
  WriteLn();

  WriteLn('Multipizieren');
  c := Vec_Multiply(b, a);
  WriteVector(c);
  WriteLn();

  WriteLn('Dividieren');
  c := Vec_Divide(b, a);
  WriteVector(c);
  WriteLn();

  WriteLn('Vertauschen');
  c := Vec_Swap(a);
  WriteVector(c);
  WriteLn();

  WriteLn('Alle Multipizieren');
  f := 2.2;
  c:=Vec_Multiply_All(a, f);
  WriteVector(c);
  WriteLn();

end;

Vektoren multiplizieren

Vektor mit einer Matrix multiplizieren.

{$asmmode intel}

function VectorMultiplySSE(const mat: TMatrix; const vec: TVector4f): TVector4f; assembler; nostackframe; register; 
asm
         Movups Xmm4, [mat + $00]
         Movups Xmm5, [mat + $10]
         Movups Xmm6, [mat + $20]
         Movups Xmm7, [mat + $30]
         Movups Xmm2, [vec]

         // Zeile 0
         Pshufd Xmm0, Xmm2, 00000000b
         Mulps  Xmm0, Xmm4

         // Zeile 1
         Pshufd Xmm1, Xmm2, 01010101b
         Mulps  Xmm1, Xmm5
         Addps  Xmm0, Xmm1

         // Zeile 2
         Pshufd Xmm1, Xmm2, 10101010b
         Mulps  Xmm1, Xmm6
         Addps  Xmm0, Xmm1

         // Zeile 3
         Pshufd Xmm1, Xmm2, 11111111b
         Mulps  Xmm1, Xmm7
         Addps  Xmm0, Xmm1

         Movups [Result], Xmm0
end;

Matrizen multiplizieren

2 Matrizen mutiplizieren.

Für eine Matrix-Multiplikation, hat man mit SSE etwa 8-9fache Geschwindigkeitssteigerung, gegenüber klassichen Single-Multiplikationen.

{$asmmode intel}

function MatrixMultiplySSE(const M0, M1: TMatrix): TMatrix; assembler; nostackframe; register; 
asm
         Movups Xmm4, [M0 + $00]
         Movups Xmm5, [M0 + $10]
         Movups Xmm6, [M0 + $20]
         Movups Xmm7, [M0 + $30]

         // Spalte 0
         Movups Xmm2, [M1 + $00]

         Pshufd Xmm0, Xmm2, 00000000b
         Mulps  Xmm0, Xmm4

         Pshufd Xmm1, Xmm2, 01010101b
         Mulps  Xmm1, Xmm5
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 10101010b
         Mulps  Xmm1, Xmm6
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 11111111b
         Mulps  Xmm1, Xmm7
         Addps  Xmm0, Xmm1

         Movups [Result + $00], Xmm0

         // Spalte 1
         Movups Xmm2, [M1 + $10]

         Pshufd Xmm0, Xmm2, 00000000b
         Mulps  Xmm0, Xmm4

         Pshufd Xmm1, Xmm2, 01010101b
         Mulps  Xmm1, Xmm5
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 10101010b
         Mulps  Xmm1, Xmm6
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 11111111b
         Mulps  Xmm1, Xmm7
         Addps  Xmm0, Xmm1

         Movups   [Result + $10], Xmm0

         // Spalte 2
         Movups  Xmm2, [M1 + $20]

         Pshufd Xmm0, Xmm2, 00000000b
         Mulps  Xmm0, Xmm4

         Pshufd Xmm1, Xmm2, 01010101b
         Mulps  Xmm1, Xmm5
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 10101010b
         Mulps  Xmm1, Xmm6
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 11111111b
         Mulps  Xmm1, Xmm7
         Addps  Xmm0, Xmm1

         Movups [Result + $20], Xmm0

         // Spalte 3
         Movups Xmm2, [M1 + $30]

         Pshufd Xmm0, Xmm2, 00000000b
         Mulps  Xmm0, Xmm4

         Pshufd Xmm1, Xmm2, 01010101b
         Mulps  Xmm1, Xmm5
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 10101010b
         Mulps  Xmm1, Xmm6
         Addps  Xmm0, Xmm1

         Pshufd Xmm1, Xmm2, 11111111b
         Mulps  Xmm1, Xmm7
         Addps  Xmm0, Xmm1

         Movups [Result + $30], Xmm0
end;


Autor: Mathias