Question

Trying to optimize the fun_a1() function. The variable j does not change in the scope of fun_a1(). So, checking j==1 or 2 or 3 for each 'i' iteration is obviously a waste of CPU cycles. But if I try to bring the condition evaluation outside the loop, I have to write redundant loops for each condition. In C, I can solve this easily by using a function pointer. However, C++ will not allow pointers to non-static functions. I found a few links describing the mysterious "pointer-to-member". (example 1, example 2) But it's still not clear how do I use it from inside the object itself e.g from inside fun_a()? Or can it be optimized in any other ways?

class A{
    void fun_b(int i);

    void fun_c(int i);

    void fun_d(int i);

    void fun_f(int i);

    void fun_a1(int j){

        for(int i=0; i<1000; i++){

                 if(j==1) fun_b(i);
            else if(j==2) fun_c(i);
            else if(j==3) fun_d(i);

            fun_f(i);           
        }

    }


    void fun_a2(int j){

        if(j==1){           
            for(int i=0; i<1000; i++) { 
                fun_b(i); 
                fun_f(i); 
            }
        }
        else if(j==2){          
            for(int i=0; i<1000; i++) { 
                fun_c(i);
                fun_f(i);
            }            
        }
        else if(j==3){
            for(int i=0; i<1000; i++) { 
                fun_d(i);           
                fun_f(i);
            }           
        }       
    }   
};
Was it helpful?

Solution 2

Using function pointers, if the compiler doesn't remove them, is a serious performance hit.

A raw if on an unchanged local variable will be probably optimized out of the loop: that isn't a very fancy optimization.

However, if you want to make this explicit, the answer isn't function or method pointers. It is lambdas and functors.

template<typename Functor>
void fun_a2_internal(Functor f) {
  for(int i = 0; i < 1000; ++i) {
    f(i);
  }
}

void fun_a2(int j) {
  if (j==1)
    fun_a2_internal([&](int i){ fun_b(i); fun_f(i); });
  else if (j==2)
    fun_a2_internal([&](int i){ fun_c(i); fun_f(i); });
  else if (j==3)
    fun_a2_internal([&](int i){ fun_d(i); fun_f(i); });
}

here we write a fun_a2_internal whose job it is to do a loop, and do some task in the loop.

Our fun_a2 passes that task in as a functor via a lambda.

This has the effect that the compiler gets to know the details of the body of the loop when compiling the loop, because the functor's operator() is a non-virtual one, and thus the same for every instance.

In general, if your answer to an optimization problem is "use function pointers" (or member pointers), you have the wrong answer.

This technique is why C++'s std::sort is faster than C's qsort.

OTHER TIPS

Here's how you'd use a pointer to member function:

void (A::*fun)(int);
if(j == 1) fun = &A::fun_b;
else if(j == 2) fun = &A::fun_c;
else if(j == 3) fun = &A::fun_d;

for(int i=0; i<1000; i++) {
    (this->*fun)(i);
    fun_f(i);
}

"optimize" is vague and should never be asked unless

  • 1, there is a particular problem being asked by, say professor based on concepts of efficiency covered

  • 2, there is a particular optimization to be done.

What you are asking is to optimize this "switch" statement

Yes, switch statement is more clean for this situation, but the more efficient way to do this is to make an array of function pointers to void functions containing these loops, then do

doFunction[j]();

for example

typedef void (*myfunc)(void);

myfunc options[10];

main()
{
    options[0] = (void*)loop1;
    options[1] = (void*)loop2;
    options[2] = (void*)loop3;
    options[3] = (void*)loop4;  
}

PS: i++ is slower than ++i unless optimized by compiler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top