Autor Beitrag
Whaite
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Do 08.05.08 00:16 
Hallo zusammen,

ich habe ein etwas seltsames Problem mit einem Record unter TurboDelphi, den ich mittels SSE optimieren will. Folgendermaßen sieht mein Test-Code aus:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
type
//...
  TglVector4f = record
  public var
    X, Y, Z, W: Single;
    class operator Add(A, B: TglVector4f): TglVector4f;
  end;

//...

class operator TglVector4f.Add(A, B: TglVector4f): TglVector4f;
asm
  movaps xmm0, DQWord ptr [A.X]
  movaps xmm1, DQWord ptr [B.X]
  addps xmm0, xmm1
  movaps DQWord ptr [Result.X], xmm0
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  V, U: TglVector4f;
begin
  V.X := 1;
  V.Y := 2;
  V.Z := 3;
  U.X := 4;
  U.Y := 14;
  U.Z := 24;
{
  asm
    movaps xmm0, dqword ptr [V.X]
  end;   
}

  V := V + U;
end;


Kompiliere ich das so, endet das beim Zugriff auf [A.X] im class operator mit einer AccessViolation. Das seltsame daran ist: Entferne ich die Auskommentierung des asm-Codes in OnCreate (sodass der Code da ausgeführt wird) vor der eigentlichen Addition, wird korrekt gerechnet und kein Zugriffsfehler erzeugt. Ich habe schon einigermaßen rumprobiert, aber mir wird das weder so recht klar noch scheint sich allzu viel im Netz dazu finden zu lassen.

Übersetzt wird das alles vom Compiler dann jedenfalls so:
Auskommentiert/Ohne seltsamen Zusatz:
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
Unit1.pas.36: movaps xmm0, DQWord ptr [A.X]
0045215C 0F2800           movaps xmm0,dqword ptr [eax]
Unit1.pas.37: movaps xmm1, DQWord ptr [B.X]
0045215F 0F280A           movaps xmm1,dqword ptr [edx]
Unit1.pas.38: addps xmm0, xmm1
00452162 0F58C1           addps xmm0,xmm1
Unit1.pas.39: movaps DQWord ptr [Result.X], xmm0
00452165 0F2901           movaps dqword ptr [ecx],xmm0
Unit1.pas.40: end;
00452168 C3               ret 
00452169 8D4000           lea eax,[eax+$00]
Unit1.pas.61: begin
0045216C 56               push esi
0045216D 57               push edi
0045216E 83C4D0           add esp,-$30
Unit1.pas.62: V.X := 1;
00452171 C704240000803F   mov [esp],$3f800000
Unit1.pas.63: V.Y := 2;
00452178 C744240400000040 mov [esp+$04],$40000000
Unit1.pas.64: V.Z := 3;
00452180 C744240800004040 mov [esp+$08],$40400000
Unit1.pas.65: U.X := 4;
00452188 C744241000008040 mov [esp+$10],$40800000
Unit1.pas.66: U.Y := 14;
00452190 C744241400006041 mov [esp+$14],$41600000
Unit1.pas.67: U.Z := 24;
00452198 C74424180000C041 mov [esp+$18],$41c00000
Unit1.pas.73: V:=V+U;
004521A0 8D4C2420         lea ecx,[esp+$20]
004521A4 8D542410         lea edx,[esp+$10]
004521A8 8BC4             mov eax,esp
004521AA E8ADFFFFFF       call TglVector4f.&op_Addition
004521AF 8D742420         lea esi,[esp+$20]
004521B3 8BFC             mov edi,esp
004521B5 A5               movsd 
004521B6 A5               movsd 
004521B7 A5               movsd 
004521B8 A5               movsd 
Unit1.pas.74: end;
004521B9 83C430           add esp,$30
004521BC 5F               pop edi
004521BD 5E               pop esi
004521BE C3               ret 
004521BF 90               nop


Mit zusätzlichem Asm-Code davor:
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
Unit1.pas.36: movaps xmm0, DQWord ptr [A.X]
0045215C 0F2800           movaps xmm0,dqword ptr [eax]
Unit1.pas.37: movaps xmm1, DQWord ptr [B.X]
0045215F 0F280A           movaps xmm1,dqword ptr [edx]
Unit1.pas.38: addps xmm0, xmm1
00452162 0F58C1           addps xmm0,xmm1
Unit1.pas.39: movaps DQWord ptr [Result.X], xmm0
00452165 0F2901           movaps dqword ptr [ecx],xmm0
Unit1.pas.40: end;
00452168 C3               ret 
00452169 8D4000           lea eax,[eax+$00]
Unit1.pas.61: begin
0045216C 55               push ebp
0045216D 8BEC             mov ebp,esp
0045216F 83C4D0           add esp,-$30
00452172 56               push esi
00452173 57               push edi
Unit1.pas.62: V.X := 1;
00452174 C745F00000803F   mov [ebp-$10],$3f800000
Unit1.pas.63: V.Y := 2;
0045217B C745F400000040   mov [ebp-$0c],$40000000
Unit1.pas.64: V.Z := 3;
00452182 C745F800004040   mov [ebp-$08],$40400000
Unit1.pas.65: U.X := 4;
00452189 C745E000008040   mov [ebp-$20],$40800000
Unit1.pas.66: U.Y := 14;
00452190 C745E400006041   mov [ebp-$1c],$41600000
Unit1.pas.67: U.Z := 24;
00452197 C745E80000C041   mov [ebp-$18],$41c00000
Unit1.pas.70: movaps xmm0, dqword ptr [V.X]
0045219E 0F2845F0         movaps xmm0,dqword ptr [ebp-$10]
Unit1.pas.73: V:=V+U;
004521A2 8D4DD0           lea ecx,[ebp-$30]
004521A5 8D55E0           lea edx,[ebp-$20]
004521A8 8D45F0           lea eax,[ebp-$10]
004521AB E8ACFFFFFF       call TglVector4f.&op_Addition
004521B0 8D75D0           lea esi,[ebp-$30]
004521B3 8D7DF0           lea edi,[ebp-$10]
004521B6 A5               movsd 
004521B7 A5               movsd 
004521B8 A5               movsd 
004521B9 A5               movsd 
Unit1.pas.74: end;
004521BA 5F               pop edi
004521BB 5E               pop esi
004521BC 8BE5             mov esp,ebp
004521BE 5D               pop ebp
004521BF C3               ret


Mein Problem; die Assemblerbefehle sind mir zwar klar, aber das Hintergrundwissen um die Logik warum genau hier nun push, pop, lea, etc. mit genau diesem und jenem Register notwendig ist, fehlt mir. :| Ansonsten springt mich auch nichts an, was diesen seltsamen Unterschied erklären würde, ich tippe aber mal darauf, dass ich irgendwie falsche Speicheradressen bekomme. Schaue ich mir aber den Speicherbereich an, auf den eax zeigt, dann steht dort wirklich A.X, A.Y, A.Z, A.W ohne Lücke drin.
Hat da vielleicht jemand ne Idee oder einen Fortbildungslink?

MfG
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Do 08.05.08 08:41 
Hallo,

sind Deine Daten überhaupt auf 16 Bytegrenzen ausgerichtet (aligned)?
Sicher gibt es hierfür Kompilereinstellungen.
homepages.fh-giessen...orlesung/sse-ref.pdf
Zitat:

12.4.3. SSE – Datentransport Befehle
Die SSE Datentransport Befehle transportieren einfache Gleitkommazahlen zwischen zwei XMM
Registern oder zwischen einem XMM Register und dem Arbeitsspeicher.
MOVAPS—Move Aligned Packed Single-Precision Floating-Point Values
Instruction Description
MOVAPS xmm1, xmm2/m128 Move packed single-precision floating-point values from xmm2/m128 to xmm1.
MOVAPS xmm2/m128, xmm1 Move packed single-precision floating-point values from xmm1 to xmm2/m128.
Der MOVAPS Befehl kopiert einen Doppel-Quadword Operanden mit vier 32bit-Gleitkommawerten aus
dem Speicher in ein 128bit XMM Register und umgekehrt, oder zwischen zwei XMM Registern. Die
Speicheradresse muss 16 Byte aligned (d.h. ohne Rest durch 16 teilbar) sein.
MOVUPS—Move Unaligned Packed Single-Precision Floating-Point Values
Instruction Description
MOVUPS xmm1, xmm2/m128 Move packed single-precision floating-point values from xmm2/m128 to xmm1.
MOVUPS xmm2/m128, xmm1 Move packed single-precision floating-point values from xmm1 to xmm2/m128.
Der MOVUPS Befehl führt die gleiche Operation durch wie der MOVAPS Befehl, akzeptiert jedoch auch
nicht-alignte Adressen. Der MOVUPS Befehl ist dafür langsamer.


ALternativ MOVUPS testen oder Die Speicheradresse von V,U ausgeben lassen.
ala Format('%X %X %X %X',[@V.X,@V.Y,@V.Z,@V.W])
eventuell fehlt packed record
TglVector4f = packed record.

Gruß Horst
Whaite Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Do 08.05.08 14:29 
Das war wohl so ziemlich das einzige, was ich vollkommen verdrängt hatte... und heute überleg ich noch, was das "a" eigentlich bedeuten sollte... :roll:
Mittels SetMinimumBlockAlignment(mba16Byte); lässt sich das Problem aus der Welt schaffen.

Einziger Nachteil, Delphi's FPU-Code scheint bei dieser Einzeloperation etwa 4 mal schneller zu sein. :D

Danke für die Antwort und den PDF-Link :)

MfG