Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding conditionals and function invocations inside a loop

Tags:

c++

I have a code that looks like this:

void function(int parameter)
{
  for( ... ) // a big loop
  {
    double a = ...;
    for( ... ) // a big loop
    {
      double b = ...;

      double value;
      if(parameter == 1)
        value = some_math_expression_1(a, b);
      else if(parameter == 2)
        value = some_math_expression_2(a, b);
      ...
    }
  }
}

The idea is that depending on the parameter I want to apply some math expression to a and b. This function is executed many times and must be fast, and I wonder if those conditional branches at each iteration can introduce an overhead that I could save.

Right now, I have written the code like this:

void function(int parameter)
{
  if(parameter == 1)
    function1();
  else if(parameter == 2)
    function2();
  else
    ...
}

So that I can apply the math expression directly if I repeat the code in every functionX(). The obvious problem is that when I want to change some piece of code I have to do it several times (I have around 10 math expressions now).

What approach could I use to avoid any overhead in function?

What if I pass a pointer to functions some_math_expression_X to function (I would change the conditionals for function invocations)?

What if I code the whole function as a macro (uf) and set the math expression as a parameter?

What if I use a template and pass the math expression as a pointer to an inline function (is this even possible)?

EDIT: Thank you for your answers. I know I can use the methods you are proposing (pointers to / array of functions, or relying on the branch predictor). However, do you have some insight about what would be better in terms of avoiding overhead? The math expressions are quite simple (something like a*b), and in addition to the loops that are long, function is also called many times (do branch predictions "survive" between calls?).

like image 972
ChronoTrigger Avatar asked Jul 12 '13 10:07

ChronoTrigger


3 Answers

You can convert the function into a template:

void functionT<int PARAMETER>()
{
  for( ... ) // a big loop
  {
    double a = ...;
    for( ... ) // a big loop
    {
      double b = ...;

      double value;
      if(PARAMETER == 1) //Constant condition!!!
        value = some_math_expression_1(a, b);
      else if(PARAMETER == 2)  //Constant condition!!!
        value = some_math_expression_2(a, b);
      ...
    }
  }
}

Since the conditions are always true or always false, the compiler will optimize the condition tree away and leave only the real math expression. No branches and no function calls!

Now, you can use it only with constant parameters:

functionT<1>();

But not with variables:

int x = 1;
functionT<x>(); //Error

If you need that, you can make a wrapper:

void function(int parameter)
{
    switch (parameter)
    {
        case 1: functionT<1>(); break;
        case 2: functionT<2>(); break;
    }
}
like image 102
rodrigo Avatar answered Nov 02 '22 23:11

rodrigo


Don't worry. Modern CPU's have branch predictors, and they will correctly predict the branch taken.

like image 37
MSalters Avatar answered Nov 03 '22 01:11

MSalters


You could set up a constant array of function pointers, and call the function associated with parameter.

But if the math expressions are rather small, a switch() statement could be even faster.

switch (parameter) {
    case 1:
        value = math expression 1;
        break;
    case 2:
        ...
}
like image 32
Ingo Avatar answered Nov 03 '22 00:11

Ingo