## Code optimization

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

### Code optimization

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
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

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)nextfor i as single = -10000 To 10000  SINE(i) = sin(i/10000)nextfor i as single = -10000 To 10000  COSINE(i) = cos(i/10000)nextdim as single a,bsleep 3000counter_begin( 1000, HIGH_PRIORITY_CLASS )  b = rndcounter_endprint "rnd",counter_cycles;" cycles"randomize timera = rndcounter_begin( 1000, HIGH_PRIORITY_CLASS )  b = atn(a)counter_endprint "atn",counter_cycles;" cycles"counter_begin( 1000, HIGH_PRIORITY_CLASS )  b = sin(a)counter_endprint "sin",counter_cycles;" cycles"counter_begin( 1000, HIGH_PRIORITY_CLASS )  b = cos(a)counter_endprint "cos",counter_cycles;" cycles"counter_begin( 1000, HIGH_PRIORITY_CLASS )  b = ATAN(0)counter_endprint "ATAN",counter_cycles;" cycles"counter_begin( 1000, HIGH_PRIORITY_CLASS )  b = SINE(0)counter_endprint "SINE",counter_cycles;" cycles"counter_begin( 1000, HIGH_PRIORITY_CLASS )  b = COSINE(0)counter_endprint "COSINE",counter_cycles;" cycles"sleep`

Results on my P3:

Code: Select all

`rnd           71 cyclesatn           142 cyclessin           105 cyclescos           96 cyclesATAN          5 cyclesSINE          5 cyclesCOSINE        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:
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
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.