What can I assume about optimizing the C / C ++ compiler?

I would like to know how to avoid wasting time and risk typos by re-hashing the source code when I integrate legacy code, library code or sample code into my own codebase.

If I give a simple example based on an image processing script, you can see what I mean.

Actually, it’s not unusual for me to integrate a piece of code as follows:

for (unsigned int y = 0; y < uHeight; y++) { for (unsigned int x = 0; x < uWidth; x++) { // do something with this pixel .... uPixel = pPixels[y * uStride + x]; } } 

Over time, I got used to doing things like transferring unnecessary calculations from the inner loop and possibly changing postfix increments to prefix ...

 for (unsigned int y = 0; y < uHeight; ++y) { unsigned int uRowOffset = y * uStride; for (unsigned int x = 0; x < uWidth; ++x) { // do something with this pixel .... uPixel = pPixels[uRowOffset + x]; } } 

Or, I could use pointer arithmetic, either by line ...

 for (unsigned int y = 0; y < uHeight; ++y) { unsigned char *pRow = pPixels + (y * uStride); for (unsigned int x = 0; x < uWidth; ++x) { // do something with this pixel .... uPixel = pRow[x]; } } 

... or row and column ... so I get something like this

 unsigned char *pRow = pPixels; for (unsigned int y = 0; y < uHeight; ++y) { unsigned char *pPixel = pRow; for (unsigned int x = 0; x < uWidth; ++x) { // do something with this pixel .... uPixel = *pPixel++; } // next row pRow += uStride; } 

Now, when I write from scratch, I will usually apply my own “optimizations”, but I know that the compiler will also do things like:

  • Moving code from inner loops to outer loops
  • Change postfix increment to prefix
  • Many other things that I have no idea about

Considering that every time I communicate with a piece of working, tested code in this way, I not only cost myself time, but also risked introducing errors with the finger problem or something else (the examples are simplified above). I know about “premature optimization”, as well as other ways to improve performance by developing better algorithms, etc., But for the situations described above, I create building blocks that will be used in larger applications with pipeline types, t predict which may be non-functional requirements, so I just want the code to be fast and tough, as far as reasonable within the time limit (I mean the time spent setting up the code).

So my question is: where can I find out which compiler optimizers are usually supported by "modern" compilers. I use a mixture of Visual Studio 2008 and 2012, but it would be interesting to know if there are differences with alternatives, for example. Intel C / C ++ Compiler. Can someone shed some insight and / or point me to a useful Internet link, book or other link?

EDIT
To clarify my question

  • The optimizations shown above were simple examples, not a complete list. I know that it is pointless (in terms of performance) to make those specific changes, because the compiler will do it anyway.
  • I am specifically looking for information about which optimizations are provided by the compilers that I use.
+8
c ++ compiler-optimization visual-c ++
source share
3 answers

I would expect that most of the optimizations you include as examples are a waste of time. A good optimizing compiler should be able to do all this for you.

I can offer three suggestions with practical advice:

  • Profile your code in the context of real processing of real data. If you can't, come up with some synthetic tests that you think will accurately mimic the final system.
  • Optimize the code you demonstrated through profiling to be a bottleneck.
  • If you are sure that part of the code needs optimization, do not just assume that expressing the invariant factoring outside the loop will improve performance. Always check, if desired, looking at the generated assembly for more information.

The above recommendations apply to any optimization. However, the last point is especially important for low-level optimizations. This is a bit of a black art, because it involves a lot of important architectural details: the memory hierarchy and bandwidth, pipelining instruction , branch prediction , the use of SIMD , etc.

I think it's better to rely on the author of the compiler, who knows the target architecture well, than trying to outsmart them.

From time to time, you will find through profiling that you need to optimize things manually. However, these cases will be quite rare, which will allow you to spend a lot of energy on what will actually matter.

In the meantime, focus on writing the right and supported code.

+16
source share

What can I assume about optimizing the C / C ++ compiler?

As far as possible, as you can imagine , unless you are experiencing functionality or performance issues with optimized code, turn off optimization and debugging.

Mordern compilers have various strategies for optimizing your code, especially if you are doing parallel programming using libraries such as OMP , Boost, or TBB .

If you DO care about what your code exactly entered into machine code, it would not be better to decompile it and watch the builds.

The most important thing for you to do manual optimization would be to reduce unpredictable branches, which is more difficult for the compiler to do.

If you want to find information about optimization, then there is already a question about SO

  • What are the methods for optimizing a C ++ compiler in Visual Studio

There are explanations in the optimization parameters that each optimizes for:

And something about optimization strategies and techniques

0
source share

I think it would probably be more useful for you to reconsider the premise of your question, rather than get a direct answer.

Why do you want to perform these optimizations? Judging by your question, I assume that this is to make a specific program faster. If so, you need to start with the question: how to speed up this program?

This question has a completely different answer. First, you need to consider Amdahl Law . This usually means that it makes sense to optimize one or two important parts of the program. Everything else is pretty much irrelevant. You must use the profiler to search for these parts of the program. At this point, you can claim that you already know that you must use a profiler. However, almost all the programmers I know do not review their code, even if they know what they need. Knowing about vegetables is not the same as eating them. ;-)

Once you place the hot spots, the solution will likely include:

  • Improving the algorithm, so the code does less work.
  • Improved memory access patterns to improve cache performance.

Again, you should use a profiler to see if your changes have improved runtime.

You can use code optimization and similar terms for more information.

If you want to become truly serious, you should also take a look at Agner Fog and Computer Architecture Optimization Guides : A Quantitative Approach . Remember to get the latest edition.

You might also want to read The Sad Tragedy of the Micro-Optimization Theater .

0
source share

All Articles