Blame Arnon

Which architecture should I compile for with GCC?

Last week I wrote about strange assembler messages on new PCs and I mentioned there could be performance issues when you don’t use -march=native.

-march=native is very good if you only plan to run your code on a specific computer, or you allow people to compile it themselves from source.

So what happens if you drop that flag? Well, if no flags are specified explicitly, GCC will usually automatically apply -mtune=generic -march=x86-64.
This should be compatible with all x64 machines since Intel Core2 (2006) and AMD Opteron (2003).
(You can verify this by running echo "int main {return 0;}" | gcc -O2 -x c -v -Q -).
This is fairly generic.

What is this generic compilation good for? Well, as a rule of thumb, you should always keep your compilations generic when you are publishing binaries that could run on many different processors. Any specific architecture you’ll compile for might break on an older or different (AMD vs. Intel for instance).
This rule has a drawback though – performance!

  • Intel claims that there is a 17%-22% improvement when the march and mtune flags are set properly, and not just generic, x86-64 or nocona is used.
  • According to Phoronix, there is some benefit to be had from using the correct march flags – but there might also be a regression. Luckily, those are expected to be fixed by GCC 4.9.0.

So what if you decide performance is important? Your stability will suffer:

  • If you compile on a new architecture (say, Core i7-4000) – it might crash on older architecture (Core i7-3000) if specific unknown assembly command is reached. You might not even know if it will fail until you test all features in your code, and reach 100% code coverage.
  • If set, the mtune flag will output an error if the target architecture doesn’t match compiled architecture and prevent program from running altogether. This is a safety option that you should consider using if compiling for specific architectures.

So if you decide to compile for specific architectures, you can find out what architecture GCC thinks you’re on by running

gcc -march=native -Q --help=target | grep march

Some Processor reference flags:

  1. Intel Core 2 Duo – -march=core2
  2. Nehalem-based Xeons – -march=corei7
  3. Sandy Bridge based Xeons (E3-12xx series, E5-14xx/24xx series, E5-16xx/26xx/46xx series) – -march=corei7-avx for GCC versions < 4.9 and -march=sandybridge for GCC versions 4.9 and newer.
  4. Ivy Bridge (Intel iN 3XXX and Xeons E3-12xx v2-series, E5-14xx v2/24xx v2-series, E5-16xx v2/26xx v2/46xx v2-series, E7-28xx v2/48xx v2/88xx v2-series) – -march=core-avx-i
  5. Haswell (Intel iN 4XXX and Xeons E3-1xxx v3-series, E5-1xxx v3-series, E5-2xxx v3-series) – -march=core-avx2

Leave a Reply