branches (if) and iterations (for)

S

s

Hello all,

I was wondering on the following:

Regarding modern C++ compilers, is there a performance difference
between the following pseudo
code snips regarding the effects of:

* the taken/not taken conditions/branches and the CPU branch
prediction;
* and/or pipeline invalidations on missed branches;

And if there's no performance difference, which version would you
choose (regarding maintainability,etc.)?



## version 1 with `break`

for (int i=0; i < array_len; i++ )
{
if ( array == requested_item )
{
found = true;
break;
} // if

} // for

if found ....

## version 2 with `continue`

for (int i=0; i < array_len; i++ )
{
if ( array != requested_item )
{
continue;
} // if

found = true;
break;
} // for

if found ....
 
J

Jonathan Lee

for (int i=0; i < array_len; i++ )
{
  if ( array == requested_item )
  {
     found = true;
     break;
  } // if

} // for


Well, presumably you don't want i to go out of scope
so I'd end up writing

int i = 0;
while (i < array_len && array != requested_item) {
// if (!found) ...
++i;
}
if (i < array_len) { /* i.e., found */ } else { ... }

This is easier to read for me. Performance wise I doubt
you'd find any significant difference between the
versions.

--Jonathan
 
J

Jeff Flinn

Jonathan said:
for (int i=0; i < array_len; i++ )
{
if ( array == requested_item )
{
found = true;
break;
} // if

} // for


Well, presumably you don't want i to go out of scope
so I'd end up writing

int i = 0;
while (i < array_len && array != requested_item) {
// if (!found) ...
++i;
}
if (i < array_len) { /* i.e., found */ } else { ... }

This is easier to read for me. Performance wise I doubt
you'd find any significant difference between the
versions.


or since the op didn't define the type of array, and since this is 2009
and the op should be using a std container:

Array::iterator itr =
std::find(array.begin(), array.end(), requested_item);

if( itr != array.end())
{
...
}

and if it's not a std container

requested_item_type* itr =
std::find(array, array + array_len, requested_item);

if( itr != (array + array_len))
{
...
}

Jeff
 
J

Jonathan Lee

or since the op didn't define the type of array, and since this is 2009
and the op should be using a std container:

I think he's asking about the form of the loop, as opposed
to how to find things in an array.

--Jonathan
 
P

Pavel

s said:
Hello all,

I was wondering on the following:

Regarding modern C++ compilers, is there a performance difference
between the following pseudo
code snips regarding the effects of:

* the taken/not taken conditions/branches and the CPU branch
prediction;
* and/or pipeline invalidations on missed branches;

And if there's no performance difference, which version would you
choose (regarding maintainability,etc.)?



## version 1 with `break`

for (int i=0; i< array_len; i++ )
{
if ( array == requested_item )
{
found = true;
break;
} // if

} // for

if found ....

## version 2 with `continue`

for (int i=0; i< array_len; i++ )
{
if ( array != requested_item )
{
continue;
} // if

found = true;
break;
} // for

if found ....


The modern compilers sometimes provide implementation-specific means for
a programmer to let compiler know what branch is likely to happen in the
program (see __builtin_expect in gcc or

http://kerneltrap.org/node/4705

for some discussion).

The "old-school" thinking was that you wanted to put the break on a
condition that happens rarely in the loop header (the compiler would
commonly generate a forward jump for that) and the one you check within
a loop will be assumed to happen more often but I am not sure if it is
still a common assumption by the compiler writers.

On a side note, if you use loop unrolling optimization (such as
-funroll-loops for gcc), you may end up with a completely unexpected
generated code (gcc especially loves unrolling the form of "for" loop
you used in your example).

As every modern compiler is even more different than way back, your best
bet is probably just reading the assembly listing of the code generated
by your compiler of choice with the particular set of options you are
going to use in your release configuration.

-Pavel
 
J

Jerry Coffin

Hello all,

I was wondering on the following:

Regarding modern C++ compilers, is there a performance difference
between the following pseudo
code snips regarding the effects of:

* the taken/not taken conditions/branches and the CPU branch
prediction;
* and/or pipeline invalidations on missed branches;

And if there's no performance difference, which version would you
choose (regarding maintainability,etc.)?

Neither. I prefer to include the real exit condition from the loop in
the condition for the loop itself, so I'd probably do something like:

bool found = false;

for (int i=0; i<array_len && !found; i++)
found = (array == requested_item);

if (found)
// ...

While it's possible that you might be able to measure a speed
difference between this and one of the others, I wouldn't bet a lot
on it. One compiler might favor one, and another compiler another.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top