5.2.操作系统对 NUMA 的支援

为了支援 NUMA 机器,操作系统必须将memory分散式的性质纳入考量。举例来说,若是一个行程执行在一个给定的处理器上,被指派给行程定址空间的实体 RAM 理想上应该要来自本地memory。否则每条指令都必须为了程序码与资料去存取远端的memory。有些仅存于 NUMA 机器的特殊情况要被考虑进去。DSO 的文字区段(text segment)在一台机器的实体 RAM 中通常正好出现一次。但若是 DSO 被所有 CPU 上的行程与执行绪用到(例如,像 libc 这类基本的执行期函式库),这表示并非一些、而是全部的处理器都必须拥有远端的地址。操作系统理想上会将这种 DSO「映像(mirror)」到每个处理器的实体 RAM 中,并使用本地的副本。这并非一种最佳化,而是个必要条件,而且通常难以实作。它可能没有被支援、或者仅以有限的形式支援。

为了避免情况变得更糟,操作系统不该将一个行程或执行绪从一个节点迁移到另一个。操作系统应该已经试著避免在一般的多处理器机器上迁移行程,因为从一个处理器迁移到另一个处理器意味著cache内容遗失。若是负载分配需要将一个行程或执行绪迁出一个处理器,操作系统通常能够挑选任一个拥有足够剩馀容量的新处理器。在 NUMA 环境中,新处理器的选择受到稍微多一些的限制。对于行程正在使用的memory,新选择的处理器不该有比旧的处理器还高的存取成本;这限制目标的清单。若是没有符合可用标准的空閒处理器,操作系统除了迁移到memory存取更为昂贵的处理器以外别无他选。

在这种情况下,有两种可能的方法。首先,可以期盼这种情况是暂时的,而且行程能够被迁回到一个更合适的处理器上。或者,操作系统也能够将行程的memory迁移到更靠近新使用的处理器的实体分页上。这是个相当昂贵的操作。可能得要复制大量的memory,尽管不必在一个步骤中完成。当发生这种情况的时候,行程必须 –– 至少短暂地 –– 中止,以正确地迁移对旧分页的修改。有了让分页迁移高效又快速,有整整一串其它的必要条件。简而言之,操作系统应该避免它,除非它是真的有必要的。

一般来说,不能够假设在一台 NUMA 机器上的所有行程都使用等量的memory,使得 –– 由于遍及各个处理器的行程的分布 –– memory的使用也会被均等地分配。事实上,除非执行在机器上的应用程序非常特殊(在 HPC 世界中很常见,但除此之外则否),不然memory的使用是非常不均等的。某些应用程序会使用巨量的memory,其余的几乎不用。若总是分配产生请求的处理器本地的memory,这将会 –– 或早或晚 –– 造成问题。系统最终将会耗尽执行大行程的节点本地的memory。

为了应对这些严重的问题,memory –– 预设情况下 –– 不会只分配给本地的节点。为了利用所有系统的memory,预设策略是条带化(stripe)memory。这保证所有系统memory的同等使用。作为一个副作用,有可能变得能在处理器之间自由迁移行程,因为 –– 平均而言 –– 对于所有用到的memory的存取成本没有改变。由于很小的 NUMA 因子,条带化是可以接受的,但仍不是最好的(见 5.4 节的数据)。

这是个帮助系统避免严重问题、并在普通操作下更为能够预测的劣化(pessimization)。但它降低整体的系统效能,在某些情况下尤为显著。这即是 Linux 允许每个行程选择memory分配规则的原因。一个行程能够为它自己以及它的子行程选择不同的策略。我们将会在第六节介绍能用于此的介面。

results matching ""

    No results matching ""