12-10-2019 09:14 AM
Hello everyone,
I have a few Interrupt service routines in my C program. Each of these uses math functions, sqrt() and asin(), both a couple of times. I faced some glitches in my code operation but couldn't find the reason until the I measured the total execution time of the ISR. It was 5 us each which is HUGE. I tried to reduce the calculations as much as possible but couldn't reduce this execution time significantly.
Is there a way to optmize the math functions to save time? Or is there any other solution to this issue?
Thank you.
Best regards,
Pramod
12-11-2019 12:30 PM
To use loook-up tables you have to remap your input between 0 and N-1 (N being the size of the table, idealy a power of 2). For asin(), it is the simplest because the input is bounded between -1.0 and +1.0 and asin(-x) == -asin(x). If the input is negative, memo it is and use -x. The input value is multiplied by N-1, giving you the index in the table. The larger the table, the more resolution/precision your result will have; you can also interpolate between Idx & Idx+1 using the remainder, i.e. input * (N-1) % 1. Then use - table value if the inpur was -ve.
For sqrt(), the idea is alike, except sqrt(4n) == 2*sqrt(n). By bringing the input between 0. and 4.0-epsilon (memorizing the scaling factor used, divided by 2) you read the table with the index (ScaledInput * N-1) and then apply the scaling factor / 2.
I assume your input and output are integers, if so, then all these manipulations can done with int meaning almost no CPU as they involve shfts and mutiplfy (for sqrt) if you play a bit with the size of the table, or index remapping or special handling when the index would be N. As for how to create the tables, look at what the indexes are vs the value used to determine the index and generate the tables accordingly.
12-10-2019 09:39 AM
12-10-2019 06:40 PM
I agree with @drjohnsmith for using trigonometrics in an interrupt.. As for your question(s): "Is there a way to optmize the math functions to save time? Or is there any other solution to this issue?". Likely, but more details should be provided.
The ubiquitous solution, if a high precision is not required, is to use look-up tables for these functions. Else, if a high precision is required, then you'll have to get your hands dirty by writing your own, either using low order polynomial approximation or with Cordic iterations using just a few iterations.
12-11-2019 06:40 AM - edited 12-11-2019 06:42 AM
Hello @drjohnsmith ,
Thank you for your answer. ISRs in my code are used for control and modulation of a converter as I need to update variables synchronous to all the ISRs. My main loop has bare minimum calculations. There is no way around for me but to make these calculations in these interrupts. I had read that these PL-PS interrupts are queued up until they are executed. Also, I am not worried if I lose a lower priority interrupt but my higher priority interrupt gets executed.
Hello @ericv ,
Could you tell me what more details are needed? I did think of using look-up tables but I had no idea how much faster they are compared to the math functions.
12-11-2019 12:30 PM
To use loook-up tables you have to remap your input between 0 and N-1 (N being the size of the table, idealy a power of 2). For asin(), it is the simplest because the input is bounded between -1.0 and +1.0 and asin(-x) == -asin(x). If the input is negative, memo it is and use -x. The input value is multiplied by N-1, giving you the index in the table. The larger the table, the more resolution/precision your result will have; you can also interpolate between Idx & Idx+1 using the remainder, i.e. input * (N-1) % 1. Then use - table value if the inpur was -ve.
For sqrt(), the idea is alike, except sqrt(4n) == 2*sqrt(n). By bringing the input between 0. and 4.0-epsilon (memorizing the scaling factor used, divided by 2) you read the table with the index (ScaledInput * N-1) and then apply the scaling factor / 2.
I assume your input and output are integers, if so, then all these manipulations can done with int meaning almost no CPU as they involve shfts and mutiplfy (for sqrt) if you play a bit with the size of the table, or index remapping or special handling when the index would be N. As for how to create the tables, look at what the indexes are vs the value used to determine the index and generate the tables accordingly.
12-11-2019 01:31 PM
2 corrections for sqrt():
- the scaling factor to apply is sqrt(scaling) and not divided by 2. sqrt(scaling) is easy to calclated using int because for every >>4 f te input, the scaling factor is incremented by 1 (starting at 1.0).
- the index is scaledinput *(N-1)/4 and not scaldeinput*(N-1) because the entry at N-1 is 4.0.
12-16-2019 01:24 AM
Thank you Eric. I will try and see if the implementation of look-up tables helps/is necessary.