【譯】到底什麼是內存模型?

What is a memory model, anyway?
到底什麼是內存模型?
 
In multiprocessor systems, processors generally have one or more layers of memory cache,
which improves performance both by speeding access to data (because the data is closer to the processor)
and reducing traffic on the shared memory bus (because many memory operations can be satisfied by local caches.)
在多處理系統上,處理器一般有一層或多層cache。它提升了訪問數據的速度(由於數據離cpu更近了),
減小了共享的內存總線的擁堵(由於大多數的對內存的操做均可以在本地的cache中獲得知足)
 
Memory caches can improve performance tremendously,
but they present a host of new challenges.
What, for example, happens when two processors examine the same memory location at the same time?
Under what conditions will they see the same value?
cache雖然極大地提升了性能,可是它帶來了新的挑戰。好比:當兩個處理器同時檢測同一個內存地址時會發生什麼?在這種狀況下它們會看到相同的值嗎?
 
At the processor level,
a memory model defines necessary and sufficient conditions
for knowing that writes to memory by other processors are visible to the current processor,
and writes by the current processor are visible to other processors.
在處理器級別上,內存模型定義了知道另外一個處理器寫內存,對當前處理器可見的充要條件;以及當前處理器寫內存,對其餘處理器可見的充要條件。
 
Some processors exhibit a strong memory model, where all processors see exactly the same value for any given memory location at all times.
Other processors exhibit a weaker memory model, where special instructions, called memory barriers,
are required to flush or invalidate the local processor cache in order to see writes made by other processors or make writes by this processor visible to others.
一些處理器提出了強內存模型,即全部處理器在任什麼時候候,對於給定的內存地址,看到的值都是同樣的。
而另外一些處理器提出了弱內存模型,即爲了讓其餘處理器的寫結果對該處理器可見,或是該處理器的寫結果對其餘處理器可見,須要一些特殊的指令,稱做內存屏障
用來沖刷處理器的本地cache或使處理器的本地cache失效。
 
These memory barriers are usually performed when lock and unlock actions are taken;
they are invisible to programmers in a high level language.
這些內存屏障一般被執行在加鎖或解鎖的動做中,對使用高級語言的程序猿隱藏。
 
It can sometimes be easier to write programs for strong memory models, because of the reduced need for memory barriers.
However, even on some of the strongest memory models, memory barriers are often necessary;
quite frequently their placement is counterintuitive.
強內存模型有時會比較容易編寫程序,由於減小了對內存屏障的須要。
可是就算是在某些最強的內存模型中,內存屏障經常也是須要的,它們放置的位置常常是違反直覺的。
 
Recent trends in processor design have encouraged weaker memory models,
because the relaxations they make for cache consistency allow for greater scalability across multiple processors and larger amounts of memory.
處理器設計的最新趨勢促進了弱內存模型,由於它們放鬆了緩存的一致性,所以能夠在多個處理器之間實現更大的可伸縮性,和使用更大容量的內存。
 
The issue of when a write becomes visible to another thread is compounded by the compiler's reordering of code.
For example, the compiler might decide that it is more efficient to move a write operation later in the program;
as long as this code motion does not change the program's semantics, it is free to do so.
If a compiler defers an operation, another thread will not see it until it is performed;
this mirrors the effect of caching.
編譯器對代碼的重排序使得寫結果什麼時候對另外一個線程可見的問題更加複雜。
好比,編譯器可能決定將寫操做移到後面會比較高效,只要代碼的移動不改變的程序的語義,這樣作就沒什麼問題。
若是編譯器推遲了一個操做,在它被執行前另外一個線程就不會看到該變化,這反映出了緩存的影響。
 
Moreover, writes to memory can be moved earlier in a program;
in this case, other threads might see a write before it actually "occurs" in the program.
All of this flexibility is by design -- by giving the compiler, runtime, or hardware the flexibility to execute operations in the optimal order, within the bounds of the memory model, we can achieve higher performance.
另外,往內存寫的操做可能被移到前面,在這種狀況下,其餘線程可能會看到寫的結果出如今了它實際"發生"以前。
爲了以最佳的順序來執行操做,編譯器、運行時或硬件會設計的比較靈活,在內存模型的邊界下,咱們能夠得到更高的性能。
 
A simple example of this can be seen in the following code:
一個簡單的例子以下面代碼所示:
 
Class Reordering {
  int x = 0, y = 0;
  public void writer() {
    x = 1;
    y = 2;
  }

  public void reader() {
    int r1 = y;
    int r2 = x;
  }
}

 

Let's say that this code is executed in two threads concurrently, and the read of y sees the value 2. Because this write came after the write to x, the programmer might assume that the read of x must see the value 1. However, the writes may have been reordered. If this takes place, then the write to y could happen, the reads of both variables could follow, and then the write to x could take place.
The result would be that r1 has the value 2, but r2 has the value 0.
上面的代碼被兩個線程併發執行,讀到y的值是2。由於y的值在x=1後被賦值的,所以程序猿可能會假定讀x的值必然是1。
然而,寫操做可能被重排序。若是發生了重排序,則y=2可能先發生,以後執行reader(),讀取y和x的值,再執行x=1。
這樣的結果就是r1=2,而r2=0。
 
The Java Memory Model describes what behaviors are legal in multithreaded code, and how threads may interact through memory.
It describes the relationship between variables in a program and the low-level details of storing and retrieving them to and from memory or registers in a real computer system.
It does this in a way that can be implemented correctly using a wide variety of hardware and a wide variety of compiler optimizations.
Java內存模型描述了多線程代碼中,什麼行爲是合法的,以及線程如何經過內存交互。它描述了程序中變量之間的關係和對實際計算機系統的內存或寄存器存取的底層細節。
它使用各類硬件和編譯器的優化,以這種方式來正確實現上述說明。
 
Java includes several language constructs, including volatile, final, and synchronized,
which are intended to help the programmer describe a program's concurrency requirements to the compiler.
The Java Memory Model defines the behavior of volatile and synchronized, and, more importantly, ensures that a correctly synchronized Java program runs correctly on all processor architectures.
Java包括幾個語言結構,volatile、final和synchronized,這些結構傾向於幫助程序猿對編譯器描述程序的併發需求。
更重要的是,Java內存模型定義了volatile和synchronized的行爲,確保正確同步的Java程序在全部處理器體系結構上都能正確運行。
 
Do other languages, like C++, have a memory model?
其餘語言,如C++,有內存模型嗎?
Most other programming languages,
such as C and C++, were not designed with direct support for multithreading.
The protections that these languages offer against the kinds of reorderings that take place in compilers and architectures are heavily dependent on the guarantees provided by the threading libraries used (such as pthreads), the compiler used, and the platform on which the code is run.
大多數其餘編程語言,如C/C++,沒有設計直接支持多線程。這些語言提供針對編譯器和體系結構發生重排序的保護措施嚴重依賴所使用的多線程庫(好比pthreads)、編譯器、和代碼運行的平臺的保證。
 
[注] C++11也提出了內存模型。
 
相關文章
相關標籤/搜索