Compiler behavior : Inlining external functions

R

Raphael

Hello,
I have 2 files
A.c : Defining a bunch of usefull functions
B.c : Defining a main that uses these ones.

I need to improve perfs :

I know that, if the caller and the functions called were in
the same file, the compiler would automatically inline them if
possible.

The question is : Is it possible to force the compiler, or to use it
in a way to make it inline my functions, even for different source files.
(I'm using GCC 3.2)

I know i could make big macros of my functions, or
gather all in the same file, but I would like to keep my source clean.

Thanks.

Raphael
 
L

Lawrence Kirby

Hello,
I have 2 files
A.c : Defining a bunch of usefull functions
B.c : Defining a main that uses these ones.

I need to improve perfs :

I know that, if the caller and the functions called were in
the same file, the compiler would automatically inline them if
possible.

Not if possible, hopefully it will perform some checks to determine
whether inlining would be a benefit. The fact is that if you have
peformance issues inlining is very rarely the solution. It can help in
specific cases where you have a very small function called a very large
number of times. Inlining can sle make code SLOWER because it can make
executable code a lot larger and reduce the opportunity for caching. It
also in effect combines smaller functions into one larger one and larger
functions tend to be more difficult to optimise.
The question is : Is it possible to force the compiler, or to use it
in a way to make it inline my functions, even for different source files.
(I'm using GCC 3.2)

That would be a good question for gnu.gcc.help. However fist consifer
whether inlining is really going to help.
I know i could make big macros of my functions, or gather all in the
same file, but I would like to keep my source clean.

From a C99 perspective you could define (i.e. include the function
body) your functions as inline (maybe static inline) in a header and
include that header in source files that use the functions.

Lawrence
 
J

jacob navia

Raphael said:
Hello,
I have 2 files
A.c : Defining a bunch of usefull functions
B.c : Defining a main that uses these ones.

I need to improve perfs :

I know that, if the caller and the functions called were in
the same file, the compiler would automatically inline them if
possible.

The question is : Is it possible to force the compiler, or to use it
in a way to make it inline my functions, even for different source files.
(I'm using GCC 3.2)

I know i could make big macros of my functions, or
gather all in the same file, but I would like to keep my source clean.

Thanks.

Raphael

As Mr Kirby replied, why do you think inlinening will be of
any use???

Did you *MEASURE* where the problem is?

I would recommend you using a profiler to seee where the problems are
and then optimize the functions you *know* are critical. Gcc comes with
a profiler utility (gprof, if I remember correctly). Use it
before mebarking in the wrong direction.

Just blindly inlining will make your code slower.

jacob
 
A

Adam Warner

Hi Raphael,
The question is : Is it possible to force the compiler, or to use it
in a way to make it inline my functions, even for different source files.
(I'm using GCC 3.2)

I hope you discover a solution. Since you raised the issue I've tried a
number of flag combinations without apparent success:
<http://gcc.gnu.org/onlinedocs/gcc/Inline.html>

Non-inlining can result in significant performance penalties. In my case
I've discovered that my read_tsc() function is not being inlined across
source files. It's the ultimate example of a function that should be
inlined:

/* Read the TimeStamp Counter */
inline uint64_t read_tsc(void) {
uint64_t r;
__asm__("rdtsc" : "=A" (r));
return r;

....
8048d59: e8 12 05 00 00 call 8049270 <read_tsc>
....
80490e1: e8 8a 01 00 00 call 8049270 <read_tsc>
....

08049270 <read_tsc>:
8049270: 55 push %ebp
8049271: 0f 31 rdtsc
8049273: 89 e5 mov %esp,%ebp
8049275: c9 leave
8049276: c3 ret

As per Lawrence Kirby's suggestion I'll ask gnu.gcc.help about this on
your behalf. The followup has been set to gnu.gcc.help since this is
largely an implementation-specific question.
I know i could make big macros of my functions, or gather all in the
same file, but I would like to keep my source clean.

Likewise. I've been building lots of helper functions content in the
knowledge that the function calling overhead can be compiled away.

When I put the read_tsc() function definition in the same source file as
the function calls to read_tsc() the execution time of my test program
drops from 5.872s to 5.654s.

Regards,
Adam
 
K

Keith Thompson

Lawrence Kirby said:
Inlining can sle make code SLOWER because it can make executable
code a lot larger and reduce the opportunity for caching. It also in
effect combines smaller functions into one larger one and larger
functions tend to be more difficult to optimise.

Larger functions are more difficult to optimize in the sense that the
optimizer has to spend more time and other resources on them (and the
increase can be much more than linear relative to the size of the
function). But combining more code into a single function can also
provide more opportunities for optimization -- and the end result
might actually be a smaller function with better cache behavior.

For example, given a function like:

void func(int n)
{
if (n >= 0) {
do_something(n);
}
else {
do_something_else(n);
}
}

there's not a lot that can be done to optimize it -- but if its
inlined from a call like

func(42);

or even

func(some_unsigned_int_object);

the optimizer can reduce the call to

do_something(n);

This is, of course, an artificial example designed to support my point.

Finally, the first law of program optimization still applies:

Don't do it.

The second law, for advanced programmers only, is:

Don't do it yet.

(I didn't originate these; I'm not sure who did.)
 
L

Lawrence Kirby

Larger functions are more difficult to optimize in the sense that the
optimizer has to spend more time and other resources on them (and the
increase can be much more than linear relative to the size of the
function).

Compilation time is something else. I'm thinking more along the lines of
code generated, e.g. the problem of register allocation is more difficult
and the result from larger code may be less optimal.
But combining more code into a single function can also
provide more opportunities for optimization -- and the end result
might actually be a smaller function with better cache behavior.

That is certainly possible, although if the inlined function is called in
a number of places the code size is likely to go up (unless it is very
small like an accessor function).
For example, given a function like:

void func(int n)
{
if (n >= 0) {
do_something(n);
}
else {
do_something_else(n);
}
}
}
there's not a lot that can be done to optimize it -- but if its inlined
from a call like

func(42);

or even

func(some_unsigned_int_object);

the optimizer can reduce the call to

do_something(n);

This is, of course, an artificial example designed to support my point.

I fully accept that inlining can result in performance gains and even
smaller executables in some cases, and is a useful feature. I'm just
pointing out that it can easily make things worse, and you need very
specific conditions to get significant gains.
Finally, the first law of program optimization still applies:

Don't do it.

The second law, for advanced programmers only, is:

Don't do it yet.

(I didn't originate these; I'm not sure who did.)

That is certainly true for micro-optimisations. Giving consideration to
performance issues early on in the selection and design of datastructures
and algorithms is important.

Lawrence
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,159
Messages
2,570,883
Members
47,416
Latest member
ReeceDorri

Latest Threads

Top