并发和内存模型

8
我正在观看Herb Sutter关于GPGPU和新的C++ AMP库的视频this。他谈到了内存模型,提到了弱内存模型和强内存模型,我认为他指的是读写排序等,但我不确定。
谷歌上有一些有趣的结果(大多数是科学论文)关于内存模型,但有人能解释一下什么是弱内存模型,什么是强内存模型以及它们与并发的关系吗?
4个回答

14
就并发性而言,内存模型规定了数据访问的限制以及一个线程/核心/处理器写入的数据何时对另一个可见的条件。
术语"强"和"弱"有些含糊不清,但基本原则是,强内存模型会在硬件上施加很多约束,以确保一个线程/核心/处理器的写入按照明确定义的顺序对其他线程/核心/处理器可见,同时允许程序员最大限度地自由访问数据。
另一方面,弱模型在硬件上几乎没有任何约束,而是将确保可见性的责任放在程序员手中。
最强的内存模型是"顺序一致性":所有处理器对所有数据的所有操作形成一个由所有处理器共同确认的单个总顺序,该顺序与每个处理器个体操作的顺序一致。这本质上是每个处理器操作的交错。
最弱的内存模型将不对处理器看到彼此的写入顺序施加任何限制。同一系统中的不同处理器可能会以不同的顺序看到写入,并且某些处理器可能会在另一个处理器写入同一内存地址后长时间使用其自己高速缓存中的"陈旧"数据。有时,整个高速缓存行被视为单个单位,因此对高速缓存行上的一个变量的写入将导致其他处理器对该高速缓存行上的其他变量的写入(这些变量对于第一个处理器尚不可见)被有效地丢弃,因为在最终将缓存行写入内存时,过期值会被覆盖掉。在这样的方案下,必须非常小心地使用显式同步指令来确保以正确的顺序向其他处理器传输数据。
例如,英特尔x86内存模型通常被认为是较强的,因为有严格的规则确定写入何时对其他处理器可见,而DEC Alpha和ARM处理器通常被认为具有弱内存模型,因为只有在代码中明确放置排序指令(内存栅或屏障)时,从一个处理器写入的内容才需要按照特定顺序对其他处理器可见。一些系统存在只能被特定处理器访问的内存。因此,在这些处理器之间传输数据需要显式的数据传输指令。这是Cell处理器的情况,GPU也经常如此。可以将其视为弱内存模型的极端情况 --- 只有在显式调用数据传输时,其他处理器才能看到数据。
编程语言通常在底层处理器提供的内存模型之上施加自己的内存模型。例如,C++0x指定了一组完整的排序约束条件,从完全放松到完全顺序一致性,因此你可以在代码中指定你需要的内容。另一方面,Java具有非常特定的排序约束条件,必须遵守,不能变更。在两种情况下,编译器必须将所需的约束转换为底层处理器的相关指令,如果在弱排序机器上请求顺序一致性,则可能相当复杂。

6
这两个术语并没有明确定义,这不是非黑即白的事情。
内存模型可以非常弱、非常强,或者介于两者之间。
它基本上指的是关于并发内存访问所提供的保证。
直觉上,你会期望在一个线程上进行的写入将立即对所有其他线程可见。你也会期望事件在所有线程上以相同的顺序出现。
但在较弱的内存模型中,两者都可能不成立。
顺序一致性是指在所有线程上保证事件以相同的顺序出现的内存模型。因此,确保顺序一致性的内存模型相当强大。
较弱的保证是因果一致性:保证在事件依赖的事件之后观察到这些事件。
换句话说,如果你首先在某个地址A上写入值x,然后再写入第二个值y,那么没有一个线程将在读取x后读取值y。因为两个写入操作是对同一地址的,如果不是所有线程观察到了相同的顺序,就会违反因果一致性。
但这并不意味着无关事件的结局。写入第三个值到另一个内存地址的结果可以被其他线程随时观察到(与顺序一致性不同,不同的线程可以以不同的顺序观察到事件)。
还有许多其他的“一致性”级别,有些更强,有些更弱,并提供各种微妙的保证,关于你可以依赖什么。
从根本上说,更强的内存模型将提供更多关于观察事件顺序的保证,并通常保证行为更接近你的直觉预期。
但是对于较弱的模型,允许更多的优化空间,尤其是在更多核心的情况下,因为需要更少的同步。
在单核 CPU 上,顺序一致性基本上是免费的,在四核 CPU 上是可行的,但在 32 核系统、4 个物理 CPU 的系统或多个物理机之间共享内存的系统上则成本过高。
你拥有的核心数越多,它们之间距离越远,就越难确保它们都以相同的顺序观察事件。所以会做出妥协,选择更弱的内存模型,以提供较松的保证。

1
一个确保顺序一致性的内存模型非常强大。这不就是强大的定义吗? - J D
@JonHarrop:这取决于你问谁。我不知道术语的单一规范定义。但是,实际上,当我们谈论强内存模型时,通常意味着顺序一致性。 - jalf

4

是的,你说得对 - 弱内存模型和强内存模型之间的区别在于可用的优化方式(读/写顺序及相关屏障)不同。

您可以通过从顺序一致模型(最严格或最强的模型)开始,然后指定如何引入、删除或移动单个线程的读写操作来指定内存模型

在此模型(顺序一致性)中,内存独立于使用它的任何处理器(线程)。内存通过控制器连接到每个线程,该控制器从每个线程提供读取和写入请求。单个线程的读取和写入按照线程指定的顺序 完全 到达内存,但可能以未指定的方式与其他线程的读取和写入交错。

了解多线程应用程序中低锁技术的影响

然而,在强内存模型和弱内存模型之间并没有确切的界限,除非您考虑顺序一致性模型与其他模型的区别。其中一些模型只是比其他模型更强或更弱,因此更容易通过重新排序进行优化。例如,.NET 2.0中针对x86的内存模型允许比.NET 1.1中的版本更多的优化,因此可以认为它是一个较弱的模型。


2
Google搜索会出现一些关于内存模型的有趣结果(主要是科学论文),但是可以有人解释一下什么是弱内存模型和强内存模型以及它们与并发性的关系吗?
强内存模型是指,在其他核心的观点下,读取和写入看起来像在程序中出现的顺序一样,并且特别是按照它们在程序中出现的顺序。这被称为顺序一致性。
弱内存模型是指,记忆执行可能会被CPU更改,例如重新排序。所有实用的CPU架构都允许指令重新排序。
请注意,Herb Sutter使用“强内存模型”来表示不重新排序原子内在函数的模型。这不是通常接受的定义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接