4 ms·
Looking at the github it seems you benchmark GCC 4.8.1 vs. go 1.2rc1. Numbers for Go look promising if one considers that Google's Go implementation does not ev
by copx 13y ago
Looking at the github it seems you benchmark GCC 4.8.1 vs. go 1.2rc1. Numbers for Go look promising if one considers that Google's Go implementation does not even have an advanced optimizer yet (in contrast to GCC).
>c++ -std=c++11 -O3 -Wall -pthread -ffast-math -mtune=native -march=native -o cpprays cpprays/main.cpp
Have you tried -O2? -O3 often generates slower code.
>i7 2600
Intel's compiler would probably generate faster code. That's why you can't just say "Go vs C++". You could let Go win this fight by compiling the C++ with Digital Mars. It is also a C++ compiler but it lacks a modern optimizer and the generated code is usually much slower.
- MTGandP 13y agoCan you elaborate on why -O3 often generates slower code? I've never heard that before.
- cpeterso 13y ago-O3 inlines functions and unrolls loops more aggressively, so the increased code size might not fit in the CPU cache.
- kid0m4n 13y agoFair enough... let me do a quick test with -O2 and see how that fares
- stormbrew 13y agoMight want to also give a go at -Os (optimize for small code size). On code that spends its time iterating on the same code over and over again this can be a big win. [edit] Nope, definitely not better. I get O2 being a slight win over O3 and Os being much worse.
- kid0m4n 13y agoSo it totally disables all loop unrolling, inlining... hmm
- stormbrew 13y agoDoes a couple of other things, including choosing instruction sequences that are more compact afaik. But also favouring compactness over alignment and obviously jumps over unrolling. Obviously this isn't code that benefits terribly much from it, but it has been known to happen.
- zxcdw 13y agoCompiler optimization flags are very code and type specific. (Note that I am comparing apples to oranges here, I used the C++ code used in Rust experiments found here: https://github.com/huonw/card-trace/blob/master/original.cpp https://github.com/huonw/card-trace/blob/master/original.cpp ) I changed the C++ version typedef float f to typedef double f, so using floats instead of doubles, compiling with the following flags: -m64 -march=corei7-avx -mtune=corei7-avx -Ofast -funroll-all-loops and the run time dropped down from 17.5 seconds to 11.2 seconds. If I remove -funroll-all-loops, the run time jumps to 14.2 seconds. The original 17.5 seconds were ran with vanilla code using float and -O3. Interestingly enough, if you use the aforementioned flags with floats instead of doubles, the program executes in 15.01 seconds instead. Using floats is bad for performance! Further, if you remove -funroll-all-loops when using floats, the performance increases, but with doubles it decreases. So, when optimizing, play with compiler flags. Play with types. Play with whatever you have at your disposal and make no assumptions. This stuff is far more complex than believing that certain flags are better than others, it all depends on everything.
- copx 13y agoIt is common knowledge among GCC users. In the past using -O3 was rare because it often generated downright broken code. There used to be an official warning about that. The situation is better nowadays but still, as far as I know, no major Linux distro uses -O3 as the default for binary packages. -O3 can generate slower code because of the aggressive inlining and loop unrolling enabled. These optimizations are very tricky because of their effect on cache use. Basically all that extra code can push other needed code/data out of the cache, which can cause a noticeable decrease in performance.
- gillianseed 13y agoI think it's 'common knowledge' which has outlived it's relevance as I can't recall the last time I found -O2 outperforming -O3. Practically every performance oriented open source program I come across also defaults to -O3 these days, or sometimes -Ofast which also enables -ffast-math. >-O3 can generate slower code because of the aggressive inlining and loop unrolling enabled -O3 turns on vectorization and inlining optimizations but I can't recall any loop unrolling options which are turned on at -O3. -funroll-loops is not turned on at any of the -O (including -O3) levels due to it being one of the hardest to get right without any runtime data as basis (which is why the only option that turns it on is PGO - profile generated optimization). Note that I'm talking about modern versions of GCC, if you are using GCC 4.21 on OSX then this (-O2 > -O3) may still typically be the case. >The situation is better nowadays but still, as far as I know, no major Linux distro uses -O3 as the default for binary packages. I'd say they typically use the upstream optimization settings.
- copx 13y ago>I think it's 'common knowledge' which has outlived it's relevance as I can't recall the last time I found -O2 outperforming -O3. I can, was about 4 months ago with GCC 4.8.0. >practically every performance oriented open source program I come across also defaults to -O3 these days How large is your sample size there? I have only seen -O3 in the default makefiles of audio/video encoders. Those tend to be a natural fit for -O3. In contrast, here is the current makefile of my favorite "performance oriented" FOSS program: http://repo.or.cz/w/luajit-2.0.git/blob_plain/HEAD:/src/Makefile http://repo.or.cz/w/luajit-2.0.git/blob_plain/HEAD:/src/Make... CCOPT= -O2 -fomit-frame-pointer # Note: it's no longer recommended to use -O3 with GCC 4.x. # The I-Cache bloat usually outweighs the benefits from aggressive inlining. >I can't recall any loop unrolling options which are turned on at -O3. You are right (I just looked it up). Guess my memory failed me there. >I'd say they typically use the upstream optimization settings I wish! Packagers love to fool around with the upstream sources and makefiles to make them conform to whatever "standards" they have.
- kid0m4n 13y agogccgo should give better numbers with Go as well. I am guess we pick one and stick with it. I don't mind trying Intel's compiler though
- bluecalm 13y agoFew remarks: -mtune is redundant with march=native turned on; -use -Ofast instead O3/ffast-math it turns some more options as well (although theoretically it might behave in non-standard way with float computations, you need to test this, it wasn't ever a problem for me) -add -flto it often helps significantly -it probably won't matter for simple program but you may try compiling with: -Ofast -march=native -flto -fprofile-generate; then run the program (it will generate .gcda files) and then recompile with the same options and -fprofile-use; EDIT: Some quick tests shows that all the options I mentioned help (MinGW, gcc 4.8.1). Original time on one thread was 3.670s, Ofast and -flto takes it to ~3.630s and adding PGO moves it to 3.46s (there is some variance with all of those) - whooping 5-6% improvement overall :)
- bluecalm 13y agoI can't edit anymore, so replying to myself: On my machine (i7 3770) inserting famous Quake3 hack in place of 1/sqrtf: http://en.wikipedia.org/wiki/Fast_inverse_square_root http://en.wikipedia.org/wiki/Fast_inverse_square_root is faster but not accurate with one iteration (image is very distorted) and slower but accurate with 2 iterations.
- twoodfin 13y agoHow would -flto help when all the code is in one module?
- bluecalm 13y agoAll I know about gcc flags is from testing a lot of combinations of them. I don't really know how -flto works but maybe it does something for functions from included files ?