## Fixed point math benchmark

General FreeBASIC programming questions.
xlucas
Posts: 263
Joined: May 09, 2014 21:19
Location: Argentina

### Fixed point math benchmark

For a routine that I needed to go superfast and didn't require high precision, I was thinking of adding an extra boost through the old practice of switching to fixed point math. To my surprise, my test benchmarks are telling me this isn't a good idea. Even integers (without the extra multiplication/shifting) seem to work slightly slower than doubles. How come?

Code: Select all

`Dim t As Double, n As LongIntDim As Double d1 = 299991, d2 = 299990, d3 = 1Dim As LongInt i1 = 299991, i2 = 299990, i3 = 1Print "Integers:"t = TimerDo   i3 *= i1   i3 /= i2   n += 1Loop Until Timer >= t + 1Print n, i3GetKeyPrint "Doubles:"t = TimerDo   d3 *= d1   d3 /= d2   n += 1Loop Until Timer >= t + 1Print n, d3GetKey`

On my computer, the code yields about 11 million iterations for integers and somewhat over 23 million iterations for doubles. What am I doing wrong? Or do current CPUs really perform better with floating point than with integers? :o
dodicat
Posts: 5155
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Fixed point math benchmark

You use longint.
change to long -optional
you are not resetting n
you cannot rely on the first run only.
Loop a while and see.

Code: Select all

`Dim t As Double, n As LongDim As Double d1 = 299991, d2 = 299990, d3 = 1Dim As Long i1 = 299991, i2 = 299990, i3 = 1do  i1 = 299991: i2 = 299990: i3 = 1  Print "Integers:"t = TimerDo   i3 *= i1   i3 /= i2   n += 1Loop Until Timer >= t + 1Print n, i3'GetKeyd1 = 299991: d2 = 299990: d3 = 1n=0sleep 100Print "Doubles:"t = TimerDo   d3 *= d1   d3 /= d2   n += 1Loop Until Timer >= t + 1Print n, d3printsleep 200'GetKeyloop until len(inkey) `
D.J.Peters
Posts: 7428
Joined: May 28, 2005 3:28

### Re: Fixed point math benchmark

you measured the timer() call too
note: integer div is "\" not "/"

By the way here are fast fixed point math including vector and matrix math.
(fadd, fmul, fmul, fdiv, fsin, fcos, fsqr, fsrqd, ftan ...)
viewtopic.php?f=7&t=22838

Joshy

32-bit data types on 64-bit OS
ints 1.225493478923397
real 16.572667466356

64-bit data types on 64-bit OS
Integers ...
Real ...
ints 2.146352917887271
real 1.429170743445866

Code: Select all

`#ifndef __FB_64BIT__type real as singletype ints as long#elsetype real as doubletype ints as longint#endifDim As real d1 = 299991, d2 = 299990, d3 = 1Dim As ints i1 = 299991, i2 = 299990, i3 = 1const N = 1000 * 1000 * 100var tStart = Timer()Print "Integers ..."tStart = Timer()for i as integer = 1 to n   i3 *= i1   i3 \= i2nextvar tInts=Timer()-tStart   Print "Real ..."tStart = Timer()for i as integer = 1 to n   d3 *= d1   d3 /= d2nextvar tReal=Timer()-tStart   print "ints " & tIntsprint "real " & tRealsleep`
Last edited by D.J.Peters on Oct 22, 2017 0:24, edited 2 times in total.
paul doe
Posts: 772
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: Fixed point math benchmark

Hola cumpis
xlucas wrote:On my computer, the code yields about 11 million iterations for integers and somewhat over 23 million iterations for doubles. What am I doing wrong? Or do current CPUs really perform better with floating point than with integers? :o

You may also want to check out this:
https://dsp.stackexchange.com/questions/4835/relative-merits-of-fixed-point-vs-floating-point-computation

Hope it helps.
Paul
jj2007
Posts: 844
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: Fixed point math benchmark

If speed is really important, consider switching to packed singles. That is a factor 4 gain, but it requires a bit of SIMD skills.
xlucas
Posts: 263
Joined: May 09, 2014 21:19
Location: Argentina

### Re: Fixed point math benchmark

Oh! How could I be so stupid! Not resetting n is the main reason why this gives such weird values!

Dodicat: Thanks. I'm really surprised. I knew it was much better to perform the test several times, but I didn't expect it to give such a huge difference. Why would it be so slow the first time in comparison to the others?

Joshy: Wow! Fixed point with all the functions! Well, if I do this with fixed point, it's not a whole program using it. It'd be just one routine that would make its calculations with fixed point. It'd be a few multiplications and a couple of divisions, it's just it'd be called many, many times. So instead of building functions, I'd probably just enter the fixed point math inline. So from your numbers, I understand that switching to fixed point is only worth it if I am to use the same word width as my compiled code? (I imagine that a 32bit ELF running under a 64bit GNU would still run fast because it'd be running in a 32bit code memory region, but if I will use Longs, I have to compile in 32bit and if I will use LongInts, I have to compile in 64bit or just use Integers, right?)

Paul Doe: ¡Gracias! Yep, that's more or less what I was starting to think. On today's computers, it looks like fixed point math may be worth it, but you have to take lots of precautions. Just using fixed point instead of floating point at any random place in the program will likely make it slower. I'll take a benchmark for Singles vs Doubles.

jj2007: As a matter of fact, I may later on translate that single routine to assembly and call it from my program, but as you say, I would have to be very skilled to use packed singles. I'm going to first try the routine with doubles and see how slow it really is, then I'll try optimising it with singles, some fixed point, etc. If I see it is worth it, I'll translate it to assembly and I'll study packed floats to see if I can get that working. I don't want to complicate my code more than necessary, but if it looks like it'll be necessary, I will.
grindstone
Posts: 547
Joined: May 05, 2015 5:35
Location: Germany

### Re: Fixed point math benchmark

xlucas wrote:Why would it be so slow the first time in comparison to the others?
Maybe because some values become cached at the first run?
dodicat
Posts: 5155
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Fixed point math benchmark

I did a little test.
I made a C library file function multiplying two floats (singles), 4 lines of C
I compared with a freebasic function.
looping 1 to 50000000 and accumulating a float
(f+=mult(1.8876,-1.00097)

result:

Code: Select all

`Time  0.2511555792298168    Pure C   result      -3.355443e+007Time  0.3508026434574276    pure FB  result      -3.355443e+007Time  0.4116691944655031    Pure C   result      -3.355443e+007Time  0.3614287024829537    pure FB  result      -3.355443e+007Time  0.2476997915655375    Pure C   result      -3.355443e+007Time  0.3490622595418245    pure FB  result      -3.355443e+007Time  0.2498644923325628    Pure C   result      -3.355443e+007Time  0.3631800361908972    pure FB  result      -3.355443e+007Time  0.2480419827625155    Pure C   result      -3.355443e+007Time  0.362808759091422     pure FB  result      -3.355443e+007Time  0.2481223978102207    Pure C   result      -3.355443e+007Time  0.3702811852563173    pure FB  result      -3.355443e+007Time  0.2500718601513654    Pure C   result      -3.355443e+007Time  0.3465009594801813    pure FB  result      -3.355443e+007Time  0.2493067209143192    Pure C   result      -3.355443e+007Time  0.3533146679401398    pure FB  result      -3.355443e+007  `

The freebasic was 32 bit -gen gcc.
-gen gas is a little faster.

If I optimize the -gen gcc -W3 -O2 then it is faster but the result is incorrect.
Conclusion from these few code lines -- C is faster at multiplying floats than FreeBASIC.
xlucas
Posts: 263
Joined: May 09, 2014 21:19
Location: Argentina

### Re: Fixed point math benchmark

(Written before your last post, Dodicat, but relevant)

Ha, ha, ha... no! I just found out why:

Simply because Dodicat made the same mistake I made. He fixed mine and reset n to 0 after the first loop, but forgot to do the same after the second. Dodicat: after fixing that, it looks like there virtually is no difference between integers and floating point. It doesn't seem to matter if it's single or double or whether it's long or longint. My guess is the reason is that the check for Timer is so much slower than the multiplication and division that the latter go unnoticed.

Now we're talking...

Code: Select all

`Dim t As Double, n As LongDim As Double d1 = 299991, d2 = 299990, d3 = 1Dim As Long i1 = 299991, i2 = 299990, i3 = 1Dim k As Longdo  i1 = 299991: i2 = 299990: i3 = 1 Print "Integers:"t = TimerDo   For k = 1 To 1000      i3 *= i1      i3 /= i2      n += 1   Next kLoop Until Timer >= t + 1Print n, i3'GetKeyd1 = 299991: d2 = 299990: d3 = 1n=0sleep 100Print "Doubles:"t = TimerDo   For k = 1 To 1000      d3 *= d1      d3 /= d2      n += 1   Next kLoop Until Timer >= t + 1Print n, d3printsleep 200n=0'GetKeyloop until len(inkey) `

Still, the difference is not immense
dodicat
Posts: 5155
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Fixed point math benchmark

Oops!
sorry n

If you use addition or multiplication then integers are faster.
But the division (/) slows down integers.
Maybe as suggested use (\) for integers.
dodicat
Posts: 5155
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Fixed point math benchmark

Try without timer swamping and using integer division for integers.

Code: Select all

`Dim t As Double, n As LongDim As Double d1 = 299991, d2 = 299990, d3 = 1Dim As Long i1 = 299991, i2 = 299990, i3 = 1Dim k As Longdo  i1 = 299991: i2 = 299990: i3 = 1 Print "Integers:"t = Timer   For k = 1 To 100000000      i3 *= i1      i3 \= i2      n += 1   Next kPrint  timer-t, i3,n'GetKeyd1 = 299991: d2 = 299990: d3 = 1n=0sleep 100Print "Doubles:"t = Timer   For k = 1 To 100000000      d3 *= d1      d3 /= d2      n += 1   Next kPrint timer-t, d3,nprintsleep 200n=0'GetKeyloop until len(inkey)sleep  `
xlucas
Posts: 263
Joined: May 09, 2014 21:19
Location: Argentina

### Re: Fixed point math benchmark

Oh! I thought operator / was mapped to operator \ when the two operands were integers! But it makes sense it doesn't, since it has to return a floating point number anyway. So I'm getting that plain integers are 19% faster than doubles when multiplying and dividing.
jj2007
Posts: 844
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: Fixed point math benchmark

I've put a testbed in the Masm32 forum.

It seems that floats and doubles are about 30% faster than integers.

Note that FreeBasic uses the FPU to do the div:

Code: Select all

`mov dword ptr [ebp-14], 1 mov eax, [ebp-38]        imul eax, [ebp-30]       mov ebx, eax             mov [ebp-38], ebx        fild dword ptr [ebp-38]  fild dword ptr [ebp-34]  fxch st(1)               fdivrp st(1), st         fistp dword ptr [ebp-38]`

Same in hand-written assembly:

Code: Select all

`fild i3fimul i1fidiv i2fistp i3`

Shorter and faster. Note also that the accuracy of results is much lower with integer arithmetics.