Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.)

like image 736
zebediah49 Avatar asked Jan 17 '23 04:01

zebediah49


2 Answers

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.

like image 129
Christoph Avatar answered Jan 30 '23 06:01

Christoph


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.

like image 39
Jens Gustedt Avatar answered Jan 30 '23 07:01

Jens Gustedt