zebediah49
zebediah49

Reputation: 7611

C constants defined at link time

I have a VERY performance-sensitive application, and am curious about if I can save some constants for linking. I have a number of global constants that I am using (simulation dimensions, for example), which are used an insane amount. I tried changing them from constants to variables, and the performance dropped dramatically. Thus, I have created a somewhat convoluted system which assigns constants from a configuration file, and builds an executable explicitly for the requested set of parameters. Thus, I would like to minimize how much stuff I rebuild for each parameter change.

The question is if I can pre-compile some of my objects, and put the values in at link time. The most likely implementation I can think of for this would be to include those constants as const arguments to the function that needs them, and hope that the compiler/linker optimization results in the same performance as having hardcoded them as #define constants. Any suggestions about how to make this work?

(You know how people say things like "but this doesn't matter unless you're doing this billions of times in scientific computing on a cluster"? -- I'm the guy doing it billions of times in scientific computing on a cluster. Yes, I also will benchmark anything before fully implementing it.)

Upvotes: 5

Views: 1510

Answers (3)

Christoph
Christoph

Reputation: 169563

Assuming gcc, you could declare the constants with external linkage, put them into their own source file and compile and link with link-time optimizations.

In case of clang, I recommend a similar approach, but instead of using regular LTO, compile to bitcode using -emit-llvm -c and only compile to native code as a last step when linking.

Also, you could leave your code as-is (ie using preprocessor definitions) and trust in ccache to avoid unnecessary recompilation.

Upvotes: 4

Jens Gustedt
Jens Gustedt

Reputation: 78903

You'd have to analyse why you have the slowdown with variables, probably best by looking into the assembler that is produced, usually this is with option -S to the compiler.

There may be a lot of reasons for the speedup if you have constants:

  • small integer constants can go to immediates of assembly operations
  • The compiler can do loop unrolling
  • there can be special arithmetic tricks if the constant is a power of 2

You can get slowdown on the other hand if you only passing pointer to const to your function and the compiler can't exclude that your const qualified object is aliased. const only says that you don't have the right to change the value but the compiler can't know if it changes unexpectedly. Here declaring the pointer with restrict might help.

So identify the trouble spots, compare them in assembler with two different versions (constants and const qualified variables) and try to find the reason for the slowdown.

Use inline to get the trouble spots neatly optimized in place.

If nothing else helps, and if you happen to localize it nicely you might even consider to write a script producing that function with literal constants and compile that little piece of code before every run. If your runs are long, there may well be a pay off for short compilation and relinking.

Upvotes: 3

blueshift
blueshift

Reputation: 6882

You can, but it's not really going to help you. The gains you get from recompiling with different constants are because the compiler knows the values at compile-time and can optimise based on that. If you build an object and link it with constant data later, that's the same as using variables and you'll suffer the performance hit.

Sounds like an interesting problem, there aren't many opportunities for real hairy-chested man's optimisation these days :)

Upvotes: 2

Related Questions