AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

[ASM / SSE] Vektoroperationen

Ein Thema von Edlmann · begonnen am 13. Jun 2012 · letzter Beitrag vom 18. Jun 2012
Antwort Antwort
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#1

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 19:18
Okay, das läuft schonmal etwa 10% schneller...

Nur warum liegt av1 bei DQWORD PTR [EAX], av2 bei EDX und Result bei ECX?

Muss man die nicht eigentlich erst dort hin moven?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.580 Beiträge
 
Delphi 12 Athens
 
#2

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 19:46
Eigentlich liegt Result in EAX, aber nur, wenn es klein genug ist und wenn es sich nicht um Typen mit Compilermagic (automatischer Speicherverwaltung) handelt.
Alles andere wird als Var/Out-Parameter übergeben.

Also alles mit maximal 32 Bit (eventuell auch 64 Bit ... bin mir grade nicht sicher, aber bei den In-Parametern sind Int64 und Double ein bissl anders) und wenn es kein String, dyn. Array, Interface oder Variant ist.

Die interne Signatur sieht also so aus:
procedure AddVecsSSE(const av1, av2: TTestVec; var Result: TTestVec);
[add]
Result in EAX und EDX = 64 Bit
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Jun 2012 um 20:15 Uhr)
  Mit Zitat antworten Zitat
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#3

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 19:51
Ach klar, macht Sinn...Danke, werd mal versuchen die Schleife für Arrays ähnlich zu optimieren

Geändert von Edlmann (13. Jun 2012 um 19:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.580 Beiträge
 
Delphi 12 Athens
 
#4

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 20:19
Zitat:
MOV EBX, Length
EBX solltest du nicht einfach so überschreiben, ohne dessen Wert zu speichern und hinterher wiederherzustellen.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#5

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 20:54
Zitat:
MOV EBX, Length
EBX solltest du nicht einfach so überschreiben, ohne dessen Wert zu speichern und hinterher wiederherzustellen.
Ist mir auch schon aufgefallen, hab noch nicht so viel mit asm gemacht und dementsprechend vergessen gehabt...ist gefixxt der Fehler
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.580 Beiträge
 
Delphi 12 Athens
 
#6

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 20:58
Delphi-Quellcode:
type
  TTestVec = packed record
    x, y, z, w: Single;
  end;
  TTestVecArr = array[0..0] of TTestVec;
  PTestVecArr = ^TTestVecArr;

procedure AddVecsArraySSE(av1, av2: Pointer; outarray: Pointer; Count: Integer);
{$IF SizeOf(Pointer) = 4}  // {$IFDEF Win32}
//asm
// MOV EDI, ECX
// MOV ECX, [EBP+8]
// DEC ECX
// CMP ECX, 0
// JL @@exit
// @@loop:
// MOVUPS XMM0, DQWORD PTR [EAX + ECX * 16]
// MOVUPS XMM1, DQWORD PTR [EDX + ECX * 16]
// ADDPS XMM0, XMM1
// MOVUPS DQWORD PTR [EDI + ECX * 16], XMM0
// DEC ECX
// ZGE @@loop
// @@exit:
//end;
asm
  MOV EDI, ECX
  MOV ECX, [EBP+8]
  CMP ECX, 0
  JLE @@exit
  DEC ECX
  CMP ECX, $07FFFFFF
  JG @@exit
  SHL ECX, 4
  @@loop:
  MOVUPS XMM0, DQWORD PTR [EAX + ECX]
  MOVUPS XMM1, DQWORD PTR [EDX + ECX]
  ADDPS XMM0, XMM1
  MOVUPS DQWORD PTR [EDI + ECX], XMM0
  SUB ECX, 16
  JNZ @@loop
  @@exit:
end;
{$ELSE}
//type
// TSingleArr = array[0..0] of Single;
// PSingleArr = TSingleArr;
//var
// i: Integer;
//begin
// for i := (Count * 4) - 1 downto 0 do
// PSingleArr(outarray)[i] := PSingleArr(av1)[i] + PSingleArr(av2)[i];
//end;
var
  i: Integer;
begin
  for i := Count-1 downto 0 do begin
    PTestVecArr(outarray)[i].x := PTestVecArr(av1)[i].x + PTestVecArr(av2)[i].x;
    PTestVecArr(outarray)[i].y := PTestVecArr(av1)[i].y + PTestVecArr(av2)[i].y;
    PTestVecArr(outarray)[i].z := PTestVecArr(av1)[i].z + PTestVecArr(av2)[i].z;
    PTestVecArr(outarray)[i].w := PTestVecArr(av1)[i].w + PTestVecArr(av2)[i].w;
  end;
end;
{$IFEND}
Keine Ahnung, ob's richtig ist.
Und Schade, daß *16 scheinbar vergessen wurde zu implementieren.
*2, *4 und *8 gibt es ja auch und daß bei der Größe der MMX-Register


Delphi-Referenz durchsuchenLength ist ein unpraktischer Name.


[edit]
Code siehe: Zitat-Funktion ... die Funktion des Delphi-Tags ist immernoch einfach nur schrecklich
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Jun 2012 um 21:18 Uhr)
  Mit Zitat antworten Zitat
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#7

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 21:07
Die Variante läuft auf jeden Fall wunderbar, und der Performancegewinn kann sich auch sehen lassen.
Ich blick noch nicht so 100% durch, aber *fängt an kaffee in Verstehen zu konvertieren*

[Edit]
Okey, habs soweit gecheckt...Allerdings geht so ja die Möglichkeit verschiedener Offsets verloren - bzw wird auf power of 2 beschränkt...aber Reicht ja.
Vielen Dank mal wieder himitsu

Geändert von Edlmann (13. Jun 2012 um 21:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.580 Beiträge
 
Delphi 12 Athens
 
#8

AW: [ASM / SSE] Vektoroperationen

  Alt 13. Jun 2012, 21:23
Ich glaub ich hab einen Bufferoverrun.
Es wird von 0 bis Count gerechnet und nicht von 0 bis Count-1 .
Hab daher oben noch ein paar DEC ECX verbaut.



Eigentlich macht man solche Array-Operationen über ESI (Source), EDI (Destination) und ECX (Counter).
z.B. wenn du dir Funktionen wie Copy/Move oder Pos ansiehst.
Und eigentlich gibt es spezielle Registerzugriffe, damit man mit nur einem Zähler als Offset für beide/alle Arrays auskommt.

Wobei einige Register spezielle Sonderfunktionen besitzen und oder welche sich für bestimmte Dinge bei Vielen eingebürgert haben.
Eben EBX als Zwischenspeicher für den Stack
ECX für Zähler
oder ESI und EDI für Arrays


Code:
MOV ESI, &Quelle // Byte-Arrays
MOV EDI, &Ziel
MOV ECX, &Anzahl
@1:
MOV AL, [ESI]
MOV [EDI], AL
INC ESI
INC EDI
DEC ECX
JNZ @1
Code:
MOV ESI, &Quelle
MOV EDI, &Ziel
MOV ECX, &Anzahl
@1:
MOV AL, [ESI]
MOV [EDI], AL
INC ESI
INC EDI
LOOP @1
Code:
MOV ESI, &Quelle
MOV EDI, &Ziel
MOV ECX, &Anzahl
@1:
MOV AL, [ESI + ECX]
MOV [EDI + ECX], AL
LOOP @1
LOOP selber ist aber nicht unbedingt ein schneller Befehl (keine Ahnung warum),
da ist
Code:
DEC ECX
und
Code:
JNZ @1
dann doch etwas besser.
Aber LOOP zeigt die Spezialisierung von Registern sehr gut.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Jun 2012 um 21:27 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:28 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