Simple answer : no. 'If' statements take a negligible amount of time on a modern, high-speed, pipelined processor. Whatever takes a long time in this work function, it is not the if statement (and you should benchmark / profile to find out what is taking the time - it's a much more productive approach than speculative optimisation).
Should I use a function pointer to select implementation in the constructor?
-
10-06-2023 - |
Вопрос
The function pointer tutorials contain an example of how to replace a switch statement by function pointers.
I have different algorithms which I would like to select in the constructor. My current implementation basically looks like this
// Constructor:
MyClass::MyClass(double *data)
: specialCase1(false), specialCase2(false), data_(data) {
if (checkData1(data)) specialCase1 = true;
else if (checkData2(data)) specialCase2 = true;
}
// Function:
double MyClass::work() {
if (specialCase1) return workSpecialCase1();
else if (specialCase2) return workSpecialCase2();
// ... do work ...
}
The work function is called a lot, therefore I am looking into ways to optimize. In principle I could add a function pointer member to the class 'double (*selectedWorkFunc)()' and then change the work function to
double MyClass::work() {
return selectedWorkFunc()
}
In general, can I expect a performance gain by using the function pointer to avoid the the if statements in the work function?
Решение
Другие советы
After studying this manual on c++ optimization, I would like to add some more infomation why the above idea will probably not work.
Since the bool value is selected on construction, the branch choosen will never change.
A branch instruction takes typically 0 - 2 clock cycles in the case that the microprocessor has made the right prediction. The time it takes to recover from a branch misprediction is approximately 12 - 25 clock cycles, depending on the processor. This is called the branch misprediction penalty.
Function pointer evaluation takes longer than that:
Calling a function through a function pointer typically takes a few clock cycles more than calling the function directly if the target address can be predicted.