Page 1 of 1

GNU C modules compiled separately = 37% reduction in speed

PostPosted: 27 Sep 2006, 17:53
by smcracraft
Hi,

I recently separated out my program into 5 modules
(instead of 1) and plan for more modules.

I noticed the speed of the program on its current
standard benchmark dropped 37% as a result.

When I combine all the code into one module, eliminate
all but a main include at the top, and recompile,
I get 37% faster than the modularized form.

My question is, does anyone know why this happens?

Stuart

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 27 Sep 2006, 18:55
by Dann Corbit
Because GCC's optimizer had a pre-frontal lobotomy.

Other compilers do not suffer this defect.

One way around it (if you are determined to use GCC) is to have two separate projects for your program.

One project is nicely modularized (for debugging, etc.) and the other one does this:

/* file: cheesy_hack.c contains the following: */
#ifdef _MSC_VER
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <more_include_files_go_here.h>
#include <etc.h>

#include "file1.c"
#include "file2.c"
#include "....c"
#include "filen.c"

and compile that when you want a speed build.

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 27 Sep 2006, 19:10
by smcracraft
Dann Corbit wrote:Because GCC's optimizer had a pre-frontal lobotomy.

Other compilers do not suffer this defect.

One way around it (if you are determined to use GCC) is to have two separate projects for your program.

One project is nicely modularized (for debugging, etc.) and the other one does this:

/* file: cheesy_hack.c contains the following: */
#ifdef _MSC_VER
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <more_include_files_go_here.h>
#include <etc.h>

#include "file1.c"
#include "file2.c"
#include "....c"
#include "filen.c"

and compile that when you want a speed build.


Thanks.

Here's another. This is a label in my makefile which makes
an alternate version of the program from all the C files
strung together with the main header file removed.

As to whether this is an optimal implementation, I don't
know.

At least it preserves my ability to use modules for
debugging and monolithic for performance but not
have to leave GNU C.

Microsoft clearly makes great compilers, no question about it.

Code: Select all
massive.exe: *.c *.h
        rm -f massive1 massive2 massive3 massive.c
        cat *.c > massive3
        egrep -v '#include "main.h"' massive3 > massive2
        echo '#include "main.h"' > massive1
        cat massive1 massive2 > massive.c
        gcc -O2 -DNDEBUG massive.c -o massive.exe


I remember seeing something like this in Crafty's
Makefile many years ago.

Stuart

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 27 Sep 2006, 20:23
by Tord Romstad
Dann Corbit wrote:Because GCC's optimizer had a pre-frontal lobotomy.


It is true that a problem with GCC is that it cannot inline function calls to a function defined in a different source code file, but I find it hard to believe that this alone can reduce the speed by as much as 37%. Are there any other problems with GCC which can harm the speed when using multiple source files?

Other compilers do not suffer this defect.

One way around it (if you are determined to use GCC) is to have two separate projects for your program.

One project is nicely modularized (for debugging, etc.) and the other one does this:

Code: Select all
/* file: cheesy_hack.c contains the following: */
#ifdef _MSC_VER
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <more_include_files_go_here.h>
#include <etc.h>

#include "file1.c"
#include "file2.c"
#include "....c"
#include "filen.c"


and compile that when you want a speed build.


Unfortunately, this won't always work. I like to declare "file-global" variables and functions by using the 'static' keyword. I may have a 'static float Foo = 3.5' in file1.c, and a 'static int Foo = 142857' in file2.c. This will cause an error when attempting to compile the project with the technique you describe.

Tord

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 27 Sep 2006, 22:42
by Dann Corbit
There are other problems as well.

If your header files are not idempotent, you will get rafts of error messages.

If one C file already #includes another C file, then you cannot blindly execute the technique.

It is not just the inlining that improves with GCC. It also is able to rearrange functions so that locality of reference is better (short jumps instead of long jumps most of the time).

It can also make better decisions about what to inline and what not to inline if it can see every function and how it is used.

Maybe it's somewhat better with GCC 4.x -- I have not done any experiments lately.

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 27 Sep 2006, 23:03
by smcracraft
Hi - my report is based on GCC 4.1.0.

It's a good toy compiler but not for serious stuff in my opinion
unless you want the freebie method.

(I had a better opinion of it before 24 hours ago.)

:-)

Stuart

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 28 Sep 2006, 02:26
by bob
couple of points:

(1) carelessly inlining can hurt program performance by crushing the cache. Inlining has to be done carefully.

(2) the way the source files appear can make a big difference. Lots of small procedures scattered all over are worse than lots of small procedures ordered so that if a calls b, then b is close to a in the source...

There are other issues as well.

I have a simple approach to use both..
objects = crafty.o

or

objects = search.o attacks.o etc...

the file crafty.c #includes the source files into one giant source, but with reasonable ordering as above. I uncomment that when using decent compilers. If the compiler (say a bad version of gcc) looks slow, I will use the individual object files which compiles everything separately to avoid indiscriminant inlining issues.

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 28 Sep 2006, 19:18
by Tord Romstad
smcracraft wrote:Hi - my report is based on GCC 4.1.0.

It's a good toy compiler but not for serious stuff in my opinion
unless you want the freebie method.


GCC is getting a too bad rap in this thread. In my opinion, it's an amazing piece of software. Remember that it supports lots of different platforms, and compiles several different languages (at least C++, Objective-C, Java, Ada and Fortran). Despite this, it manages to be almost competitive with commercial C++ compilers which generate code only for x86 processors. I think this is a fantastic achievement for a free software project.

Tord

Re: GNU C modules compiled separately = 37% reduction in spe

PostPosted: 28 Sep 2006, 21:08
by mridul
Tord Romstad wrote:
smcracraft wrote:Hi - my report is based on GCC 4.1.0.

It's a good toy compiler but not for serious stuff in my opinion
unless you want the freebie method.


GCC is getting a too bad rap in this thread. In my opinion, it's an amazing piece of software. Remember that it supports lots of different platforms, and compiles several different languages (at least C++, Objective-C, Java, Ada and Fortran). Despite this, it manages to be almost competitive with commercial C++ compilers which generate code only for x86 processors. I think this is a fantastic achievement for a free software project.

Tord


The point is not if it is a monumental piece of software - it might be.
The point is , it is slow and does not do a great job on most platforms it supports - supporting multiple platforms at the cost of not doing a good job of its basic requirements of optimisation is not something to be proud about :wink:
It should be competitive in its basic functionality ... the number of platforms supported , and other things like this are 'gravy' : useful no doubt but not critical.

There are a large number of pretty dodgey set of optimisations in gcc - which might speed up an unoptimum piece of code , not something which has been written with performance also as a criterion like chess engines are.


Mridul