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
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

warum rechnet er dann in seinem Beispiel mit -9999 bis +9999?
:?
Klar, weil er damit die Zahl hinter/unter dem Bruchstrich meint. :wink:

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
Franky
Beiträge: 1132
Registriert: 29.08.2004 16:31
Wohnort: Münsterland
Kontaktdaten:

Beitrag von Franky »

Edit:
Syntaxfehler im Deutschen, Division durch zweierpotenzen, nich mit ;)
Ich dachte, man verseht mich schon :(

So, nun zu kaerus frage und PMVs antwort

Richtig, PMV. Ich hatte die Methode von Kaeru schonmal als Optimierungsvorschlag im Englischen Board gepostet (bzw. Das ASM-Äquivalent dazu). Trond hat mich auf den Fehler aufmerksam gemacht und so hab ich denn erstmal ruhe gegeben. Aber da ich mir sicher war, dass man den wie ich finde etwas langsamen Code (besonders IDIV) optimieren kann, hab ich einfach mal nachgeschaut, wie sich diese Veränderung auswirkt. Und siehe da, während IDIV im negativen Bereich aufrundet (-23/8 wird zu -3), rundet SAR ab (-23/8 wird zu -4).

Meine Pointerei, wie du´s so schön nennst (Falls du die Labels meinst O_o), fragt nun ab:
1.) Is der zu dividierende Wert<0?
Wenn ja:
2.)Ist der Wert kein gradzahlig vielfaches des Teilers?
Wenn nein: +1 und alles ist geritzt.



Zum praktischen nutzen:
Nunja.
Wie gesagt, habe ich es im Englischen Forum als Feature-Request gepostet. Da ich den Code aber nicht in dem Forum vergammeln lassen wollte, dachte ich mir, hier kann man sowas auch gebrauchen.
Praktische Anwendung in dem Sinne sollte es vor allem im Bereich normaler ASM-Optimierung finden.
Aber wenn du es unbedingt in einem Normalen Code einsetzen willst, kannst du ja mit einem Macro arbeiten. Das ist zwar keine Native Syntax, aber es nutzt dann den Code.

Code: Alles auswählen

Macro Divide(erg,wert,LaufIndex)
!        MOV    ebx,dword [v_#wert]
!         SAR    ebx,3
!        MOV    dword [v_#erg],ebx
!         CMP    ebx,0
!         JNL l___div_end_#LaufIndex
!            SAL ebx,3
!           CMP dword[v_#wert],ebx
!            JE l___div_end_#LaufIndex
!               INC dword[v_#erg]
         __div_end_#LaufIndex:
EndMacro
Der Laufindex muss sein, da sonst die Labels doppelt benannt sind.



Falls du nun wirklich Pointer meinst: Das dient nur dazu, die Werte in einen Speicherbereich ein zu tragen, damit man nachher abfragen kann, ob zwischen der PB-Spezifischen und der Eigenen Division unterschiede auftreten ;) Hat mit der Optimierung nichts zu tun, daher kann es über die Compilerdirektiven auch ausgeklammert werden :wink: :(
Falsch zugeordnetes Zitat des Tages: "O'zapft is" - Edward Snowden :)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ach SO du meinst den zähler....
sorry, bin nich voll auf der höhe (schupfen, husten, kopf- und gliederschmerzen)
ja kla, das is mit bitshift schwieriger...


[EDITH]
hier ist der code für negative zahlen...
du machst ja auch ne fallunterscheidung, also darf ich das auch... ;)

Code: Alles auswählen

a = -1000
Debug Hex(a)
a ! $FFFFFFFF
Debug a
a +1
Debug a
a >> 3
Debug a
a -1
Debug a
a ! $FFFFFFFF
Debug a
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Mit den neuen Intel-Prozis (habe den Wolfdale E8400) ist das Verhältnis übrigens nicht so gravierend (nur 1,4-fach schneller). Aus dem Asm-Code ist vielleicht noch ein bisschen rauszukitzeln:

Code: Alles auswählen

!        MOV    ebx,dword [v_a] 
!         SAR    ebx,3 
!        MOV    dword [v_c],ebx 
;!         CMP    ebx,0 
;!         JNL l___div_end 
!jns l___div_end   ;nach SAR von negativer Zahl ist das Signum-Flag gesetzt, sonst nicht 
;!            SAL ebx,3 
;!           CMP dword[v_a],ebx 
;!            JE l___div_end 
!test dword [v_a],7  ;dies ist Wert für Shift 3, für allgemeine Anwendung wohl nicht so gut
!jz l___div_end
!               INC dword[v_c] 
         __div_end: 
Aber in Test-Schleifen schlagen mitunter ganz andere Sachen zu...

Gruß
Helle
Antworten