# I.2 处理器间通信：性能的关键问题
<!-- source: p1178 -->

处理器数量较多的多处理器中，处理器彼此相距更远，因此通信代价更高。此外，真正的并行应用要求应用内部的线程相互通信，其通信量通常大于松耦合的独立进程或独立事务集合；后两种情况正是许多商业服务器应用的典型特征。上述因素共同使高效的处理器间通信成为决定并行性能的最重要因素之一，在科学计算市场中尤其如此。

遗憾的是，要刻画应用的通信需求和体系结构的通信能力，十分复杂。本节考察决定通信性能的关键硬件特征，下一节再讨论应用行为及其通信需求。

任何硬件通信机制都有三个关键性能指标。

1. **通信带宽。** 理想情况下，通信带宽应受处理器、存储器和互连带宽的限制，而不应受通信机制某个环节的限制。互连网络决定系统的最大通信容量。单个节点的输入、输出带宽往往和系统总带宽同样重要，既受节点内部体系结构影响，也受通信机制影响。通信机制如何影响节点带宽？发生通信时，参与通信的节点中的资源会被占住，阻碍其他传入、传出通信。如果报文中的每个字都引入这种资源占用，它就对通信带宽设定了一个绝对上限，而且通常低于网络或存储系统所能提供的带宽。资源占用也可能包含按每次通信事件支付的部分，例如每个传入或传出的请求都会产生一次。在后一种情况下，资源占用限制的是通信事件速率，它对总体通信带宽的影响则取决于报文大小。
2. **通信延迟。** 理想情况下，延迟应尽可能低。如附录 F 所述，在没有争用时：

<!-- source: p1179 -->

$$
\begin{aligned}
\text{通信延迟}={}&\text{发送方开销}+\text{传播时间}\\
&+\text{传输时间}+\text{接收方开销}
\end{aligned}
$$

传播时间是固定的，传输时间由互连网络决定。收发报文的软、硬件开销则主要由通信机制及其实现决定。延迟为什么关键？它既影响性能，也影响多处理器编程的难易程度。若不能隐藏延迟，通信就会占住处理器资源，或迫使处理器等待，从而直接影响性能。

开销（overhead）与资源占用（occupancy）密切相关，因为许多形式的开销也会占住节点的一部分资源，带来资源占用代价，进而限制带宽。通信机制的关键特征可以直接影响这两者。例如，如何为远程通信的目的地址命名？如何实现保护？在共享地址空间中，命名和保护由处理器提供，额外开销很小。相反，如果每次通信都必须由操作系统提供这些机制，就会增加通信的开销和资源占用代价，进而降低带宽、增加延迟。

3. **通信延迟隐藏能力。** 通信机制在多大程度上能够让通信与计算重叠，或让不同通信重叠，从而隐藏延迟？虽然这一指标不像前两项那样容易测量，但它仍然很重要。可以在通信延迟相同、延迟隐藏支持不同的多处理器上测量运行时间，对其加以量化。隐藏延迟当然是个好主意，但也给软件系统、最终给程序员增加了负担；而且，能够隐藏多少延迟取决于应用。因此，通常最好仍尽可能降低延迟本身。

正如下节所示，这些性能指标都受应用所需通信的特征影响。被传送数据项的大小是最明显的一项：它不仅直接影响延迟和带宽，还影响不同延迟隐藏方法的有效性。同样，通信模式的规则程度影响命名和保护的成本，从而影响通信开销。一般来说，既能高效处理小规模也能处理大规模数据传送、既适应不规则也适应规则通信模式的机制，更灵活，也能在更广泛的应用中保持效率。当然，设计者考察任何通信机制时，都必须同时考虑成本与性能。

<!-- source: p1180 -->

## 不同通信机制的优势

大规模多处理器传送数据的两种主要方式是消息传递和共享内存。这两类通信机制各有优势。共享内存通信的优点包括：

- 与集中式多处理器中广为理解的机制兼容；这类机器都采用共享内存通信。OpenMP 联盟（说明见 [openmp.org](https://www.openmp.org/)）提出了共享内存多处理器的标准编程接口。消息传递也有标准，即 MPI（Message Passing Interface，消息传递接口），但原文所讨论的共享内存多处理器，以及面向吞吐量环境中的松耦合集群，并不采用这一标准。
- 当处理器间通信模式复杂，或在执行过程中动态变化时，更容易编程。同样的优势也简化了编译器设计。
- 可以用熟悉的共享内存模型开发应用，只把注意力集中在对性能至关重要的访问上。
- 传送小数据项时，通信开销更低，带宽利用更好。这源于通信的隐式性质，以及通过内存映射在硬件中实现保护，而不是通过 I/O 系统实现保护。
- 可以用硬件控制的缓存自动缓存全部共享和私有数据，从而降低远程通信频率。我们将看到，缓存同时降低共享数据访问的延迟和争用。这一优势也伴随一个缺点，下文会提到。

消息传递通信的主要优势包括：

- 硬件可以更简单，尤其是与能够一致地缓存远程数据、具有可扩展性的共享内存实现相比。
- 通信是显式的，因而更容易理解。在共享内存模型中，有时很难判断何时会发生通信、何时不会，以及通信的代价有多大。
- 显式通信将程序员的注意力引向并行计算中这个代价高昂的环节，有时能促使多处理器程序采用更好的结构。
- 同步自然地与消息发送联系在一起，减少了同步不正确引入错误的可能性。

<!-- source: p1181 -->

- 更容易采用由发送方发起的通信，这在性能上可能有一定优势。
- 如果通信较少、结构较规则，就更容易用类似事务的结构提高容错能力。此外，节点耦合较松、通信显式，也使故障隔离更加容易。
- 规模最大的多处理器采用集群结构，而这种结构本质上基于消息传递。使用两套通信模型可能引入不必要的复杂性。

当然，无论硬件支持哪一种机制，都可以在其上用软件建立所需的通信模型。在共享内存之上支持消息传递要容易得多：消息本质上是将数据从一处存储器送到另一处，因此可以通过从地址空间的一部分复制到另一部分来实现。主要困难在于，报文可能未对齐且长度任意，而存储系统通常以对齐的缓存块为传送单位。软件可以付出较小的性能代价克服这些困难；如果增加少量硬件支持，则基本可以不付出性能代价。

在消息传递硬件上高效支持共享内存就困难得多。没有显式的共享内存硬件支持时，每次共享内存访问都需要操作系统介入，提供地址转换、内存保护，并将访存转换为消息的发送和接收。加载、存储通常只移动少量数据，而软件处理这些通信的开销很高，严重限制了软件共享内存能够提供可接受性能的应用范围。原书因此指出，在商业系统中，用消息传递来实现共享内存一直没有成为实用方案。

> **译注：** 本节关于 MPI 使用范围及软件共享内存实用性的判断，保留原书所讨论系统和年代的语境，不应读作对所有实现的普遍限制。
