Division to shift optimization

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Yes, I meant the divisor.
Obviously I meant it should only happen with constants, so you don't need to check anything at run-time. But I wasn't aware of the problem with rounding and negative numbers.

As you can see, it's much faster:

Code: Select all

tmp = 123495
t = ElapsedMilliseconds()
For i = 0 To 100000000
  x = tmp/2
Next
t - ElapsedMilliseconds()

t2 = ElapsedMilliseconds()
For i = 0 To 100000000
  x = tmp >> 1
Next
t2 - ElapsedMilliseconds()

MessageRequester("divide with 2",Str(-t))
MessageRequester("the other",Str(-t2))
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Edit 3: Post was full of wrong info, removed it. See below.
Last edited by tinman on Sat Dec 01, 2007 6:56 pm, edited 3 times in total.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

Trond wrote: Obviously I meant it should only happen with constants, so you don't need to check anything at run-time.
Good then I didn't get it all wrong :)
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

On mine, the shift by itself is quicker (2400) than the divide (3500), but if you include the If then the total time is 4700, and if you include the If and the increment, then it pushes it to a whopping 5400.

Could really do with a quick if and increment...
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Edit2: Removed code for incorrect algorithm. See below.
Last edited by tinman on Sat Dec 01, 2007 7:21 pm, edited 1 time in total.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

:shock: that is sloooow! 9900 for me!
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Turn off the debugger...
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

Ah! :oops:
Thanks!
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

OK, I think I've figured out the correct algorithm. Code below, with some example ASM.

In fact, looking at the ASM that PB currently produces it converts the long to a quad, then performs the division. So the same code works for longs and quads quite easily. I don't know how to do this shifting nicely for quads so perhaps thats another issue doing it this way.

Code: Select all

Define.l b
Define.l a

#MAX_RANGE = 100000000
;#MAX_RANGE = 10
#DIVIDE_BY = 2
#SHIFT_BY = 1

st=GetTickCount_()
For a = -#MAX_RANGE To #MAX_RANGE
    b = a / #DIVIDE_BY
Next
et=GetTickCount_()
MessageRequester("Duration", Str(et-st))

st=GetTickCount_()
For a = -#MAX_RANGE To #MAX_RANGE
    ;b = a >> #SHIFT_BY
    ;If b < 0 And (a & ((1 << #SHIFT_BY)-1))
    ;    b + 1
    ;EndIf

    #ADJUST_MASK = (1 << #SHIFT_BY)-1
    ;Debug #ADJUST_MASK
    
    MOV    ebx, dword [v_a]
    MOV    eax, ebx
    AND    eax, #ADJUST_MASK
    SETNZ  al
    AND    eax, 1
    ROL    ebx, 1
    AND    eax, ebx
    ROR    ebx, 1
    SAR    ebx, #SHIFT_BY
    ADD    ebx, eax
    MOV    dword [v_b],ebx
    
    Debug b
Next
et=GetTickCount_()
MessageRequester("Duration", Str(et-st))
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
Post Reply