Specifically, I'm looking for a plain-English explanation of phrases like "no operation can be ordered before a load" or "no operation can be ordered after a write", etc. What exactly is an operation, and what does it mean for it to get "re-ordered"?
Different instructions use different parts of the processor. Modern super-scalar processors are able to execute multiple instructions simultaneously, as long as they use different resources (from a single thread, I am not referring to multicore). So the CPU will actually go looking forward in the instruction stream for an instruction it can start working on at the same time as the current one (due to pipelining and branch prediction, instructions are decoded quite a while before they execute, which makes this look-ahead possible).
The CPU is careful to respect data dependencies, meaning that if one instruction uses the result of another, they will execute in the right order. But if for example two instructions write two different memory locations, and the first one can't start because it's waiting for say an integer division unit to become available, the memory write from the "later" instruction could actually happen first.
This becomes important when some other thread is looking at those memory locations. So there are flags provided in the instruction set, called memory barriers, which tell the CPU that later instructions in the pipeline need to wait for earlier ones, even if there's no data dependency. The C++11 memory model defines what your source code has to look like to persuade the compiler to insert these flags.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With