开发者

Is there a faster alternative to if-else in this case?

while(some_condition){  
    if(FIRST)  
    {   
        do_this;  
    }  
    else  
    {  
        do_that;  
    }
}

In my program the possibility of if(FIRST) succeeding is about 1 in 10000. Can there be any alternative in C/C++ such that we can avoid checking the condition on every iteration inside the while loop with the hope of seeing a better performance in this case.

Ok! Let me put in some more detail. i am writing a code for a signal acquisiton and tracking scheme where the state of my system will remain in TRACKING mode more often that ACQUISITION mode.

while(signal_present)  
{    
    if(ACQUISITION_SUCCEEDED)  
    {     
        do_tracking();  // this functions can change the state from TRACKING to ACQUISITION  
    }    
    else  
    {    
        do_acquisition();  // this f开发者_开发知识库unction can change the state from ACQUISITION to TRACKING  
    }     
}    

So what happens here is that the system usually remains in tracking mode but it can enter acquisition mode when tracking fails but is not a common occurrence.( Assume the incoming data to be infinite in number. )


The performance cost of a single branch is not going to be a big deal. The only thing you really can do is put the most likely code first, save on some instruction cache. Maybe. This is really deep into micro-optimization.


There is no particularly good reason to try to optimize this. Almost all modern architectures incorporate branch predictors. These speculate that a branch (an if or else) will be taken essentially the way it has been in the past. In your case, the speculation will always succeed, eliminating all overhead. There are non-portable ways to hint that a condition is taken one way or another, but any branch predictor will work just as well.

One thing you might want to do to improve instruction-cache locality is to move do_that out of the while loop (unless it is a function call).


The GCC has a __builtin_expect “function” that you can use to indicate to the compiler which branch will likely be taken. You could use it like this:

if(__builtin_expect(FIRST, 1)) …

Is this useful? I have no idea. I have never used it, never seen it used (except allegedly in the Linux kernel). The GCC documentation actually discourages its usage in favour of using profiling information to achieve a more reliable metric.


On recent x86 processor systems, final execution speed will barely rely on source code implementation.

You can have a look at this page http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/ to see amount the optimization that occurs inside the processor.


If this test is really consuming significant time compared to the implementation of do_aquisition, then you might get a boost by having a function table:

typedef void (*trackfunc)(void);
trackfunc tracking_action[] = {do_acquisition, do_tracking};
while (signal_present)
{
   tracking_action[ACQUISITION_STATE]();
}

The effects of these kinds of manual optimizations are very dependent on the platform, the compiler, and the optimization settings.

You will most likely get a much greater performance gain by spending your time measuring and tuning the do_aquisition and do_tracking algorithms.


If you don't know when "FIRST" will be true, then no.

The issue is whether FIRST is time consuming or not; maybe you could evaluate FIRST before the loop (or part of it) and just test the boolean.


I'd change moonshadow's code a little bit to

while( some_condition )
{
   do_that;
   if( FIRST )
   {
     do_this; // overwrite what you did earlier.
   }
}


Based on your new information, I'd say something like the following:

while(some_condition)
{
  while(ACQUISITION_SUCCEEDED)
  {
    do_tracking();
  }
  if (some_condition)
    while(!ACQUISITION_SUCCEEDED)
    {
      do_acquisition();
    }
}

The point is that the ACQUISITION_SUCCEEDED state must include the some_condition information to a certain extent (i.e. it will break out of the inner loops if some_condition is false - hence there is a chance to break out of the outer loop)


This is a classic in optimization. You should avoid putting conditionals within loops if you can. This code:

while(...)
{
    if( a )
    {
       foo();
    }
    else
    {
       bar();
    }
}

is often better to rewrite as:

if( a )
{
    while(...)
    {
        foo();
    }
}
else
{
    while(...)
    {
        bar();
    }
}

It's not always possible though, and you should always when you try to optimize something measure the performance before and after.


There is not much more useful optimizing you can do with your example.

The call / branch to the do_this and do_that may negate any savings you earned by optimizing an if-then-else statement.

One of the rules of performance optimizing is to reduce branches. Most processors prefer to execute sequential code. They can take a chunk of sequential code and haul it into their caches. Branching interrupts this pleasantry and may cause a complete reload of the instruction cache (which loses valuable execution time).

Before you micro-optimize at this level, review your design to see if you can:

  1. Eliminate unnecessary branching.
  2. Split up code so it fits into the cache.
  3. Organize the data to reduce fetches from memory or hard drive.

I'm sure that the above steps will gain you more performance than optimizing your posted loop.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜