Sign in Join
Wiki copytemporary

SSE/de: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: SSE/de

OldNewLine
1+## SSE
2+
3+Mit der SSE-Erweiterung der Modernen CPUs, kann bis zu 8-9fache Geschwindigkeitssteigerung erzielen, gegenüber klassischen FPU-Operationen.
4+
5+Am besten werden 4x Vektoren und 4x4 Matrizen unterstützt, dies wird sehr viel bei OpenGL gebraucht.
6+
7+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.
8+
9+Folgende Beispiele sollten alle ab Intel-Core laufen.
10+
11+Teilweise, kann Lazarus von Haus auf SSE und AVX verwenden, dafür muss folgendes unter *"Projekt --\> Projekteinstellungen... --\> Benutzerdefinierte Einstellungen"* ergänzt werden:
12+
13+ -al
14+ -CfAVX2
15+ -CpCOREAVX2
16+ -O3
17+ -Sv
18+ -OpCOREAVX2
19+ -OoFASTMATH
20+
21+Dies hat auf die direkten Assembler Funktionen keinen Einfluss.
22+
23+### Hilfs- Deklarationen und Funktionen
24+
25+``` pascal
26+{$asmmode intel}
27+
28+type
29+ TVector4f = array[0..3] of Single;
30+ TMatrix = array[0..3] of TVector4f;
31+
32+var
33+ a: TVector4f = (1.0, 2.0, 3.0, 4.0);
34+ b: TVector4f = (5.0, 6.0, 7.0, 8.0);
35+ c: TVector4f;
36+ f: single = 2.0;
37+
38+procedure WriteVector(v: TVector4f);
39+begin
40+ WriteLn(v[0]: 8: 4, ' ', v[1]: 8: 4, ' ', v[2]: 8: 4, ' ', v[3]: 8: 4);
41+end;
42+```
43+
44+### Die wichtigsten Vektor-Operationen
45+
46+#### Vektoren Addieren
47+
48+Klassisch:
49+
50+``` pascal
51+Result[0] := v0[0] + v1[0];
52+Result[1] := v0[1] + v1[1];
53+Result[2] := v0[2] + v1[2];
54+Result[3] := v0[3] + v1[3];
55+```
56+
57+SSE beschleunigt:
58+
59+``` pascal
60+function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;
61+asm
62+ Movups Xmm0, [v0]
63+ Movups Xmm1, [v1]
64+ Addps Xmm1, Xmm0
65+ Movups [Result], Xmm1
66+end;
67+```
68+
69+#### Vektoren Subtrahieren
70+
71+Klassisch:
72+
73+``` pascal
74+Result[0] := v0[0] - v1[0];
75+Result[1] := v0[1] - v1[1];
76+Result[2] := v0[2] - v1[2];
77+Result[3] := v0[3] - v1[3];
78+```
79+
80+SSE beschleunigt:
81+
82+``` pascal
83+function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;
84+asm
85+ Movups Xmm0, [v0]
86+ Movups Xmm1, [v1]
87+ Subps Xmm1, Xmm0
88+ Movups [Result], Xmm1
89+end;
90+```
91+
92+#### Vektoren Multiplizieren
93+
94+Klassisch:
95+
96+``` pascal
97+Result[0] := v0[0] * v1[0];
98+Result[1] := v0[1] * v1[1];
99+Result[2] := v0[2] * v1[2];
100+Result[3] := v0[3] * v1[3];
101+```
102+
103+SSE beschleunigt:
104+
105+\<syntaxhighlight lang="pascal\> function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register; asm
106+
107+`        Movups  Xmm0, [v0]`\
108+`        Movups  Xmm1, [v1]`\
109+`        Mulps   Xmm1, Xmm0`\
110+`        Movups  [Result], Xmm1  `
111+
112+end;
113+
114+</syntaxhighlight>
115+
116+#### Vektoren Dividieren
117+
118+Klassisch:
119+
120+``` pascal
121+Result[0] := v0[0] / v1[0];
122+Result[1] := v0[1] / v1[1];
123+Result[2] := v0[2] / v1[2];
124+Result[3] := v0[3] / v1[3];
125+```
126+
127+SSE beschleunigt:
128+
129+``` pascal
130+function Vec_Add(const v0, v1: TVector4f): TVector4f; assembler; nostackframe; register;
131+asm
132+ Movups Xmm0, [v0]
133+ Movups Xmm1, [v1]
134+ Divps Xmm1, Xmm0
135+ Movups [Result], Xmm1
136+end;
137+```
138+
139+#### Vektoren Tauschen
140+
141+Klassisch:
142+
143+``` pascal
144+Result[0] := v[3];
145+Result[1] := v[2];
146+Result[2] := v[1];
147+Result[3] := v[0];
148+```
149+
150+SSE beschleunigt:
151+
152+``` pascal
153+function Vec_Swap(const v: TVector4f): TVector4f; assembler; nostackframe; register;
154+asm
155+ Movups Xmm0, [v]
156+ Pshufd Xmm1,Xmm0, $1b
157+ Movups [Result], Xmm1
158+end;
159+```
160+
161+#### Vektoren Skalieren
162+
163+Klassisch:
164+
165+``` pascal
166+Result[0] := v[0] * f;
167+Result[1] := v[1] * f;
168+Result[2] := v[2] * f;
169+Result[3] := v[3] * f;
170+```
171+
172+SSE beschleunigt:
173+
174+``` pascal
175+function Vec_Multiply_All(const v: TVector4f; f: Single): TVector4f; assembler; nostackframe; register;
176+asm
177+Movss Xmm0, f
178+Pshufd Xmm0, Xmm0, $00
179+Movups Xmm1, [v]
180+Mulps Xmm1,Xmm0
181+Movups [Result], Xmm1
182+end;
183+```
184+
185+### Beispiele
186+
187+``` pascal
188+procedure TForm1.Button1Click(Sender: TObject);
189+var
190+ a: TVector4f = (1.0, 2.0, 3.0, 4.0);
191+ b: TVector4f = (5.0, 6.0, 7.0, 8.0);
192+ c: TVector4f;
193+
194+ f: single = 2.0;
195+
196+begin
197+ WriteLn('Addieren');
198+ c := Vec_Add(a, b);
199+ WriteVector(c);
200+ WriteLn();
201+
202+ WriteLn('Subtrahieren');
203+ c := Vec_Sub(b, a);
204+ WriteVector(c);
205+ WriteLn();
206+
207+ WriteLn('Multipizieren');
208+ c := Vec_Multiply(b, a);
209+ WriteVector(c);
210+ WriteLn();
211+
212+ WriteLn('Dividieren');
213+ c := Vec_Divide(b, a);
214+ WriteVector(c);
215+ WriteLn();
216+
217+ WriteLn('Vertauschen');
218+ c := Vec_Swap(a);
219+ WriteVector(c);
220+ WriteLn();
221+
222+ WriteLn('Alle Multipizieren');
223+ f := 2.2;
224+ c:=Vec_Multiply_All(a, f);
225+ WriteVector(c);
226+ WriteLn();
227+
228+end;
229+```
230+
231+### Vektoren multiplizieren
232+
233+Vektor mit einer Matrix multiplizieren.
234+
235+``` pascal
236+
237+{$asmmode intel}
238+
239+function VectorMultiplySSE(const mat: TMatrix; const vec: TVector4f): TVector4f; assembler; nostackframe; register;
240+asm
241+ Movups Xmm4, [mat + $00]
242+ Movups Xmm5, [mat + $10]
243+ Movups Xmm6, [mat + $20]
244+ Movups Xmm7, [mat + $30]
245+ Movups Xmm2, [vec]
246+
247+ // Zeile 0
248+ Pshufd Xmm0, Xmm2, 00000000b
249+ Mulps Xmm0, Xmm4
250+
251+ // Zeile 1
252+ Pshufd Xmm1, Xmm2, 01010101b
253+ Mulps Xmm1, Xmm5
254+ Addps Xmm0, Xmm1
255+
256+ // Zeile 2
257+ Pshufd Xmm1, Xmm2, 10101010b
258+ Mulps Xmm1, Xmm6
259+ Addps Xmm0, Xmm1
260+
261+ // Zeile 3
262+ Pshufd Xmm1, Xmm2, 11111111b
263+ Mulps Xmm1, Xmm7
264+ Addps Xmm0, Xmm1
265+
266+ Movups [Result], Xmm0
267+end;
268+```
269+
270+### Matrizen multiplizieren
271+
272+2 Matrizen mutiplizieren.
273+
274+Für eine Matrix-Multiplikation, hat man mit SSE etwa 8-9fache Geschwindigkeitssteigerung, gegenüber klassichen Single-Multiplikationen.
275+
276+``` pascal
277+
278+{$asmmode intel}
279+
280+function MatrixMultiplySSE(const M0, M1: TMatrix): TMatrix; assembler; nostackframe; register;
281+asm
282+ Movups Xmm4, [M0 + $00]
283+ Movups Xmm5, [M0 + $10]
284+ Movups Xmm6, [M0 + $20]
285+ Movups Xmm7, [M0 + $30]
286+
287+ // Spalte 0
288+ Movups Xmm2, [M1 + $00]
289+
290+ Pshufd Xmm0, Xmm2, 00000000b
291+ Mulps Xmm0, Xmm4
292+
293+ Pshufd Xmm1, Xmm2, 01010101b
294+ Mulps Xmm1, Xmm5
295+ Addps Xmm0, Xmm1
296+
297+ Pshufd Xmm1, Xmm2, 10101010b
298+ Mulps Xmm1, Xmm6
299+ Addps Xmm0, Xmm1
300+
301+ Pshufd Xmm1, Xmm2, 11111111b
302+ Mulps Xmm1, Xmm7
303+ Addps Xmm0, Xmm1
304+
305+ Movups [Result + $00], Xmm0
306+
307+ // Spalte 1
308+ Movups Xmm2, [M1 + $10]
309+
310+ Pshufd Xmm0, Xmm2, 00000000b
311+ Mulps Xmm0, Xmm4
312+
313+ Pshufd Xmm1, Xmm2, 01010101b
314+ Mulps Xmm1, Xmm5
315+ Addps Xmm0, Xmm1
316+
317+ Pshufd Xmm1, Xmm2, 10101010b
318+ Mulps Xmm1, Xmm6
319+ Addps Xmm0, Xmm1
320+
321+ Pshufd Xmm1, Xmm2, 11111111b
322+ Mulps Xmm1, Xmm7
323+ Addps Xmm0, Xmm1
324+
325+ Movups [Result + $10], Xmm0
326+
327+ // Spalte 2
328+ Movups Xmm2, [M1 + $20]
329+
330+ Pshufd Xmm0, Xmm2, 00000000b
331+ Mulps Xmm0, Xmm4
332+
333+ Pshufd Xmm1, Xmm2, 01010101b
334+ Mulps Xmm1, Xmm5
335+ Addps Xmm0, Xmm1
336+
337+ Pshufd Xmm1, Xmm2, 10101010b
338+ Mulps Xmm1, Xmm6
339+ Addps Xmm0, Xmm1
340+
341+ Pshufd Xmm1, Xmm2, 11111111b
342+ Mulps Xmm1, Xmm7
343+ Addps Xmm0, Xmm1
344+
345+ Movups [Result + $20], Xmm0
346+
347+ // Spalte 3
348+ Movups Xmm2, [M1 + $30]
349+
350+ Pshufd Xmm0, Xmm2, 00000000b
351+ Mulps Xmm0, Xmm4
352+
353+ Pshufd Xmm1, Xmm2, 01010101b
354+ Mulps Xmm1, Xmm5
355+ Addps Xmm0, Xmm1
356+
357+ Pshufd Xmm1, Xmm2, 10101010b
358+ Mulps Xmm1, Xmm6
359+ Addps Xmm0, Xmm1
360+
361+ Pshufd Xmm1, Xmm2, 11111111b
362+ Mulps Xmm1, Xmm7
363+ Addps Xmm0, Xmm1
364+
365+ Movups [Result + $30], Xmm0
366+end;
367+```
368+
369+Autor: Mathias
370+
371+---
372+*From the Free Pascal wiki, page "SSE/de", as it stood on 2020-01-19 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
373+Category: Deutsch
374+Category: Free Pascal Programmers Guide/de

Back to history