Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++ optimizing away checks to see if a function has already been run before

Let's say you have a function in C/C++, that behaves a certain way the first time it runs. And then, all other times it behaves another way (see below for example). After it runs the first time, the if statement becomes redundant and could be optimized away if speed is important. Is there any way to make this optimization?

bool val = true; 

void function1() {

   if (val == true) {
      // do something
      val = false; 
   }
   else {
      // do other stuff, val is never set to true again 
   }

}
like image 704
umps Avatar asked Oct 19 '12 21:10

umps


6 Answers

gcc has a builtin function that let you inform the implementation about branch prediction:

 __builtin_expect 

http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

For example in your case:

bool val = true; 

void function1()
{
    if (__builtin_expect(val, 0)) {
       // do something
       val = false; 
    }
    else {
      // do other stuff, val is never set to true again 
    }
}
like image 126
ouah Avatar answered Nov 12 '22 03:11

ouah


You should only make the change if you're certain that it truly is a bottleneck. With branch-prediction, the if statement is probably instant, since it's a very predictable pattern.

That said, you can use callbacks:

#include <iostream>
using namespace std;
typedef void (*FunPtr) (void);
FunPtr method;
void subsequentRun()
{
    std::cout << "subsequent call" << std::endl;
}
void firstRun()
{
    std::cout << "first run" << std::endl;
    method = subsequentRun;  
}
int main()
{
    method = firstRun;
    method();
    method();
    method();
}

produces the output:

first run
subsequent call
subsequent call

like image 20
Luchian Grigore Avatar answered Nov 12 '22 02:11

Luchian Grigore


You could use a function pointer but then it will require an indirect call in any case:

void (*yourFunction)(void) = &firstCall;

void firstCall() {
 ..
 yourFunction = &otherCalls;
}

void otherCalls() {
 ..
}

void main()
{
  yourFunction();
}
like image 31
Jack Avatar answered Nov 12 '22 03:11

Jack


One possible method is to compile two different versions of the function (this can be done from a single function in the source with templates), and use a function pointer or object to decide at runtime. However, the pointer overhead will likely outweigh any potential gains unless your function is really expensive.

like image 43
Antimony Avatar answered Nov 12 '22 02:11

Antimony


You could use a static member variable instead of a global variable..

Or, if the code you're running the first time changes something for all future uses (eg, opening a file?), you could use that change as a check to determine whether or not to run the code (ie, check if the file is open). This would save you the extra variable. Also, it might help with error checking - if for some reason the initial change is be unchanged by another operation (eg, the file is on removable media that is removed improperly), your check could try to re-do the change.

like image 4
Sveltely Avatar answered Nov 12 '22 03:11

Sveltely


A compiler can only optimize what is known at compile time.

In your case, the value of val is only known at runtime, so it can't be optimized.

The if test is very quick, you shouldn't worry about optimizing it.

like image 1
alestanis Avatar answered Nov 12 '22 02:11

alestanis