Rkshvch
Rkshvch

Reputation: 113

What is faster: compare then change, or change immediately?

Let I'm doing very fast loops and I have to be sure that in the end of each loop the variable a is SOMEVALUE. What will be faster?

if (a != SOMEVALUE) a = SOMEVALUE;

or just instantly do

a = SOMEVALUE;

Is it float/int/bool/language specific?

Update: a is a primitive type, not a class. And the possibility of TRUE comparison is 50%. I know that the algorithm is what makes a loop fast, so my question is also about the coding style.

Update2: thanks everyone for quick answers!

Upvotes: 3

Views: 1824

Answers (9)

ArjunShankar
ArjunShankar

Reputation: 23680

That if can actually be 'optimized away' by some compilers, basically turning the if into code noise (for the programmer who's reading it).

When I compile the following function with GCC for x86 (with -O1, which is a pretty reasonable optimization level):

int foo (int a)
{
  int b;

  if (b != a)
    b = a;

  b += 5;

  return b;
}

GCC just 'optimizes' the if and the assignment away, and simply uses the argument to do the addition:

foo:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        popl    %ebp
        addl    $5, %eax
        ret
        .ident  "GCC: (GNU) 4.4.3"

Having or not having the if generates exact the same code.

Upvotes: 1

MByD
MByD

Reputation: 137332

Change immediately is usually faster, as it involves no branch in the code.

As commented below and answered by others, it really depends on many variables, but IMHO the real question is: do you care what was the previous value? If you are, you should check, otherwise, you shouldn't.

Upvotes: 1

Mihai Maruseac
Mihai Maruseac

Reputation: 21435

The general answer is to profile such kind of questions. However, in this case a simple analysis is available:

Each test is a branch. Each branch incurs a slight performance penalty. However, we have branch prediction and this penalty is somewhat amortized in time, depending how many iterations your loop has and how many times the prediction was correct.

Translated into your case, if you have many changes to a during the loop it is very likely that the code using if will be worse in performance. On the other hand, if the value is updated very rarely there would be an infinitely small difference between the two cases.

Still, change immediately is better and should be used, as long as you don't care about the previous value, as your snippets show.

Other reasons for an immediate change: it leads to smaller code thus better cache locality, thus better code performance. It is a very rare situation in which updating a will invalidate a cache line and incur a performance hit. Still, if I remember correctly, this will byte you only on multi processor cases and very rarely.

Keep in mind that there are cases when the two are not similar. Comparing NaNs is undefined behaviour.

Also, this comment treats only the case of C. In C++ you can have classes where the assignment operator / copy constructor takes longer than testing for equality. In that case, you might want to test first.

Taking into account your update, it's better to simply use assignment as long as you're sure of not dealing with undefined behaviour (floats). Coding-style wise it is also better, easier to read.

Upvotes: 2

Luchian Grigore
Luchian Grigore

Reputation: 258618

Profile the code. Change accordingly.

For basic types, the no branch option should be faster. MSVS for example doesn't optimize the branch out.

That being said, here's an example of where the comparison version is faster:

struct X
{
    bool comparisonDone;
    X() : comparisonDone(false) {}
    bool operator != (const X& other) { comparisonDone = true; return true; }
    X& operator = (const X& other)
    {
       if ( !comparisonDone )
       {
           for ( int i = 0 ; i < 1000000 ; i++ )
               cout << i;
       }
       return *this;
    }
}

int main()
{
    X a;
    X SOMEVALUE;
    if (a != SOMEVALUE) a = SOMEVALUE;
    a = SOMEVALUE;
}

Upvotes: 1

Senthil Babu
Senthil Babu

Reputation: 1263

As you are asking this for a C++ program, I assume that you are compiling the code into native machine instructions.

Assigning the value directly without any comparison should be much faster in any case. To compare the values, both the values a and SOMEVALUE should be transferred to registers and one machine instruction cmp() has to be executed.

But in the later case where you assign directly, you just move one value from one memory location to another.

Only way the assignment can be slower is when memory writes are significantly costlier than memory reads. I don't see that happening.

Upvotes: 1

Giovanni B
Giovanni B

Reputation: 1032

As others have said, profiling it is going to be the easiest way to tell as it depends a lot on what kind of input you're throwing at it. However, if you think about the computational complexity of the two algorithms, the more input you throw at it, the smaller any possible difference of them becomes.

Upvotes: 1

Art
Art

Reputation: 20392

In almost all cases just setting the value will be faster.

It might not be faster when you have to deal with cache line sharing with other cpus or if 'a' is in some special type of memory, but it's safe to assume that a branch misprediction is probably a more common problem than cache sharing.

Also - smaller code is better, not just for the cache but also for making the code comprehensible.

If in doubt - profile.

Upvotes: 2

john
john

Reputation: 8027

I would be surprised is the answer wasn't a = somevalue, but there is no generic answer to this question. Firslty it depends on the speed of copy versus the speed of equality comparison. If the equality comparison is very fast then your first option may be better. Secondly, as always, it depends on your compiler/platform. The only way to answer such questions is to try both methods and time them.

Upvotes: 1

unwind
unwind

Reputation: 399843

You should profile it.

My guess would be that there is little difference, depending on how often the test is true (this is due to branch-prediction).

Of course, just setting it has the smallest absolute code size, which frees up instruction cache for more interesting code.

But, again, you should profile it.

Upvotes: 1

Related Questions