传统上,分布式计算基于消息传递模型,其中数据以消息的形式从处理器传递到处理器。RPC 实际上是相同的模型(或非常接近)。
DSM 是分布式系统的所有节点(处理器)共享的虚拟地址空间。程序访问 DSM 中的数据的方式与访问传统计算机虚拟内存中的数据的方式非常相似。在具有 DSM 的系统上,数据在不同计算机的本地存储器之间移动的方式与它们在一台计算机的 RAM 和外部存储器之间移动的方式相同。
6.1 DSM的优势
- 在消息传递模型中,程序员通过显式的消息发送和接收操作提供对共享数据的访问。在这种情况下,需要对算法进行量化,保证缓冲区中信息的及时变化,并对数组索引进行变换。所有这些都使编程和调试变得非常复杂。DSM 对程序员隐藏数据传输,并为他提供他已经习惯在多处理器上使用的共享内存抽象。使用 DSM 进行编程和调试要容易得多。
- 在消息传递模型中,数据在两个不同的地址空间之间移动。这使得在进程之间传输复杂的数据结构变得非常困难。此外,通过引用传递数据和传递包含指针的数据结构通常是复杂且昂贵的。DSM 还允许您通过引用传递数据,这简化了分布式应用程序的开发。
- 所有节点的总物理内存量可能很大。应用程序可以使用如此大量的内存,而不会产生与传统磁盘交换系统相关的开销。由于处理器速度的增长速度快于内存速度,同时出现了非常快速的通信,这一优势变得越来越重要。
- DSM 系统几乎可以无限增长,这与具有共享内存的系统不同,即 是可扩展的。
- 为共享内存多处理器编写的程序原则上可以在 DSM 系统上运行而无需任何更改(至少它们可以很容易地移植到 DSM 系统)本质上,DSM 系统克服了多处理器的体系结构限制并减少了编写所需的工作量分布式系统的程序。这些通常在固件中实现,但近年来已经有几个商业 MPP 与 DSM 在硬件中实现(凸 SPP,KSR1)。
6.2 DSM实现算法
以下问题是 DSM 实施的核心。
- 如何维护有关已删除数据位置的信息。
- 如何在访问远程数据时减少与实施通信协议相关的通信延迟和高昂的开销成本。
- 如何在多个节点上同时提供共享数据以提高系统性能。
让我们考虑四种基本的 DSM 实现算法。
所有共享数据都由中央服务器维护。它在读取请求时将数据返回给客户端,在写入请求时它会更正数据,并将回执发送回客户端。当服务器没有响应时,客户端可以使用超时来发送重试。通过请求编号可以识别重复的写入请求。如果对服务器的多次重复调用仍未得到应答,应用程序将收到否定响应代码(这是由客户端提供的)。
该算法易于实现,但服务器可能成为瓶颈。
为避免这种情况,可以将共享数据分布在多个服务器上。在这种情况下,客户端必须能够确定每次访问共享变量时要联系哪个服务器。一次向所有服务器发送请求是不可取的,因为它不会减少服务器上的负载。最好的解决方案是根据地址分配数据并使用映射功能确定正确的服务器。
与之前的算法不同,当一个数据请求被发送到它的位置时,在这个算法中数据的位置会发生变化——它们会移动到需要它们的地方。这允许在本地执行顺序数据访问。迁移算法只允许一个节点在任何给定时间访问一个数据元素。
通常迁移整个页面或数据块,而不是请求的数据单元。这使您可以利用应用程序中数据访问的固有局部性来降低迁移成本。但是,当页面在节点之间迁移时经常只提供少量请求时,这种方法会导致抖动。一些系统允许您设置页面被强制保留在节点中的时间,以便在将页面迁移到另一个节点之前有时间对其执行多次访问。
迁移算法允许 DSM 与单个节点中操作系统提供的虚拟内存集成。如果 DSM 页面大小与虚拟内存页面大小相同(或它的倍数),那么您可以使用普通机器指令访问共享内存,使用硬件检查 RAM 中是否存在所需的页面并用物理地址替换虚拟地址。当然,为此,处理器的虚拟地址空间必须足以寻址整个共享内存。在这种情况下,一个节点中的多个进程可以共享同一个页面。
为了确定数据块的位置,迁移算法可以使用跟踪块移动的服务器,或者使用每个节点中的提示机制。广播请求也是可能的。
以前的算法只允许一个节点(该数据所在的节点)中的进程在任何时候访问共享数据。该算法通过数据块乘法机制扩展了迁移算法,允许多个节点能够同时读取和写入数据,或者一个节点能够读取和写入数据(多读一写协议)。并发读取访问的可能性提高了性能,但写入破坏或更正数据块的任何过时副本的成本很高。
使用这种算法时,需要跟踪所有数据块及其副本的位置。例如,块的每个所有者都可以跟踪其副本的位置。
当读取次数明显超过写入次数时,该算法可以降低平均读取访问成本。
该算法是先前算法的扩展。它允许许多节点同时对共享数据进行读写访问(多读取器和多写入器协议)。由于许多节点可以并行写入数据,因此有必要控制对它们的访问以保持数据一致性。
确保数据一致性的一种方法是使用特殊过程来订购内存修改。所有希望修改共享数据的节点都必须将其修改发送到该进程。它将为每个修改分配一个连续的编号,并将其与修改一起广播到所有具有被修改数据块副本的节点。每个节点将按照其编号的升序进行修改。收到的修改数量的差距将意味着丢失一个或多个修改。在这种情况下,节点可能会请求丢失的修改。
上述所有算法都是低效的。效率只能通过改变内存访问的语义来实现。
6.3 一致性模型
一致性模型是程序和内存之间的一种协议,它表明如果程序遵循一定的规则,内存模块的操作就会正确,但是如果违反了程序的要求,那么内存不保证正确执行读/写操作。本章讨论分布式内存系统中使用的主要一致性模型。
满足条件的一致性模型:对地址 X 的内存位置的读操作必须返回地址 X 最近的写操作写入的值,称为强一致性模型。上面的条件看起来很自然很明显,但是它假设系统有绝对时间的概念来确定最近的写操作。
所有单处理器系统都提供强一致性,但在分布式多处理器系统中情况要复杂得多。假设变量 X 位于机器 B 的内存中,并且在机器 A 上运行的进程试图在时间 T1 读取该变量的值。为此,机器 B 发送对变量 X 的请求。稍后,在 T2 时刻,机器 B 上运行的进程执行了向变量 X 写入新值的操作。为确保严格一致性,读取操作必须返回机器 A 的变量旧值,无论机器 A 位于何处以及两次 T1 和 T2 彼此之间的距离如何。但是,如果 T1-T2 为 1 纳秒且机器相距 3 米,
P1: W(x)1 | P1: W(x)1 |
--> t | --> t |
P2: R(x)1 | P2: R(x)0 R(x)1 |
а) | б) |
a) 严格一致的内存
b) 没有严格一致性 的内存
强一致性是编程的理想模型,但不幸的是,对于程序员来说,它无法在分布式系统中实现。然而,实践经验表明,在某些情况