我正在观看Herb Sutter 关于 GPGPU 和新的 C++ AMP 库的视频。他在谈论内存模型并提到弱内存模型,然后是强内存模型,我认为他指的是读/写顺序等,但我不确定。
谷歌发现了一些关于内存模型的有趣结果(主要是科学论文),但是有人可以解释什么是弱内存模型,什么是强内存模型以及它们与并发的关系吗?
我正在观看Herb Sutter 关于 GPGPU 和新的 C++ AMP 库的视频。他在谈论内存模型并提到弱内存模型,然后是强内存模型,我认为他指的是读/写顺序等,但我不确定。
谷歌发现了一些关于内存模型的有趣结果(主要是科学论文),但是有人可以解释什么是弱内存模型,什么是强内存模型以及它们与并发的关系吗?
在并发方面,内存模型指定了对数据访问的约束,以及一个线程/内核/处理器写入的数据对另一个线程/内核/处理器写入的条件。
弱和强这两个术语有些含糊,但基本前提是强内存模型对硬件施加了很多限制,以确保一个线程/内核/处理器的写入对其他线程/内核/处理器清晰可见-定义的顺序,同时允许程序员最大的数据访问自由。
另一方面,弱模型对硬件的限制很少,而是将确保可见性的责任交给了程序员。
最强的内存模型是顺序一致性:所有处理器对所有数据的所有操作形成一个由所有处理器商定的单一总顺序,这与每个处理器上单独的操作顺序一致。这本质上是每个处理器操作的交错。
最弱的内存模型不会对处理器看到彼此写入的顺序施加任何限制。同一系统中的不同处理器可能会看到不同顺序的写入,并且某些处理器可能会在另一个处理器写入同一内存地址后长时间使用自己缓存中的“陈旧”数据。有时,整个高速缓存行被视为一个单元,因此对高速缓存行上的一个变量的写入将导致从其他处理器对该高速缓存行上的其他变量的写入被第一个处理器不可见的有效丢弃,因为当它最终将高速缓存行写入内存时,陈旧的值被写入顶部。在这样的方案下,必须非常小心以确保数据以正确的顺序传输到其他处理器,
例如,Intel x86 内存模型通常被认为处于更强大的一端,因为对于写入对其他处理器可见的顺序有严格的规定,而 DEC Alpha 和 ARM 处理器通常被认为具有弱内存模型,因为如果您在代码中明确放置排序指令(内存围栏或屏障),则仅需要以特定顺序对其他处理器可见来自一个处理器的写入。
某些系统具有只能由特定处理器访问的内存。因此,在这些处理器之间传输数据需要明确的数据传输指令。Cell 处理器就是这种情况,GPU 也经常是这种情况。这可以被视为弱内存模型的极端——如果您明确调用数据传输,数据仅对其他处理器可见。
编程语言通常将自己的内存模型强加于底层处理器提供的任何东西之上。例如,C++0x 指定了一整套从完全放松到完全顺序一致性的排序约束,因此您可以在代码中指定您需要的内容。另一方面,Java 有一组非常具体的排序约束,必须遵守并且不能改变。在这两种情况下,编译器都必须将所需的约束转换为底层处理器的相关指令,如果您在弱排序机器上请求顺序一致性,这可能会非常复杂。
这两个术语没有明确定义,也不是非黑即白。
记忆模型可能非常弱,非常强,或者介于两者之间。
它基本上是指对并发内存访问提供的保证。
天真地,您会期望在一个线程上进行的写入立即对所有其他线程可见。您会期望事件在所有线程上也以相同的顺序出现。
但在较弱的记忆模型中,这些都可能不成立。
顺序一致性是内存模型的术语,它保证事件在所有事件中以相同的顺序出现线程中以相同的顺序出现。因此,确保顺序一致性的内存模型非常强大。
一个较弱的保证是因果一致性:保证事件在它们所依赖的事件之后被观察到。
换句话说,如果你先将一个值写入x
某个地址A
,然后再将第二个值写入同一个地址,那么在读取该值之后y
,任何线程都不会再读取该值。因为这两次写入是针对同一个地址的,所以如果不是所有线程都遵循相同的顺序,就会违反因果一致性。但这并没有说明无关事件应该发生什么。其他线程绝对可以随时观察到将第三个值写入不同内存地址的结果(因此不同线程可能以不同的顺序观察事件,这与顺序一致性下不同)y
x
还有很多其他这样的“一致性”级别,有的更强,有的更弱,并为你可以依赖什么提供各种微妙的保证。
从根本上说,更强大的记忆模型将为观察事件的顺序提供更多保证,并且通常会保证行为更接近您的直觉预期。
但是较弱的模型允许有更多的优化空间,特别是它可以更好地扩展内核(因为需要更少的同步)
顺序一致性在单核 CPU 上基本上是免费的,在四核上是可行的,但在 32 核系统或具有 4 个物理 CPU 的系统上会非常昂贵。或多台物理机之间的共享内存系统。
你拥有的核心越多,它们之间的距离越远,就越难确保它们都以相同的顺序观察事件。所以做出了妥协,你满足于一个较弱的内存模型,它可以提供更宽松的保证。
是的,你是对的 - 弱内存模型和强内存模型之间的区别在于可用优化的不同(读/写顺序和相关栅栏)。
您可以从顺序一致的模型(最严格或最强的模型)开始指定内存模型,然后指定如何引入、删除或相对于彼此移动来自单个线程的读取和写入
在这个模型(顺序一致)中,内存独立于使用它的任何处理器(线程)。内存通过一个控制器连接到每个线程,该控制器提供来自每个线程的读取和写入请求。来自单个线程的读取和写入完全按照线程指定的顺序到达内存,但它们可能以未指定的方式与来自其他线程的读取和写入交错
但是,强记忆模型和弱记忆模型之间没有确切的界限,除非您考虑顺序一致的模型与其他模型。其中一些只是更强/更弱,因此比其他更容易通过重新排序进行优化。例如,用于 x86 的 .NET 2.0 中的内存模型允许比 .NET 1.1 中的版本进行更多优化,因此可以将其视为较弱的模型。
谷歌发现了一些关于内存模型的有趣结果(主要是科学论文),但是有人可以解释什么是弱内存模型,什么是强内存模型以及它们与并发的关系吗?
强内存模型是这样一种模型,从其他内核的角度来看,读取和写入似乎按照它们出现在程序中的方式发生,特别是按照它们在程序中出现的顺序。这称为顺序一致性。
弱内存模型是一种内存执行可能被 CPU 更改的模型,例如重新排序。所有实用的 CPU 架构都允许重新排序指令。
请注意,Herb Sutter 使用“强记忆模型”来表示原子内在函数未重新排序的模型。这不是普遍接受的定义。