5

据我了解,对于 NUMA 系统的性能,有两种情况需要避免:

  1. 同一套接字中的线程写入同一高速缓存行(通常为 64 字节)
  2. 来自不同套接字的线程写入同一虚拟页面(通常为 4096 字节)

一个简单的例子会有所帮助。假设我有一个双插槽系统,每个插槽都有一个带有两个物理内核的 CPU(和两个逻辑内核,即每个模块没有 Intel 超线程或 AMD 两个内核)。让我借用OpenMP 上的图表:for schedule

| socket 0    | core 0 | thread 0 |
|             | core 1 | thread 1 |

| socket 1    | core 2 | thread 2 |
|             | core 3 | thread 3 |

因此,基于案例 1,最好避免线程 0 和线程 1 写入相同的缓存行,基于案例 2,最好避免线程 0 写入与线程 2 相同的虚拟页面。

但是,我被告知,在现代处理器上,第二种情况不再是问题。套接字之间的线程可以有效地写入相同的虚拟页面(只要它们不写入相同的缓存行)。

案例二不再是问题了吗?如果它仍然是一个问题,那么正确的术语是什么?将这两种情况称为一种虚假分享是否正确?

4

1 回答 1

2

关于案例 1,您是对的。关于案例 2 的更多详细信息:

根据操作系统的NUMA 策略和任何相关的迁移问题,线程 0 和 2 正在写入的页面的物理位置可能是套接字 0 或套接字 1。这些情况是对称的,所以假设有第一次接触策略,并且线程 0 最先到达那里。操作顺序可以是:

  1. 线程 0 分配页面。
  2. 线程 0 写入将要处理的缓存行。该缓存行在套接字 0 上的缓存中从无效转换为已修改。
  3. 线程 2 写入将要处理的缓存行。要将该行置于独占状态,套接字 1 必须向套接字 0 发送 Read For Ownership 并接收响应。
  4. 线程 0 和线程 2 可以继续他们的业务。只要线程 0 不接触线程 2 的缓存行,反之亦然,并且没有其他人做任何会改变任一行状态的事情,线程 0 和线程 2 正在执行的所有操作都是套接字(可能是内核)本地的.

您可以在不影响结果的情况下交换 2. 和 3. 的顺序。无论哪种方式,步骤 3 中套接字之间的往返都将比步骤 2 中的套接字本地访问花费更长的时间,但是每次线程 2 需要将其线路置于修改状态时,只会产生一次成本。如果在该缓存行的状态转换之间继续执行足够长的时间,则额外的成本将摊销。

于 2014-05-16T22:33:24.630 回答