Floating-point Power of 2 (powf2 & powd2)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Floating-point Power of 2 (powf2 & powd2)

Post by Keya »

floating-point Pow2() functions for Float and Double, a bit faster than PB's Pow(n,2)
(not a fair competition though as PB's Pow() is general-purpose supporting both integer+float and variable exponent)

Code: Select all

CompilerIf #PB_Compiler_Debugger
  CompilerError("Error - Turn off debugger for timings")  
CompilerEndIf

Procedure.f Powf2(value.f)
! fld  dword [p.v_value]   ;load 32bit Float
! fmul st, st              ;pow2 = value * value
! fstp dword [p.v_value]   ;store
ProcedureReturn value
EndProcedure

Procedure.d Powd2(value.d)
! fld  qword [p.v_value]   ;load 64bit Double
! fmul st, st              ;pow2 = value * value
! fstp qword [p.v_value]   ;store
ProcedureReturn value
EndProcedure


Define result.f, ftest.f = 7

Time1 = ElapsedMilliseconds()
For i = 1 To 9000000
  result = Pow(ftest, 2)
Next i
Time2 = ElapsedMilliseconds()
MessageRequester("Purebasic Pow()", Str(Time2-Time1))


Time1 = ElapsedMilliseconds()
For i = 1 To 9000000
  result = Powf2(ftest)
Next i
Time2 = ElapsedMilliseconds()
MessageRequester("asm Powf2()", Str(Time2-Time1))
Last edited by Keya on Fri Mar 04, 2016 9:52 pm, edited 1 time in total.
User avatar
StarBootics
Addict
Addict
Posts: 1006
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Re: Floating-point Power of 2 (powf2 & powd2)

Post by StarBootics »

A Macro is much faster :

Code: Select all

Procedure.f Powf2(value.f)
  ! fld  dword [p.v_value]   ;load 32bit Float
  ! fmul st, st              ;pow2 = value * value
  ! fstp dword [p.v_value]   ;store
  ProcedureReturn value
EndProcedure

Procedure.d Powd2(value.d)
  ! fld  qword [p.v_value]   ;load 64bit Double
  ! fmul st, st              ;pow2 = value * value
  ! fstp qword [p.v_value]   ;store
  ProcedureReturn value
EndProcedure

Macro Powr2(value)
  (value * Value)
EndMacro

Define result.f, ftest.f = 7

Time1 = ElapsedMilliseconds()
For i = 1 To 9000000
  result = Pow(ftest, 2)
Next i
Time2 = ElapsedMilliseconds()
MessageRequester("Purebasic Pow()", Str(Time2-Time1))

Time1 = ElapsedMilliseconds()
For i = 1 To 9000000
  result = Powf2(ftest)
Next i
Time2 = ElapsedMilliseconds()
MessageRequester("asm Powf2()", Str(Time2-Time1))

Time1 = ElapsedMilliseconds()
For i = 1 To 9000000
  result = Powr2(ftest)
Next i
Time2 = ElapsedMilliseconds()
MessageRequester("asm Powr2()", Str(Time2-Time1))
On my computer I got 96 ms, 77 ms and 31 ms

Best regards
StarBootics
The Stone Age did not end due to a shortage of stones !
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Floating-point Power of 2 (powf2 & powd2)

Post by Keya »

yes macro would be better especially seeing as its so tiny :)
Im not so sure about your multiply being faster though ...

What I'm doing is the following line (shown in three variations), in a "For i = 1 to 1.4 million" loop... note the timings!

Code: Select all

 ft = Sqr(Abs(Pow(*p1\a,2) - Pow(*p2\a,2)))        ;=128, 127, 127
 ft = Sqr(Abs(Powf2(*p1\a) - Powf2(*p2\a)))        ;=19, 18, 18
 ft = Sqr(Abs(*p1\a * *p1\a) - (*p2\a * *p2\a))    ;=538, 540, 538
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Floating-point Power of 2 (powf2 & powd2)

Post by Keya »

Hmm, i made a cut-down demo of what im doing, but this one agrees with your finding that the straight multiply is faster:

Code: Select all

Procedure.f Powf2(value.f)
  ! fld  dword [p.v_value]   ;load 32bit Float
  ! fmul st, st              ;pow2 = value * value
  ! fstp dword [p.v_value]   ;store
  ProcedureReturn value
EndProcedure


bufa = AllocateMemory(9000000)
bufb = AllocateMemory(9000000)
*p1.Ascii = bufa
*p2.Ascii = bufb


Time1 = ElapsedMilliseconds()
For i = 1 To 9000000
 ;ft = Sqr(Abs(Pow(*p1\a,2) - Pow(*p2\a,2)))        ;=257, 248, 249
 ;ft = Sqr(Abs(Powf2(*p1\a) - Powf2(*p2\a)))        ;=48, 50, 48
 ft = Sqr(Abs(*p1\a * *p1\a) - (*p2\a * *p2\a))     ;=34, 41, 33
 *p1+1: *p2+1
Next i
Time2 = ElapsedMilliseconds()

MessageRequester("Time", Str(Time2-Time1))
but that leaves me perplexed as to why it's performing differently in my other code! completely different timings from what should be identical code. Well... at the end of the day i'll be saving a lot of time (have to call this a lot), that's the main thing lol :D
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Floating-point Power of 2 (powf2 & powd2)

Post by wilbert »

Compared with the other two lines, your line should probably be

Code: Select all

ft = Sqr(Abs(*p1\a * *p1\a - *p2\a * *p2\a))
instead of

Code: Select all

ft = Sqr(Abs(*p1\a * *p1\a) - (*p2\a * *p2\a))
If you really need to do this calculation so often, you might consider converting the whole equation to asm.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Floating-point Power of 2 (powf2 & powd2)

Post by Keya »

ahhh yes! good catch thankyou :) caffeine levels not good here for debugging
the speed of the procedure is actually really good so far, Pow() seemingly the only bottleneck. I wasnt sure how Sqr() would go but it seems fast, and likewise no hiccups from Abs()
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Floating-point Power of 2 (powf2 & powd2)

Post by wilbert »

Keya wrote:I wasnt sure how Sqr() would go but it seems fast, and likewise no hiccups from Abs()
Pow() requires multiple instructions, Sqr() only one (fsqrt). How fast that fsqrt instruction is, depends a lot on the cpu architecture but on a modern Intel cpu it's quite fast.
Windows (x64)
Raspberry Pi OS (Arm64)
Joris
Addict
Addict
Posts: 890
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: Floating-point Power of 2 (powf2 & powd2)

Post by Joris »

I'm not into ASM, but with your Powf2(value.f) you can't do a Pow(value, 1.3) or whatever 'power value', or am I missing something ?

OOoops yeah sorry saw it just a litle later "Power of 2"...
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Post Reply