What is the fastest way to find the maximum of two floats in C ++?

What is the fastest way to find a maximum of two floats:

and)

y = std::max(x1, x2);

      

b)

if (x1 > x2)
    y = x1;
else
    y = x2;

      

from)

y = x1 > x2 ? x1 : x2;

      

thanks

+1


a source to share


13 replies


Here's another question

Why do you think that such a small optimization would matter in the larger context of your program?

I find it highly unlikely that micro-optimizations like this will have a measurable impact on your program. You should never micro-optimize like this unless the profiler specifically showed it to be a problem.

EDIT Add explanations to comments

The reason there isn't a big answer to this question is because the performance of this code is highly dependent on ...



  • The way it was used in your program
  • The specific compiler you are using
  • Optimization flags passed to your compiler
  • In a specific architecture, you use the code
  • Many other very tiny things that were not included in the question

Even if all of this information were included, our answers would be speculations at best. The only way to answer this question is to pop out the profiler and see which is faster.

However, this is almost certainly not worth the effort. Micro-optimizing such a small part of your program will almost certainly not add any discernible advantage over your code. In general, it is a really bad idea to optimize such code, unless the profiler tells you so. Otherwise, you will spend a lot of time optimizing something without any acceptable benefits.

Yes, there are times when this kind of optimization can be important. But that would only be in special cases where the code was part of a very tight, highly called loop. However, the only way to identify such a code is to use a profiler.

+24


a source


It's compiler specific, but I suspect the result is the same. Have a look at the compiler output assembly.



+4


a source


You can check this yourself on your system.

I did it for you on gcc-redhat. Results of my system, for 100,000 executions with x1 = 432943.5 and x2 = 434232.9

a) ~ 1200 μs b) ~ 600 μs c) ~ 600 μs

EDIT: When optimizing -O2, I got the same results in all three cases: ~ 110 μs.

Of course, the actual outcome will depend on many factors in your particular problem and system.

+4


a source


-O3 Dual Core Macbook pro 2.4ghz

std :: max (x1, x2) Time: 4.19488 RMAAx: 4.19613 if time: 4.18775? Time: 4.18831

std :: max (x1, x2) Time: 4.1836 RMAAx: 4.18274 if time: 4.18603? Time: 4.18857

std :: max (x1, x2) Time: 4.18714 RMAAx: 4.18759 if time: 4.19752? Time: 4.19797

std :: max (x1, x2) Time: 4.1926 RMAAx: 4.19293 if time: 4.19334? Time: 4.19626

std :: max (x1, x2) Time: 4.18963 RMAAx: 4.19628 if time: 4.19253? Time: 4.19107

#include <iostream>

using namespace std;

int main (int argc, char * const argv[]) {

    uint64_t iterations = 10000000000;
    float x1 = 3455.232;
    float x2 = 7456.856;
    float y = 0;

    for (int count = 0; count < 5; ++count)
    {       
        clock_t begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = std::max(x1, x2);
        }

        std::cout << "std::max(x1, x2) Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1;
            if (y < x2)
                y = x2;
        }

        std::cout << "RMAAx : " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            if (x1 > x2)
                y = x1;
            else
                y = x2;
        }

        std::cout << "if Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1 > x2 ? x1 : x2;
        }

        std::cout << "? Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;
    }

    return 0;
}

      

+4


a source


Intel x86 has instructions (FCOMI / FCOMIP / FUCOMI / FUCOMIP) that provide fast comparison of floating point values. Your CPU might also have instructions like this. The trick is figuring out what C ++ writes to maximize the chances of your compiler using these instructions, instead of doing something slower but more general.

An optimistic suggestion is to use std :: max (float, float) in the hope that someone else ignores those mocking "micro lens" and "premature optimization" and did the research needed to provide specialization for std :: max (float, float) which will use your hardware's specialized instructions.

+3


a source


B and C will amount to the same, at least in theory. I choose them because if std::max

not a function call (like a macro) this will be the fastest.

Edit . Apparently std::max

is a call to a template function like your C form. Http://www.cplusplus.com/reference/algorithm/max/

+2


a source


Same observation as usual when it comes to "fastest". Have you measured the execution time of your maximum calculation being reported to the rest of the process execution time? Does this "optimization" decision have a significant impact on the runtime of your application?

I'm 99% sure the difference between your suggestions is not worth considering.

+2


a source


The only way to know this is to measure them. They can range from compiler to compiler or platform to platform.

Loop each one for 100,000 or 500,000 iterations and compare the total execution time.

+2


a source


Rate them and find out.

+2


a source


First, as others have said, profile your code and make sure it's something worth optimizing. If so, read on: you can do it without forking. See Down with fcmp: Conditional Movements for Unrated Mathematics for more details.

+2


a source


And this way could be better?

y = x1;
if (y < x2)
    y = x2;

      

Removing the else clause can be better interpreted by the compiler.

Edit1: If benchmarking remember to do half of the test with x1 greater than x2 and the other half with x2 greater. Otherwise, the results do not reflect actual cases.

Edit2: Microoptimazions are somehow useful if you are working on embedded systems with 1 or 2k memory. And also, its an interesting problem to think about why the timings are different in each case.

+1


a source


It is common to #define

use either b or c as a macro, and use it throughout your code. Note that this only works in most cases and will die if you pass an x ​​or y argument modified by a non-idempotent operator or a function call with side effects. For instance:

#define MAX(x,y) (((x) < (y)) ? (y) : (x))
...
MAX(i++, ++j); //won't work properly, the ++ will get executed twice.
MAX(changeKSomehow(k), changeLSomehow(L)); //won't work, the functions will get called twice.

      

It turns out std :: max, at least for GNU libstdc ++, is implemented in almost the same way and uses a hint inline

. The compiler should be able to take a hint when needed (when the <operator takes multiple instructions, so as not to impose a huge amount of i $ -pressure if it was inlined).

0


a source


With a decent optimizer, they are equivalent.

0


a source







All Articles