0

I want to write function in C that takes seconds and nanoseconds as input. Converts seconds and nanoseconds into microseconds, returns the total in microseconds.

unsigned long long get_microseconds(int seconds, unsigned long long nSeconds);

Now the conversion is pretty trivial. I can use following formula-

mSeconds = Seconds*1000000 + nSeconds/1000 (Loss of precision in nanosecond conversion is alright, my timer has anyway minimum resolution of 100 microseconds)

What would be fastest way of implementing this equation without using multiplication and division operators to get the best accuracy and least number of cpu cycles.

EDIT: I am running on a custom DSP with a GNU based but custom designed toolchain. I have not really tested out performance of the arithmetic operation, I am simply curious to know if it would affect the performance and if is there a way to improve it.

Steve H
  • 461
  • 2
  • 10
  • 18

3 Answers3

6
return Seconds*1000000 + nSeconds/1000;

If there's any worthwhile bit-shifting or other bit manipulation worth doing, your compiler will probably take care of it.

Amit
  • 45,440
  • 9
  • 78
  • 110
1

The compiler will almost certainly optimize the multiplication as far as it can. What it will not do is "accept a small loss" when dividing by 1000, so you will perhaps find it somewhat faster writing

return Seconds*1000000 + nSeconds/1024; /* Explicitly show the error */

...keeping in mind that nSeconds can't grow too much, or the error may become unacceptable.

But whatever you do, test the results - both speed and accuracy over real inputs. Also explore converting the function to a macro and save the call altogether. Frankly, for so simple a calculation there's precious little chance to do better than an optimizing compiler.

Also, consider the weight of this optimization in the scope of the global algorithm. Is this function really called with such a frequency that its savings are worth the hassle?

LSerni
  • 55,617
  • 10
  • 65
  • 107
0

If nSeconds never gets above 232 (it shouldn't if you are working with "split time" as from timespec - it should be below 109), you should probably use a 32 bit integer for it.

On a 64 bit machine it's not a problem to use 64 bit integers for everything (the division is optimized to a multiply by inverse+shift), but on a 32 bit one the compiler gets tricked into using a full 64 bit division routine, which is quite heavyweight. So, I would do:

unsigned long long get_microseconds(int seconds, unsigned long nSeconds) {
    return seconds*1000000ULL + nSeconds / 1000;
}

This, at least on x86, doesn't call external routines and manages to keep the 64 bit overhead to a minimum.

Of course, these are tests done on x86 (which has a 32x32=>64 multiply instruction even in 32 bit mode), given that you are working on a DSP you would need to check the actual code produced by your compiler.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299