In the "C++0x Ramble" series: Multithreaded memory model (referred to as a ramble) explains the difficulties of multithreading parallelism, here I layered to see this problem.
1. Why is it layered?
The abstraction of the C + + language is closer to the abstraction of the machine, and the instance of C + + running on the virtual machine is almost invisible, so the relationship between the two is easily confused. Some people often take the disassembly to see, and as the C + + language is such evidence, this is the cart before the horse. Assuming that C + + is translated directly into a compilation, this is just a question of how to translate one language into another language. What the compiler does is to use some abstraction of the target language to realize some abstraction of the source language, so the semantics and behavior of the target language cannot determine the source language, but only the correctness and quality of the translation. For example, a C + + class has a semantic invocation of a constructor, but its behavior is trivial, and the code in the translated code does not see any constructor calls, which is not evidence that the constructor does not exist. So, here we split the hierarchy, on the one hand is the assembly and its implementation (that is, the CPU) of the combination, on the other hand is C + +.
2. How to translate?
Clearly, translation is based on a full understanding of both languages. To understand a language, it is necessary to understand its provided abstraction and its semantics. How do I define semantics? This is a study of the programming language of the people to do, more classical has the operational semantics, the referent semantics. Here we do not strictly look at these two languages from an operational semantic point of view.
2.1 assembly language is relatively low level, its operation semantics is very clear. Considering parallelism, Intel (discussed here only x86) also defines its memory order, which shows some of the assembly code that executes in parallel, and shows what kind of results are possible and what results are not possible.
2.2 for C + +, its semantics can also be described by some operations and their state changes (purely operational semantics do not fully describe C + +, we are only more concerned about operations and their results).
At this point, the correctness of translation becomes the equivalence of the operation.
Et cetera, mentioned in 2.1 in parallel, 2.2 does not mention (or not mentioned before c++11), yes, this is the problem: C + + has no such semantics, but in fact, through multi-threaded execution in parallel, so its correctness is not guaranteed.
3. How do I ensure that languages without parallel semantics are correct in parallel execution?
In the article "Ramble" has been said. One simple way to do this is to prohibit the compiler from making any optimizations: All operations are performed strictly in code order, and all actions trigger the cache coherence operation to ensure that their side effects are visibility in the order of cross-threading. "I don't think it's a simple matter of banning the compiler from doing any optimizations to get back to the effect, even requiring the compiler to do more." More of this is equivalent to the expansion of the source language: there are parallels. The "Data-race-free" mentioned later makes it possible to improve efficiency while guaranteeing correctness, which is actually equivalent to a language with parallel semantics for compiler extensions (when synchronization primitives are provided by compilers as compiler extension languages, when synchronization primitives are provided by the library, It is considered that the library extends the semantics, and the compiler must understand the semantics provided by the library, otherwise the optimization will be ruined where the library code is called. How do you implement libraries? Programming for execution environments. Either the library is written directly in the language of the execution environment, or by inserting code that executes the environment (inline assembly), which is not optimized by the compiler at the insertion code.
The above correctness considers the comparison theory, if actually speaking?
A assumes that optimizations do not cross function calls. This allows the library's code to be protected, on the other hand, to ensure the correctness of the call.
b for execution environment programming, with inline assembly to ensure parallel semantics.
C assumes optimization does not span inline assembly.
The above assumptions are easier to implement, and after implementation we have a language that relies on libraries to provide parallel semantics.
4. What if the source language has parallel semantics?
After defining the semantics of the Mutex,atom in c++11, the compiler knows that the order of certain operations cannot be changed, and should be added in the appropriate place.
Correct C + + parallelism