Faster Floats

BlitzMax Forums/BlitzMax Programming/Faster Floats

ImaginaryHuman(Posted 2007) [#1]
I was doing some speed tests to see how fast my computer (Intel iMac Core2 Duo 2GHz) is at reading and writing different types of data (bytes, shorts, ints, floats etc), based on number of instructions or based on amount of memory read. Looks like if you store a Float as an integer and read it from an Integer it is faster than reading it from a float:

Local MyFloat:Float
IntPtr(VarPtr(MyFloat))[0]=IntegerMemoryPtr[offset]

is faster than
Local MyFloat:Float=FloatMemoryPtr[offset]

Reading the float from binary data stored in an int with an Int Ptr took about 200 millisecs, versus 300 for reading from a Float pointer.

Also
IntegerMemoryPtr[offset]=IntPtr(VarPtr(MyFloat))

is faster than
FloatMemoryPtr[offset]=MyFloat

Writing the float to memory as an integer of binary data took 167 millisecs, versus 173 millisecs to write a Float to a Float pointer.

Okay so the write isn't that much faster, but the read is significantly faster. Also seems in general that dealing with floats and doubles and longs is substantially slower than dealing with Int's, more than just the extra bytes of memory access.

Maybe reading a floating point number (Float/Double) in from memory entails reading the memory, writing it back out as a float, then reading it into a float variable? I know the PPC processor used to have the issue that a float had to be written to memory before it could be read as an integer, and vice versa.


marksibly(Posted 2007) [#2]
Bad idea.

The first one is faster because it's doing an integer move.

However, if you ever actually want to *use* the float (god forbid), a float move will eventually be required!

In addition, the first one will cause the float to be spilled, since you are taking the address of a local variable (which always causes a local to spill).


ImaginaryHuman(Posted 2007) [#3]
Interesting. I understand what you're saying except for spilling. What is that? Do you mean that getting the address of a local requires pushing it into memory and is then accessed as an integer from memory?

I do disagree though about needing to do a float move. If you create the float as a real Float variable, and write its bytes using varptr to a 4-byte space in memory, then to re-use it you just create a blank Float variable and read the bytes into its memory space. Why wouldnt you be able to just use the Float once you've read the bytes into its memory?


Floyd(Posted 2007) [#4]
All floating point operations take place in special 80-bit registers. Since this is the only way such numbers can be used it seems reasonable for BlitzMax to load the number into a register as it moves the value in memory.

If you had an application which needed to move large amounts of floating point numbers, without doing any operations on them, then it would make sense to do the kind of floatless read/write that you suggested. There aren't many such applications. Notice that sorting is not one them as the numbers must be loaded into registers in order to compare them.


ImaginaryHuman(Posted 2007) [#5]
Ok. So at some point there has to be a transfer to the Float register in order to use the values, so the speedup wouldn't apply.

I found also that Reading/Writing memory using Doubles is faster than using Int's or Long's, if you need to just move memory around. Doubles took 40 millisecs while Int's took about 60, even though in general Int's are much faster than everything else for math and stuff. Longs in general seem kind of slow - I thought perhaps a Long would be a nice fast 64-bit move but alas not.

Int's are way faster than using Shorts and Bytes that it almost seems pointless to use Shorts and Bytes unless you want to save memory space - even if you store byte values in Int's and read four times as much memory it's faster than reading individual bytes.