NUMA系统,虚拟页面和虚假共享

Z b*_*son 5 parallel-processing multithreading openmp numa

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

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

一个简单的例子会有帮助.假设我有一个双插槽系统,每个插槽都有一个带有两个物理内核的CPU(和两个逻辑内核,即每个模块没有Intel超线程或AMD两个内核).让我借一下OpenMP的数据:按计划进行

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

| socket 1    | core 2 | thread 2 |
|             | core 3 | thread 3 |
Run Code Online (Sandbox Code Playgroud)

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

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

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

Aar*_*man 2

您对案例 1 的看法是正确的。有关案例 2 的更多详细信息:

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

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

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