Code optimization

General FreeBASIC programming questions.
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Code optimization

Postby Ophelius » Apr 08, 2010 2:19

I'm trying to optimize my code and thought that creating a lookup table for trig functions would greatly optimize calculations(especially when I'm making several of those calculations per frame). I wrote up some test code to see how much better it would be:

Code: Select all


    DIM SHARED AS SINGLE SINE(-10000 TO 10000), COSINE(-10000 TO 10000), ATAN(-25000 to 25000)

    dim j as single
    FOR j = -25000 to 25000
        ATAN(j) = ATN(j/10000)
    next j
   
    FOR j = -10000 to 10000
        SINE(j) = SIN(j/10000)
    next j

    FOR j = -10000 to 10000
        COSINE(j) = COS(j/10000)
    next j
   
    dim ST AS SINGLE
    dim as single b
   
    dim i as integer
    ST = TIMER
    do
        b = ATN(rnd)
        i += 1
    loop until TIMER - ST >= 10
   
    PRINT "ATN:";i
   
    i = 0
    ST = TIMER
    do
        b = SIN(rnd)
        i += 1
    loop until TIMER - ST >= 10
    PRINT "SIN:";i
   
    i = 0
    ST = TIMER
    do
        b = COS(rnd)
        i += 1
    loop until TIMER - ST >= 10
    PRINT "COS:";i
    PRINT
   
    i = 0
    ST = TIMER
    do
        b = ATAN(INT(rnd*10000))
        i += 1
    loop until TIMER - ST >= 10
    PRINT "ATAN:";i
   
    i = 0
    ST = TIMER
    do
        b = SINE(INT(rnd*10000))
        i += 1
    loop until TIMER - ST >= 10
    PRINT "SINE:";i

    i = 0
    ST = TIMER
    do
        b = COSINE(INT(rnd*10000))
        i += 1
    loop until TIMER - ST >= 10
    PRINT "COSINE:";i
   
    sleep



Turns out it isn't that much faster. Here are my results in calculations/sec:

ATN: 970,491.8
SIN: 963,806.3
COS: 970,074.9

ATAN: 1,003,734.7
SINE: 998,793.1
COSINE: 1,010,858.3

Note: The arrays are dimensioned for my min and max values. They might differ for other implementations.

Any way to optimize trig functions further or differently?
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Postby 1000101 » Apr 08, 2010 3:32

Well, you will have to change your benchmark so you are benchmarking what you think you are. Right now you are benchmarking rnd which is a very slow function. Instead of using rnd just run it through the same loop for each method but build a list of random values at the start. This also insures that each method is processing the same data.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Apr 08, 2010 3:32

Code: Select all

'====================================================================
#include "windows.bi"
#include "counter.bas"
'====================================================================
'' Counter.bas is available here:
''
'' http://www.freebasic.net/forum/viewtopic.php?t=4221#4221
'====================================================================

Dim Shared As Single SINE(-10000 To 10000)
Dim Shared As Single COSINE(-10000 To 10000)
Dim Shared As Single ATAN(-25000 To 25000)

for i as single = -25000 To 25000
  ATAN(i) = atn(i/10000)
next

for i as single = -10000 To 10000
  SINE(i) = sin(i/10000)
next

for i as single = -10000 To 10000
  COSINE(i) = cos(i/10000)
next

dim as single a,b

sleep 3000

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = rnd
counter_end
print "rnd",counter_cycles;" cycles"

randomize timer
a = rnd

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = atn(a)
counter_end
print "atn",counter_cycles;" cycles"

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = sin(a)
counter_end
print "sin",counter_cycles;" cycles"

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = cos(a)
counter_end
print "cos",counter_cycles;" cycles"

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = ATAN(0)
counter_end
print "ATAN",counter_cycles;" cycles"

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = SINE(0)
counter_end
print "SINE",counter_cycles;" cycles"

counter_begin( 1000, HIGH_PRIORITY_CLASS )
  b = COSINE(0)
counter_end
print "COSINE",counter_cycles;" cycles"

sleep

Results on my P3:

Code: Select all

rnd           71 cycles
atn           142 cycles
sin           105 cycles
cos           96 cycles
ATAN          5 cycles
SINE          5 cycles
COSINE        5 cycles
Last edited by MichaelW on Apr 08, 2010 3:44, edited 3 times in total.
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Apr 08, 2010 3:32

LUTs in a machine with an FPU is useless. Use only LUTS when you need to calculate multiple trig values in one call. ie. Plasmas. Trig Luts are only used for machines with no FPU.
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Postby Ophelius » Apr 08, 2010 3:41

relsoft wrote:LUTs in a machine with an FPU is useless. Use only LUTS when you need to calculate multiple trig values in one call. ie. Plasmas. Trig Luts are only used for machines with no FPU.


When you say one call, do you mean one Frame, one line, what? I'm guessing all computers these days have floating point units?

MichaelW: Thanks for the code and results. I can see it's much faster. ;)

1000101 wrote:Instead of using rnd just run it through the same loop for each method but build a list of random values at the start. This also insures that each method is processing the same data.

I figured since every calculation was using the rnd function anyways, so I figure it wouldn't affect the outcome. I thought a call to rnd would take the same time every time.

Return to “General”

Who is online

Users browsing this forum: No registered users and 10 guests