exp function speed

I'm trying to streamline the code in my loop subroutine as much as possible. It needs to run as quickly as possible and there's a monumental amount of code to process in each loop!
My current worry is about a few calls to the standard math exp function. Is this quite slow or should I not be worrying about it? I guess what I really want to know is how it compares with other math functions (add, divide, sqrt etc). If it's significantly slower, I may need to think of another way to do it (e.g. lookup tables).

Paul

You'll find it's a lot slower than simpler operations like add and multiply. Why not write a program to measure it? A simple way would be to blink an LED but where you would normally make delay() calls, have a loop in which you make exp() calls.

Rather than have to employ a frequency meter to measure the speed, use this idiom:

  long duration = micros () ;
  .. code to time ..
  duration = micros () - duration ; // calculates timestamp difference.
  Serial.print (duration) ; Serial.println ("us") ;

Great thanks, will give it a try.
Paul

paulsoulsby:
I'm trying to streamline the code in my loop subroutine as much as possible. It needs to run as quickly as possible and there's a monumental amount of code to process in each loop!
My current worry is about a few calls to the standard math exp function. Is this quite slow or should I not be worrying about it? I guess what I really want to know is how it compares with other math functions (add, divide, sqrt etc). If it's significantly slower, I may need to think of another way to do it (e.g. lookup tables).

Paul

All Arduinos (including the Due) have no direct support for floating point, and need to emulate it in software. So figure a basic add might be something like a hundred cycles, a multiply a couple of hundred, and divide and square root are measured in thousands of cycles. Exp is made up of quite a few multiplies, adds, and compares, so it is also fairly slow.

So, if you are extremely speed challenged, you need to figure how to do the calculations in integer arithmetic (and note on non-Due Arduinos, even integer calculations are multiple cycles, but it is still much faster than floating point).

Or alternatively, if you cannot do it fast enough on the Arduino, you need to move to a processor with a faster clock rate and that has floating point calculations in hardware, such as the Raspberry Pi, which has a clock rate 40 times the Arduino, much, much more memory, and has both 32-bit integer and floating point direct instructions. If you search around, you will find there are various melds between the Arduino to control devices, and the R-PI to do the brunt of the calculations (or eliminating the Arduino, and doing h/w control on the R-PI). I'm not sure whether the pcDunio offered by Sparkfun has hardware floating point, but even emulated floating point should be faster than Arduinos.

Note, be sure to actually measure whether exp is slowing down your app. Perhaps your bottleneck is waiting for some event, perhaps it is the speed of the floating point calculations.

Can you show the code how you use the exp function?

What is the min and max value [range] you use as param?
Or is the param already a "complex" function?

Note you can always use a lookup table and interpolate, see - Arduino Playground - MultiMap -
Drawback is that it introduces a small error.

It's used several times, but generally in the form:

MIDI_pbend_gain = exp(floatmap(newmsb, 0, 127, -0.693147180559945, 0.693147180559945));

Where floatmap is the same as map, but can take floats.
newmsb could be anything from 0-127, hence why a lookup table won't work (it'd be to big - I've already nearly maxed out the memory!!)

Very interesting to know that the Arduino can't do floating point in hardware. I do a hell of a lot of calculations using lookup tables with values 0 to 1 and then scale as required. I wonder if I should do a total rewrite of the software and try and eliminate as much of the floats as possible....

Paul

Floats take 4 bytes each, so you would have an array that is half a kilobyte in size, right? Alright, if you have several similar arrays, it can be tight.

Low level hardware generally cannot do floating point math in hardware, so those kind of operations would be slow, no surprise there. If you need speed, you need to operate on integers until you really need to represent the floating point value somewhere, in my opinion. Or maybe there is a another cheap enough platform that can also do floating point math in hardware.

Chaul:
Floats take 4 bytes each, so you would have an array that is half a kilobyte in size, right? Alright, if you have several similar arrays, it can be tight.

Low level hardware generally cannot do floating point math in hardware, so those kind of operations would be slow, no surprise there. If you need speed, you need to operate on integers until you really need to represent the floating point value somewhere, in my opinion. Or maybe there is a another cheap enough platform that can also do floating point math in hardware.

In the USA, Rasberry Pi's are $25 for the basic model (256 megabytes of memory, no ethernet, single USB connector) or $35 for the more advanced model (512 megabytes of memory, ethernet, 2 USB connectors). Now, while the R-PI does have some pins that can be used for dealing with devices and supports I2C/SPI, it isn't its strong suit. So as I said, if you need to deal with a lot of floating point calculations, the R-PI would be much faster than an Arduino. If you are primarily touching hardware, with occasional calculations, then the Arduino is the better solution. There are people that have Arduino and R-PI combos, where they use low cost Arduinos (possibly clone machines that aren't official Arduinos) to deal with hardware, and the R-PI to be the brains.

paulsoulsby:
It's used several times, but generally in the form:

MIDI_pbend_gain = exp(floatmap(newmsb, 0, 127, -0.693147180559945, 0.693147180559945));

A float won't hold that precision anyway. If this is something to do with music you can probably achieve what you want with a lookup table. Or simplify the calculations. What is the input (music-wise) that will have 15 decimal places of precision?

You can keep your lookup table in program memory, and thus not use your valuable RAM for it.

I suggest you use a lookup table in program memory as Nick suggests. A further possibility is to make use of the fact that exp(a + b) = exp(a) * exp(b). So you could use (say) split your 7-bit value 'newmsb' into 4 bit and 3 bit values, then use one 16-entry lookup table and one 8-entry lookup table instead of a single 128-entry table.

paulsoulsby:
My current worry is about a few calls to the standard math exp function. Is this quite slow or should I not be worrying about it?

I came across this thread when searching for faster exp() method (which appears to be very slow on attiny85). I use exp to calculate Gaussian distribution (i.e. I use exp(-x*x)), and for this case I found a nice polynomial approximation:

float myexp(float x) {
 return 1.0/(1.0-(0.634-1.344*x)*x);
}

// somewhere in the code
float gaussian = myexp( -dist*dist );

This works well as approximation for exp(x) for values of x in range from -10 to 0 (but not for positive values!), making this a fast alternative to standard exp() function in some cases.

Of course, it could be much faster by using fixed-point maths.

This is a more general truth. Many of the usual math functions that are difficult to execute in small processors in fact have an infinite polynomial expression, and just using the first two or three terms gives high accuracy.

paulsoulsby:
It's used several times, but generally in the form:

MIDI_pbend_gain = exp(floatmap(newmsb, 0, 127, -0.693147180559945, 0.693147180559945));

Where floatmap is the same as map, but can take floats.
newmsb could be anything from 0-127, hence why a lookup table won't work (it'd be to big - I've already nearly maxed out the memory!!)

Very interesting to know that the Arduino can't do floating point in hardware. I do a hell of a lot of calculations using lookup tables with values 0 to 1 and then scale as required. I wonder if I should do a total rewrite of the software and try and eliminate as much of the floats as possible....

Paul

Anything you need to do with MIDI can be done FAR more efficiently using fractional integer arithmetic. I've implemented complete, professional quality 32-voice MIDI wavetable synthesizers using an 8MHz MC68008 processor for doing ALL of the control calculations, and had plenty of CPU bandwidth left over. There was NO floating point whasoever.

Regards,
Ray L.