Optimierte Division mit zweierpotenzen

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:

Optimierte Division mit zweierpotenzen

Beitrag von Franky »

Hi Leute, hier mal ein kleines Beispiel, wie man die Division mit festen zweierpotenzen doppelt so schnell bewerkstelligt:

Code: Alles auswählen

#Compare=0

Global a,b,c.l,*adr1.long,*adr2.long,adr1.l,adr2.l
adr1=AllocateMemory(80000)
adr2=AllocateMemory(80000)

;Rechnung: c=a/8

Zeit=GetTickCount_()
   For b=1 To 99999
    CompilerIf #compare
     *adr1=adr1
    CompilerEndIf
     For a=-9999 To 9999
 !        MOV    eax,dword [v_a]
; !        MOV    ebx,dword [v_a]
 ;!        MOV    eax,ebx
 !        MOV    ebx,8
 !        CDQ
 !        IDIV   ebx
 ;!        MOV    ebx, eax
 ;!        MOV    dword [v_c],ebx
 !        MOV    dword [v_c],eax
     CompilerIf #Compare
       *adr1\l=c
       *adr1+4
     CompilerEndIf
   Next
 Next
zeit2=GetTickCount_()
   For b=1 To 99999
     CompilerIf #compare
      *adr2=adr2
     CompilerEndIf
;    CallDebugger
    For a=-9999 To 9999
!        MOV    ebx,dword [v_a]
!         SAR    ebx,3
!        MOV    dword [v_c],ebx
!         CMP    ebx,0
!         JNL l___div_end
!            SAL ebx,3
!           CMP dword[v_a],ebx
!            JE l___div_end
!               INC dword[v_c]
         __div_end:
     CompilerIf #compare
         *adr2\l=c
         *adr2+4
     CompilerEndIf
  Next
 Next
zeit3=GetTickCount_()
 
CompilerIf #compare
*adr1=adr1
*adr2=adr2
dif=0
For a=0 To 19998
     If *adr1\l<>*adr2\l
            INC dif
           Debug Str(a-9999)+"/8="+Str(*adr1\l)+"   SAR a,3="+Str(*adr2\l)+"  %8="+Str(a%8)
     EndIf 
     *adr1+4
     *adr2+4
Next 
CompilerEndIf 
MessageRequester("Ergebnis:","Freds Method: "+Str(zeit2-zeit)+"ms"+Chr(13)+"My Method: "+Str(zeit3-zeit2)+"ms"+Chr(13)+"Menge der Unterschiede: "+Str(dif))
Das erste stellt Freds Code Dar (aus dem ASM-Output kopiert). Das da drunter ist meins.
Falsch zugeordnetes Zitat des Tages: "O'zapft is" - Edward Snowden :)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
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 »

Bei mir siehts so aus:
Freds Method: 88867ms
My Method: 15212ms
Menge der Unterschiede: 0 (auch mit #compare = 1)
Also 5,84 mal so schnell. :allright:
Zuletzt geändert von NicTheQuick am 03.03.2008 16:32, insgesamt 1-mal geändert.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Beitrag von RSBasic »

Freds Method: 158219ms
My Method: 121562ms
Menge der Unterschiede: 0
:?
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
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 »

@RSBasic:
:?
Das wundert mich ein bisschen. Hattest du auch den Debugger aus? Dein
Prozessor ist nämlich sicherlich schneller als mein 1200-er.
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Freds Method: 43875ms
My Method: 7735ms
Menge der Unterschiede: 0
Ist also signifikant schneller :allright:
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Beitrag von RSBasic »

NicTheQuick hat geschrieben:@RSBasic:
:?
Das wundert mich ein bisschen. Hattest du auch den Debugger aus? Dein
Prozessor ist nämlich sicherlich schneller als mein 1200-er.
Nein, der war an.

Hab jetzt den Debugger ausgeschaltet:
Freds Method: 45891ms
My Method: 8625ms
Menge der Unterschiede: 0
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> Das erste stellt Freds Code Dar (aus dem ASM-Output kopiert).

da stellt sich mir die frage, von welchem PB-code eigentlich?

ich persönlich würde z.b. eine zweierpotenz-teilung grundsätzlich so schreiben:

Code: Alles auswählen

Var >> 3
anstatt so

Code: Alles auswählen

Var / 8
ich bin jetzt zu faul, durch dein komisches gepointere durchzusteigen...

mich würde mal interessieren
a) wie soll ich deinen code einsetzen, wenn ich ne stinknormale variable teilen will
b) wie sieht deine demo aus, ergänzt um einen direkten vergleich mit Var >> 3

letzteres wollte ich eigentlich mal grad hinschreiben,
aber deine komischen adr-pointer sind mir jetzt zu aufwendig,
um da schnell nen vergleich hinschreiben zu können.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
PMTheQuick
Beiträge: 630
Registriert: 05.05.2005 19:06

Beitrag von PMTheQuick »

---------------------------
Ergebnis:
---------------------------
Freds Method: 30015ms
My Method: 8250ms
Menge der Unterschiede: 0
---------------------------
OK
---------------------------


Ziemlicher Unterschied ;)

Gruss
PMTheQuick :D
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Kaeru Gaman hat geschrieben:> Das erste stellt Freds Code Dar (aus dem ASM-Output kopiert).

da stellt sich mir die frage, von welchem PB-code eigentlich?

ich persönlich würde z.b. eine zweierpotenz-teilung grundsätzlich so schreiben:

Code: Alles auswählen

Var >> 3
anstatt so

Code: Alles auswählen

Var / 8
ich bin jetzt zu faul, durch dein komisches gepointere durchzusteigen...

mich würde mal interessieren
a) wie soll ich deinen code einsetzen, wenn ich ne stinknormale variable teilen will
b) wie sieht deine demo aus, ergänzt um einen direkten vergleich mit Var >> 3
Richtig vermutet, wie schon als Kommentar angegeben verwendet Franky
den ASM-Output von

Code: Alles auswählen

;Rechnung: c=a/8
... wenn ich anstelle des ASM folgendes einsetzte

Code: Alles auswählen

c = a >> 3
ist Freds Optimierung besser ...
Fred: ~5500
Franky: ~7000
Das Problem hierbei ... Bitshift funktioniert natürlich nur bei Zahlen >= 0
:wink:

Fals also mit negativen Zahlen zu rechnen ist, ist Frankys viel besser.

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: Optimierte Division mit zweierpotenzen

Beitrag von Kaeru Gaman »

Franky hat geschrieben:Hi Leute, hier mal ein kleines Beispiel, wie man die Division mit festen zweierpotenzen doppelt so schnell bewerkstelligt:
...so und nun nenn mir mal den exponenten, den ich ner 2 geben muss, um ne negative zahl rauszubekommen....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten