It's said that compiling GNU tools and Linux kernel with -O3
gcc optimization option will produce weird and funky bugs. Is it true? Has anyone tried it or is it just a hoax?
8 Answers
-O3
has several disadvantages:
- First of all it often produces slower code than
-O2
or-Os
. Sometimes it produces longer code due to loop unrolling which may be in fact slower due to worse cache performance of code. - As it was said it sometimes produces wrong code. It may be either due to error in optimalization or error in code (like ignoring strict aliasing). As kernel code sometimes is and sometimes have to be 'smart' I'd say it is possible that some kernel developer made some error. I experienced various strange problems, like crashing of userspace utilities, when I compiled kernel with gcc 4.5 which at that point was stable. I still use gcc 4.4 for kernel and several selected userspace utilities due to various bugs. The same may apply for
-O3
. - I don't think it offers much benefit for the Linux kernel. The kernel does not do heavy computations and in places it does, it is optimized with assembly.
-O3
flag will not change the cost of context switching or speed of I/O. I don't think something like <0.1% speedup of overall performance is worth it.
-
7Linux is compiled with -fno-strict-aliasing since Linus thinks gcc is being stupid and overly restrictive since it does stupid things like treat values as different even though they blatantly obviously are not (ie the aliasing was introduced inside one function and the compiler can see it). see mail-archive.com/[email protected]/msg01647.html– Spudd86Commented Oct 31, 2010 at 16:56
-
@Spudd86: Did he mean that they are obviously not for human being reading code or for compiler? As I said - Kernel sometimes need to do smart things that userspace programs should not do. What makes sense for userspace (heavy optimization in some areas) may make no sense for kernel (larger amount of smart code + bottleneck in different places). Commented Oct 31, 2010 at 17:14
-
1
-
2@Spudd86: I disagree with it then. Making compiler 'smart enough' to spot such 'obvious' things is not trivial. So the only possible way is a) produce only slow(er) code (which is unacceptable for some use cases in, say, HPC) and/or force programmers to manually optimize the code b) make the rules stricter to allow 'dumber' compiler to make optimalization - route taken by C standard. Commented Jul 24, 2013 at 22:07
-
Yeah..... phoronix.com/review/linux-os-amd-ryzen9-9950x Intel Continues To Show AMD The Importance Of Software Optimizations: 16% More Ryzen 9 9950X Performance - So much for the conjecture that it doesn't matter. Commented Aug 20 at 19:29
Over the last 10 years I've been running multiple Gentoo systems with 1000+ packages using -O3 -march=native
globally and have yet to run into any of these mythical stability issues that -O3
is supposed to have. Benchmarks of CPU intensive applications (like math/science apps) consistently show -O3
to produce faster code, after all it would be pointless if it didn't. For a majority of desktop apps CFLAGS
don't matter much as much anyway since they are IO bound, but it matters a lot for server side stuff that is CPU bound.
It's used in Gentoo, and I didn't notice anything unusual.
-
10However please note that -O3 is often filtered out by ebuilds. Commented Sep 5, 2010 at 12:19
Note that large chunks of the toolchain (glibc in particular) flat out don't compile if you change optimization levels. The build system is setup to ignore your -O preferences for these sections on most sane distros.
Simply put, certain fundamental library and OS features depend on the code actually doing what it says, not what would be faster in many cases. -fgcse-after-reload in particular (enabled by -O3) can cause odd issues.
-O3 uses some aggressive optimisations that are only safe if certain assumptions about register use, how stack frames are interacted with, and function reentrancy are true, and these assumptions are not guaranteed to be true in some code like the kernel especially when inline assembly is used (as it is in some very low level parts of the kernel and its driver modules).
-
Not to mention it's not always faster, you have to actually come up with benchmarks and test it vs
-O2
to know weather or not it hurts or helps– Spudd86Commented Oct 31, 2010 at 16:58
Yeah, this an old thread, but actually, no one have answered the question, that is: "does it (the -O3 option) really produce bugs in real application?, does it ever occurred?"
Of course I'm relying on my own experience, because there's simply no other way. I'm referring to gcc starting from version 4.4 here.
There are 2 existing "myths" about the O3 level in gcc, but what is really strange, those myths can be found even in official statements published by really big software companies (I'm not going to list them here, for obvious reasons).
Myth#1: O3 produces bigger code, so it can't fit the cache memory, and therefore it will in fact run slower -> actually it's the O2 which generates bigger executable code without any significant benefits -> it is usually slower than O1 - but O3 is always faster, typically +20% or more, mainly thanks to vectorization.
Myth#2: O3 breaks the resulting executable code: Not really a myth: the O3 can break the code which is not written in the "O3" in mind. Or in other words: the O3 will damage programs which were never meant to be optimized by the gcc at the O3 level. This normally should have a lengthy explanation, but I'll try to make it as short as possible:
O3 is ALLWAYS generating correct code, but the problem is that the optimized code is faster - this WILL break programs with unresolved / never tested logic race conditions (especially multi-threaded applications, linux kernel is a perfect candidate for a victim in this case)
O2/O3 optimization levels have the "clever" functionality for eliminating "apparently" dead code ("apparently" never executed OR the code provides results which are "apparently" never used) - this can cause astonishing crashes in programs which otherwise run flawlessly with O1 optimization level.
"does it really produce bugs in real application(s)?"
Yes, it does: I had to add function attribute: attribute((optimize("O1"))) in some cases, to prevent "dumb" removal of the nested calls, while using the O3 optimization level in gcc.
Regards
-
I agree with you that the question has not been answered. I believe one problem is that we would need a CONSISTENT, THOROUGH and RELIABLE table of benchmarks, where we can compare the real effects of -O2 versus -O3, on real, existing hardware. Most people seem to just refer to the "known myth/facts" and nobody wants to tackle on doing the hard work of reproducible, thorough benchmarks (me neither but my excuse is that I am lazy and not competent to come to good conclusions anyway; I am not a professional software developer after all).– shevyCommented Jun 13, 2020 at 19:15
-
I (and I think most people) would argue that "programs with unresolved / never tested logic race conditions" were already broken to start with; and if compiling with -O3 makes the resulting faults easier to detect and/or reproduce, that's generally a good thing, as bugs that are easier to reproduce are easier to analyze and then fix. Commented Jun 23, 2022 at 15:37
-
@shevy: Here someone has benchmarked a
-O3
vs. a-O2
kernel. Geometric mean: +1.3% in performance. Stress-NG context switching had +270% in performance, some around +5% .. +11%, while most around 2%..3% and two cases had performance loss. (I just read from the table presented there, I did not verify the calculations by myself.) Commented Mar 10 at 20:12 -
@JeremyFriesner My C program hit a random segfault in stress testing. The segfault can be triggered once in hundreds of running, so the RELIABILITY testing is very time-consuming and the problem is hard to catch. I still not find the rootcause, and it seemed to be vanish when the program is built with
-O2
.– wangt13Commented Jul 11 at 0:47 -
@wangt13 you might want to run your program under
valgrind
orhelgrind
or Clang Static Analyzer or Clang'sAddress Sanitizer
orThread Sanitizer
orUndefined Behavior Sanitizer
or similar, and take seriously any warnings they generate. These tools can often point out problems that would otherwise be very difficult to detect, reproduce, or analyze. Commented Jul 11 at 1:29
While you can get away with using -O3 and other optimizations knobs on most applications (and it can result in speed improvements), I would hesitate to use such tweaks the kernel itself or on the tool chain required for building it (compiler, binutils, etc.).
Think about it: Is a 5% performance gain of the raid and ext3 subsystems worth system crashes or potential data loss and/or corruption?
Tweak all the knobs to want for that Quake port you're playing or the audio/video codecs you use for ripping your DVD collection to divx files. You'll likely see an improvement. Just don't mess w/ the kernel unless you have time to waste and data you can bear to lose.
-
5I'am not asking if it is worth or not, safe or not, or why we shouldn't do this, what I'am asking is the fact, does it really produce bugs in real application?, does it ever occurred?, does it proved so..– urayCommented Sep 5, 2010 at 1:16
-
The question is not about a "x% gain" is worth it. The question is IF there is such a gain to begin with anywhere. you also imply that this results in data loss and corruption. Have you actual proof or is this another urban legend?– shevyCommented Jun 13, 2020 at 19:16
I provided my experience here for reference.
I am using GCC7.2.0 in my project, there is a thirdparty SDK (multi-threading) built with -O2
, a C program (multi-threading) is built with -O3
by default and linked to SDK.
With stress testing, I found the C program hit Segmentation Fault
in 1 of hundreds of running. The core dump pointed to one function in SDK.
I re-ran the stress testing for many times, and can hit the Segmentation Fault
always, and got the same core dump.
Then, I built the C program with -O2
and linked to the SDK. With thousands of running, there is NO fault found.
I just posted my own question asking for the confirmation that if -O3
can really generate bug for mutli-threading user space applications.
Based on the comments and answers in this question, I think the answer should be Yes
.
-O0
is not supported at all! stackoverflow.com/questions/29151235/…