Inline functions in iteration

5

In several articles, I read that adding an inline function within a while (for) generates an unnecessary consumption of system resources.

Write:

#include <iostream>

inline int cubo(int n){
    return n*n*n;
}

int main(){
    for(int i = 0; i<40; i++){
        std::cout << cubo(3) << std::endl;
    }
    return 0;
}

It would not be the same as writing:

#include <iostream>

int main(){
    for(int i = 0; i<40; i++){
        std::cout << 3*3*3 << std::endl;
    }
    return 0;
}

Something like, the compiler will copy the function for each repetition, rather than doing the above.

    
asked by anonymous 30.07.2014 / 14:37

3 answers

6

The inline specifier has two very distinct uses. The first is to tell the compiler that this function will probably perform better if it is overwritten in the call. The second, and perhaps neglected, is to allow the function to be defined twice. I'll explain:

Suppose you have a matematica.hpp header with the function like this:

int cubo(int n) {
    return n*n*n;
}

Now create two different code files, one with the main function and another with another function. If both include their header, both will define a cube function. At the time of generating the final executable this will give problem because the linker will not know which one to use (even if they are identical). If you add inline to the definition this problem is gone. The linker merely assumes two functions inline with the same name are equal and uses one of the two without giving an error. That is, with inline you can define functions in headers. This is necessary because in order to perform optimization, the compiler needs to have the function definition in all files.

Now the interesting point: Compilers are smart. They will take the initiative to optimize the function with or without their hint of inline . Similarly, the compiler may choose not optimize if it concludes that the costs are greater than the benefits. For example, your code, whether with or without inline , produces the same result when compiled with -O2 (optimize speed, not aggressively). But if you leave, for example, the larger function (try adding a cout inside it) the compiler chooses not to apply the optimization to -O2 because of the increase in code size. But if you include the inline hint, it will do so by relying on you to have a good reason for wanting the inline.

But if the costs are huge (eg, inline of a 1000-line function within one that is less than 10), the compiler will most likely decline even with the hint. You can still force using the following:

int cubo(int n) __attribute__((always_inline)); // Isso é específico do GCC. Não funcionará
                                                // em qualquer outro compilador.

inline int cubo(int n) {
    return n*n*n;
}

Turning now to your specific question. Inline has two good sides and one bad side. The first is to remove the need for a function call. It may seem like a bit, but organizing the arguments and making the jump to a possibly distant code region will cost a few cycles. The second is that this allows more optimizations in the resulting code, such as reducing 3*3*3 to 27 and saving more. The disadvantage is the code increase. If a 5-line function is optimized in 10 places, there are 50 more lines of code. And this can cause a function or the body of a loop to not fit in the processor code cache, and force it to have to read memory in the middle of a critical execution.

Simply put: Use inline in any function defined in a header. Use inline in any function that is too small and trivial. Do not use inline anywhere else unless you know what you are doing and make sure it will be a benchmark.

    
12.08.2014 / 19:31
4

Compiling with g++ 4.8.1 , with the -O2 option, both of the above excerpts have exactly the same assembly code (with the exception of label names). Therefore, there is no difference and there is no unnecessary consumption of resources (at least in this scenario).

    
30.07.2014 / 15:38
0

When you use inline, the compiler chooses to copy the body of the function and replace it in the call instead of using the function itself.

As @Lucas Virgili commented, using the -02 option would cause the compiler to maximize program performance, so the codes result in the same program.

In case of a function to return the cube of a number, another option you have is to use #define.

    
12.08.2014 / 18:07