Jump to content

How are CPU instruction set extension compatibilities handled when running an executable?

MrZoraman

There are a lot of CPU instruction set extensions. For the sake of an example I will use AVX-512, but even then, different CPUs support different subsets of the AVX-512 extension....

 

If I try to run a modern program that uses AVX-512 on an older CPU (or competitor CPU) that doesn't know about AVX-512, what happens? How is this problem addressed?

 

Someone was telling me that because of this, compiled programs don't contain any CPU extensions to make sure this kind of thing doesn't happen. But if that's the case, what's the point of extensions? What's the point of putting instruction set extensions on consumer CPUs?

 

Thanks!

Link to comment
Share on other sites

Link to post
Share on other sites

I can't really speak for any of the programs out there, but from a software dev student perspective I would say they would have to create different paths to the call the CPU.

Simply put, a program has to do a certain calculation, at which point it will check what the CPU supports (or it will probably have done this beforehand) and just run the calculation on the best possible option for the CPU in question.

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

I think generally speaking, the executable and CPU each have a list of instructions they support, and if the executable needs something the CPU doesn't have, it won't run.

 

Some programs also have compatibility fallbacks for certain instructions, so if a program needs AVX512 but doesn't see it on the CPU, it can fall back to performing the same operations in software for a minor speed penalty.

Link to comment
Share on other sites

Link to post
Share on other sites

8 hours ago, MrZoraman said:

If I try to run a modern program that uses AVX-512 on an older CPU (or competitor CPU) that doesn't know about AVX-512, what happens? How is this problem addressed?

 

If it's not handled by the developer it just won't work. Most programs that use AVX512 will check if your cpu supports it before trying to use it.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

First, to be able to use such feature you have to code in specific language that allow you to directly call those instruction. Secondly you need to compile this exe on a device with that extension set. Once you run the app on a non supporting platform you will get an error (at least on windows). When loading cpu modules it will be missing the specific subset or complete set of the AVX-512. Checking for those by code is not that complicated and the developper should also check for it to offer an alternate compilation OR use alternative methods not using any of the AVX-512. Problem come from different CPU for example the Cascade lake and tiger lake have different variation of the AVX-512 but that is another story

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Franck said:

First, to be able to use such feature you have to code in specific language that allow you to directly call those instruction

Incorrect. The requirement is that the compiler produces a binary using those instructions. The developer doesn't have to specifically use the instructions themselves, they can just enable compiler-flags that'll let the compiler use whichever instructions that'll produce the fastest code.

1 hour ago, Franck said:

Secondly you need to compile this exe on a device with that extension set

Again incorrect. You can produce binary code on any platform you like, like e.g. you can perfectly well compile ARM-binaries on an x86-platform; you're not executing the code when you're compiling it, so it doesn't matter if your platform supports the instructions or not.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

18 hours ago, MrZoraman said:

If I try to run a modern program that uses AVX-512 on an older CPU (or competitor CPU) that doesn't know about AVX-512, what happens?

The program will simply crash.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

There's an instruction called CPUID, which can be used to get information about the current CPU, and which instructions extensions it supports. 

 

If a developer tried to cover all of their bases, usually they would have multiple implementations of the same functions written with different extensions, and then have a fall back written in C/C++ or whatever their language is, which will still give the same functionality, albeit with nowhere the same performance. 

 

Generally the way this would work is there would be a function pointer which has the address of the function you'll end up using.  

At program start up, the developer would write an initialization function, which would do the CPUID checks, and set the function pointer with the address of the specific function to use.  Then during normal use, you're code only to call that one function pointer.

 

You could also do the same thing if you're workload would benefit from GPU acceleration, but you also want to make sure it still works on a computer that doesn't have a GPU, but does have a CPU with SIMD instruction

Link to comment
Share on other sites

Link to post
Share on other sites

10 minutes ago, JacobFW said:

Generally the way this would work is there would be a function pointer which has the address of the function you'll end up using.  

At program start up, the developer would write an initialization function, which would do the CPUID checks, and set the function pointer with the address of the specific function to use.

Indeed. As I've mentioned before in other threads, popular applications like e.g. VLC and FFmpeg, do this. They can be statically compiled for specific CPU-specs with just a simple flag given to the configure-script, but almost no one actually uses the option nowadays.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

19 hours ago, MrZoraman said:

If I try to run a modern program that uses AVX-512 on an older CPU (or competitor CPU) that doesn't know about AVX-512, what happens? How is this problem addressed?

On x86/x64, the CPU throws an invalid opcode exception. Whatever happens then depends on the OS, which should have installed a handler for that exception.

 

One way for applications to handle supporting multiple instruction sets would be to check CPU capabilities at runtime using the CPUID function and selecting the correct version of a library. Using diffirent DLL's for each supported instruction set, for example. 

 

Altough modern C++ compilers can create vectorized code under the right conditions it requires manual optimisation for the best performance. Using immintrin.h, for example.

Link to comment
Share on other sites

Link to post
Share on other sites

There's a few different strategies. The first, most common, and easiest, is to just not use extensions.

Another way is to write multiple functions, and control which ones get compiled with some flags. This way, you can compile the same application, but to take advantage of different extensions, or none if they are not available.

A third way is to be dynamic about it. That is to write a program that checks at runtime what extensions are available, and calls the appropriate function(s).

A different way is to use a JIT, like the CLR or the JVM. These can decide at runtime how to compile your intermediate code (CIL or Bytecode respectively), into machine instructions.

 

 

Quote

I'm guessing if you tried to force it the processor would stop you from getting it into a bad state. Something like the command isn't recognized or something. It's been a minute since I took my CPU course, though.

 

@Sakuriru Not always: https://github.com/xoreaxeaxeax/sandsifter is an application that runs "random" opcodes and sees what happens. It has found many cases of undocumented instructions, some of which produce illegal behavior.

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×