14

In this highly voted answer to a question on the performance differences between C++ and Java I learn that the JIT compiler is sometimes able to optimize better because it can determine the exact specifics of the machine (processor, cache sizes, etc.):

Generally, C# and Java can be just as fast or faster because the JIT compiler -- a compiler that compiles your IL the first time it's executed -- can make optimizations that a C++ compiled program cannot because it can query the machine. It can determine if the machine is Intel or AMD; Pentium 4, Core Solo, or Core Duo; or if supports SSE4, etc.

A C++ program has to be compiled beforehand usually with mixed optimizations so that it runs decently well on all machines, but is not optimized as much as it could be for a single configuration (i.e. processor, instruction set, other hardware).

Question: Is there a way to tell the compiler to optimize specifically for my current machine? Is there a compiler which is able to do this?

Community
  • 1
  • 1
Beginner
  • 5,277
  • 6
  • 34
  • 71
  • 1
    So someone on the internet says "Java is faster than C++", and you are worried that it might be true? :-) Why don't you also read [Is inline assembly language slower than native C++ code?](http://stackoverflow.com/questions/9601427/is-inline-assembly-language-slower-than-native-c-code) to balance that? – Bo Persson Apr 11 '17 at 13:52
  • @BoPersson Haha, you're right, I got a little bit worried here :-) The gist of the answers to that post seem to be that programming in C++ will lead to faster code than handwritten assemly for me. If it turns out that Java is acually faster than C++ most of the time because of the JIT, that would be quite surprising, don't you think so? – Beginner Apr 11 '17 at 13:59
  • 2
    It's kind of a myth spread by the Java guys. Theoretically, the JIT *could* contain a tuned code generator for every CPU ever produced. But of course it doesn't. And like the answers here say - if you need your code tuned to the very latest CPU available to be fast enough, you compile for that. Then it won't run on a 386, but neither will the JITed version in any useful way. – Bo Persson Apr 11 '17 at 14:11
  • 1
    @Beginner, The answer you quote were just based on theory. Experiment proved that compiled code run just faster! The reason is simple. Compiled code are designed to be compiled! Java is not. And in the end, what do the JIT is compiling code that is not designed to be compiled. All the java code that has been sold by Oracle to say "Hey java is faster" are just C code style written in Java for a very specific architecture and code. It is really boring to fight against hoax propagated by such a mercantile company. – Oliv Apr 11 '17 at 15:16
  • FWIW a C++ programs can also have dynamic feature detection and dynamic tuning, but that means that all available versions of a function are pre-compiled so it makes the executable bigger. – harold Apr 11 '17 at 17:44

2 Answers2

11

For GCC, you can use the flag -march=native. Be aware that the generated code may not run on other CPUs because

GCC uses this name to determine what kind of instructions it can emit when generating assembly code.

So CPU specific assembly can be generated.

If you want your code to run on other CPU types, but tune it for better performance on your CPU, then you should use -mtune=native:

Specify the name of the processor to tune the performance for. The code will be tuned as if the target processor were of the type specified in this option, but still using instructions compatible with the target processor specified by a -mcpu= option.

Vitor
  • 2,734
  • 29
  • 40
  • `-march=native` compiles for the CPU doing the compiling (eg. your machine), not an arbitrary target. – MuertoExcobito Apr 11 '17 at 13:36
  • Wow, -march allows a wide variety of architectures. This is exactly what I was looking for. https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/i386-and-x86_002d64-Options.html – Beginner Apr 11 '17 at 13:43
4

Certainly a compiler could be instructed to optimize for a specific architecture. This is true of gcc, if you look at the multitude of architecture flags that you can pass in. The same is true to a lesser extent on Visual Studio, as it has the -MACHINE option and /arch options.

However, unlike in Java, this likely means that the generated code is only (safe) to run on that hardware that is being targeted. The assertion that Java can be just as fast or faster only likely holds in the case of generically compiled C++ code. Given the target architecture, C++ code compiled for that specific architecture will likely be as fast or faster than equivalent Java code. Of course, it's much more work to support multiple architectures in this way.

MuertoExcobito
  • 9,741
  • 2
  • 37
  • 78
  • Thank you! One more question: the machine option only allows four different values: /MACHINE:{ARM|EBC|X64|X86} I was hoping for something that actually takes the specifics of my CPU into account, like cache sizes, etc. I find it really surprising that the JIT should be able to do something the C++-compiler can't... – Beginner Apr 11 '17 at 13:40
  • updated answer with the /arch options, with which you can give 'enhanced instruction set' support, such as SSE2, etc. – MuertoExcobito Apr 11 '17 at 13:54