Speicherbereich umdrehen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Franky
Beiträge: 1132
Registriert: 29.08.2004 16:31
Wohnort: Münsterland
Kontaktdaten:

Speicherbereich umdrehen

Beitrag von Franky »

Hi, hab mir gerade ne funktion geschrieben und gemerkt, dass ich sie garnicht gebrauche.


wie gesagt, hiermit dreht man einfach nen speicherbereich um
123456789 wird zu
987654321

Code: Alles auswählen

Procedure TurnArrayL(buffer.l,laenge.l)
           MOV Eax,buffer
           MOV Ebx,buffer
           ADD Ebx,laenge
            TA_begin:
                        MOV Ecx, dword[Ebx]
                        XCHG dword[Eax], Ecx
                        MOV dword[Ebx], Ecx
                       ADD Eax,4 
                       SUB Ebx,4
            CMP Eax,Ebx
            JBE l_ta_begin          
EndProcedure
Es ist nix besonderes, aber vielleicht braucht es wer

Danke für die kleine Syntaxhilfe an Deeem

Achja, wenn wer ne schnellere Version weiß, bitte melden, man is ja immer gewillt, zu lernen ;)
Falsch zugeordnetes Zitat des Tages: "O'zapft is" - Edward Snowden :)
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Nicht optimal, aber vielleicht regts an :)
2.6x schneller:

Code: Alles auswählen

Procedure TurnArrayL2(buffer.l,laenge.l) 
  MOV Eax,buffer 
  MOV Ebx,buffer 
  ADD Ebx,laenge 
  TA_begin2: 
    MOV Ecx, dword[Ebx] 
    MOV Edx, dword[Eax]
    MOV dword[Eax], Ecx
    MOV dword[Ebx], Edx 
    ADD Eax,  4
    ADD Ebx, -4
    CMP Eax, Ebx
  JBE l_ta_begin2          
EndProcedure
Kurz: XCHG ist lahm für Memory-Register
Während mit XCHG 7 Clocks benötigt werden, sind es mit 4 Movs nur 4.

greetz
Remi
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Und die ganze Schleife dann noch ein bischen optimiert:

Code: Alles auswählen

Procedure TurnArrayL2(Buffer.l,laenge.l) 
  MOV Eax, Buffer 
  XOR Esi, Esi
  MOV Ebx, laenge
  SHR Ebx, 2
  TA_begin2: 
    MOV Ecx, dword[Eax+Ebx*4]
    MOV dword[Eax+Esi*4], Ecx 
    MOV Ecx, dword[Eax+Esi*4] 
    MOV dword[Eax+Ebx*4], Ecx 
    INC Esi
    DEC Ebx
    CMP Esi, Ebx
  JA byte l_ta_end
    MOV Ecx, dword[Eax+Ebx*4]
    MOV dword[Eax+Esi*4], Ecx 
    MOV Ecx, dword[Eax+Esi*4] 
    MOV dword[Eax+Ebx*4], Ecx 
    INC Esi
    DEC Ebx
    CMP Esi, Ebx
  JA byte l_ta_end
    MOV Ecx, dword[Eax+Ebx*4]
    MOV dword[Eax+Esi*4], Ecx 
    MOV Ecx, dword[Eax+Esi*4] 
    MOV dword[Eax+Ebx*4], Ecx 
    INC Esi
    DEC Ebx
    CMP Esi, Ebx
  JA byte l_ta_end
    MOV Ecx, dword[Eax+Ebx*4]
    MOV dword[Eax+Esi*4], Ecx 
    MOV Ecx, dword[Eax+Esi*4] 
    MOV dword[Eax+Ebx*4], Ecx 
    INC Esi
    DEC Ebx
    CMP Esi, Ebx
  JBE l_ta_begin2
    
  TA_End:
  ProcedureReturn
EndProcedure
Habs allerdings nicht getestet...
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Laut Testprogramm liegt Deeem2031 bei einem Speicherbuffer der Größe 10.000.000 Bytes mit 1000 Umkehrungen mit 40779 Millisekunden vor remi_meier mit 41229 ms.
Benutzeravatar
Franky
Beiträge: 1132
Registriert: 29.08.2004 16:31
Wohnort: Münsterland
Kontaktdaten:

Beitrag von Franky »

Hm, interessant :)
Gibt es eigentlich ein schönes Nachschlagewerk, wo genau steht, welche funktion am meisten optimiert, was welche operation genau macht und braucht und so? Also, besonders, was am meisten optimiert ist, würde mich interessieren, den rest kann ich ja inner ASM-Hilfe nachschlagen
Falsch zugeordnetes Zitat des Tages: "O'zapft is" - Edward Snowden :)
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

@Deem:
Aso mit dem 'byte' in 'JA byte l_ta_end' gibts bei mir ein 'relative jump out
of range', ohne gehts.
Das Lustige ist nur, genau den gleichen Ansatz hatte ich auch, bevor ich
mein Ding gepostet habe, es lief irgendwie nicht. Ist aber fast schade, dass
das nur so wenig Geschwindigkeit bringt..

@Franky:
In fast jeder Asm-Befehlsreferenz steht unten in einer Tabelle, wie lange
der Befehl zum ausführen braucht.

EDIT: Deem, es scheint dein Code hätte nen Fehler...
Er kehrt nicht vollständig um (bei mir), schau nochmals nach ;-)
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

remi_meier hat geschrieben:@Deeem:
Aso mit dem 'byte' in 'JA byte l_ta_end' gibts bei mir ein 'relative jump out
of range', ohne gehts.
Dann hattest du warscheinlich den Debugger an. Das "byte" war aber auch nur zum testen ob relative jumps benutzt werden, kann man also auch löschen.
remi_meier hat geschrieben:EDIT: Deeem, es scheint dein Code hätte nen Fehler...
Er kehrt nicht vollständig um (bei mir), schau nochmals nach ;-)

Der Code sollte funktionieren. Hab auch noch einen weiteren Versuch dazu gepackt, allerdings ist der nicht schneller.

Code: Alles auswählen

Procedure TurnArrayL2(Buffer.l,laenge.l) 
  MOV Eax, Buffer 
  XOR Esi, Esi 
  MOV Ebx, laenge 
  SHR Ebx, 2
  TA2_begin2: 
  MOV Ecx, dword[Eax+(Ebx-1)*4] 
  MOV Edx, dword[Eax+Esi*4] 
  MOV dword[Eax+Esi*4], Ecx 
  MOV dword[Eax+(Ebx-1)*4], Edx 
  INC Esi 
  DEC Ebx 
  CMP Esi, Ebx 
  JA byte l_ta2_end 
  MOV Ecx, dword[Eax+(Ebx-1)*4] 
  MOV Edx, dword[Eax+Esi*4] 
  MOV dword[Eax+Esi*4], Ecx 
  MOV dword[Eax+(Ebx-1)*4], Edx 
  INC Esi 
  DEC Ebx 
  CMP Esi, Ebx 
  JA byte l_ta2_end 
  MOV Ecx, dword[Eax+(Ebx-1)*4] 
  MOV Edx, dword[Eax+Esi*4] 
  MOV dword[Eax+Esi*4], Ecx 
  MOV dword[Eax+(Ebx-1)*4], Edx 
  INC Esi 
  DEC Ebx 
  CMP Esi, Ebx 
  JA byte l_ta2_end 
  MOV Ecx, dword[Eax+(Ebx-1)*4] 
  MOV Edx, dword[Eax+Esi*4] 
  MOV dword[Eax+Esi*4], Ecx 
  MOV dword[Eax+(Ebx-1)*4], Edx 
  INC Esi 
  DEC Ebx 
  CMP Esi, Ebx 
  JBE l_ta2_begin2 
  
  TA2_End: 
  ProcedureReturn 
EndProcedure

Procedure TurnArrayL3(Buffer.l,laenge.l) 
  MOV Eax, Buffer 
  MOV Edi, laenge
  SUB Edi, 4
  ADD Edi, Eax
  XCHG Edi, Esp
  
  TA3_begin2: 
  MOV Ecx, dword[Esp]
  MOV Edx, dword[Eax]
  PUSH Edx
  MOV dword[Eax], Ecx
  ADD Eax, 4
  CMP Eax, Esp
  JA byte l_ta3_end 
  
  MOV Ecx, dword[Esp]
  MOV Edx, dword[Eax]
  PUSH Edx
  MOV dword[Eax], Ecx
  ADD Eax, 4
  CMP Eax, Esp
  JA byte l_ta3_end 
  
  MOV Ecx, dword[Esp]
  MOV Edx, dword[Eax]
  PUSH Edx
  MOV dword[Eax], Ecx
  ADD Eax, 4
  CMP Eax, Esp
  JA byte l_ta3_end 
  
  MOV Ecx, dword[Esp]
  MOV Edx, dword[Eax]
  PUSH Edx
  MOV dword[Eax], Ecx
  ADD Eax, 4
  CMP Eax, Esp
  JBE l_ta3_begin2 
  
  TA3_End: 
  
  MOV Esp, Edi
  ProcedureReturn 
EndProcedure
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Vorschlag auf die Schnelle; nicht getestet:

Code: Alles auswählen

Procedure TurnArrayL4(buffer.l,laenge.l) 

    MOV esi,buffer
    MOV edi,esi
    ADD edi,laenge        ;korrekt laenge-4
weiter: 
    CLD 
    !LODSD 
    MOV edx,[edi]
    STD
    !STOSD
    MOV [esi-4],edx
    CMP esi,edi
    JB l_weiter

EndProcedure
Gruss
Helle
Benutzeravatar
Sylvia
verheiratet<br>1. PureGolf-Gewinner
Beiträge: 487
Registriert: 29.08.2004 09:42
Wohnort: Old Europe

Beitrag von Sylvia »

@Helle:
so in etwa hätte ich es auch gemacht... :mrgreen:

Übrigens...hat dein Chess schon ein paar Baustellen weniger ? Schick mir
bitte mal deine neueste Version. Macht einen leistungsfähigen Eindruck,
aber der Code...ganz schön anstrengend; streckenweise fehlt mir völlig
der Durchblick. <)
Basic Pur = PureBasic
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

@Helle

Deine Procedure funktioniert bei mir aber nicht:

Code: Alles auswählen

Procedure TurnArrayL4(buffer.l,laenge.l)
  MOV esi,buffer
  MOV edi,esi
  ADD edi,laenge        ;korrekt laenge-4
  weiter:
    CLD
    !LODSD
    MOV Edx,[edi]
    STD
    !STOSD
    MOV [esi-4],Edx
    CMP esi,edi
  JB l_weiter
EndProcedure

Procedure TurnArrayL(buffer.l,laenge.l)
  MOV Eax,buffer
  MOV Ebx,buffer
  ADD Ebx,laenge
  TA_begin:
    MOV Ecx, dword[Ebx]
    XCHG dword[Eax], Ecx
    MOV dword[Ebx], Ecx
    ADD Eax,4
    SUB Ebx,4
    CMP Eax,Ebx
  JBE l_ta_begin
EndProcedure

Size = 1000000

*mem = AllocateMemory(Size)
For a.l = 0 To Size - 1 Step 4
  PokeL(*mem + a, a)
Next

time1 = ElapsedMilliseconds()
  For b.l = 1 To 100
    TurnArrayL(*mem, Size)
  Next
time1 = ElapsedMilliseconds() - time1

time2 = ElapsedMilliseconds()
  For b   = 1 To 100
    TurnArrayL4(*mem, Size)
  Next
time2 = ElapsedMilliseconds() - time2

MessageRequester("Zeiten", Str(time1) + #CRLF$ + Str(time2))
Antworten