c++ - NUMA:如何检查分配了 C++ 数组的 RAM 的哪一部分?

标签 c++ multithreading virtual-memory numa

我的服务器有 2 个 CPU 和 64GB RAM,每个 CPU 32GB。

我知道每个 CPU 都有自己的 RAM 部分,我们称它们为 RAM1 和 RAM2。我想让我的程序知道它在哪个 RAM(RAM1 或 RAM2)上分配数据。

我尝试检查指针值:

  // put the thread at i-th CPU, using pthread_setaffinity_np
TData *a = new TData[N];
...
cout << "CPU = " << i << " adress = " << a << endl; 

但输出看起来是随机的。我想那是因为地址是虚拟的。虚拟内存地址和部分RAM有对应关系吗?

如何检查我的数组“a”分配在哪个 RAM 中?

最佳答案

您的问题已得到解答here .我只想添加一些评论。

请注意,调用 new [] 并不会实际分配物理内存。在现代操作系统上,这只会导致匿名内存映射开始。匿名映射不对应于文件系统中的文件,而是由交换(如果有)支持。最初,整个区域指向内核中包含全零的只读页面。只有当您实际写入新分配的内存时,才会安装一个新的内存页面,它会替换访问地址所在页面范围的零页面。这就是为什么我们说零页是写时复制(或 CoW)映射到进程的虚拟地址空间的原因。默认策略是尝试在访问内存区域的线程运行的同一 NUMA 节点上分配新页面。这称为“首次接触”NUMA 策略。如果该 NUMA 节点上没有足够的内存,则该页面会分配到其他具有足够空闲内存的节点上。小分配也有可能在更大的区域(称为竞技场)内结束,由 C 库内存分配器 malloc()(C++ 运算符 new [] 管理)调用 malloc() 以进行实际的内存分配)。在这种情况下,页面可能已经存在于物理内存中,甚至在您写入新分配的内存之前。

Linux 有一个坏习惯,在交换时不保留内存区域的 NUMA 关联。也就是说,如果在 NUMA 节点 0 上分配了一个页面,然后换出然后换回,则无法保证该页面不会被放置在 NUMA 节点 1 上。这就产生了“我的内存分配在哪里”的问题有点棘手,因为连续换出然后换入很容易使您在几分之一秒前从 move_pages() 获得的结果无效。因此,该问题仅在以下两种特殊情况下才有意义:

  • 您显式锁定了内存区域:可以使用 mlock(2) 系统调用来告诉操作系统不要交换进程虚拟的特定范围地址空间;
  • 您的系统没有事件的交换区:这会阻止操作系统将页面移出和移回主内存。

关于c++ - NUMA:如何检查分配了 C++ 数组的 RAM 的哪一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19813681/

相关文章:

c++ - 我怎样才能得到一个vector::value_type的sizeof?

c++ - 从 C++ 使用 tar 创建压缩文件

c++ - 使用 SAPI.H - 为什么我的程序只说第一个词?

iphone - glGenTextures 在后台线程中返回零

Java:根据参数值选择性同步方法

c++ - 在线程之间发送字符串数据 (Win32)

linux - 什么时候将虚拟地址分配给程序/进程?

c++ - 递归加法序列C++

ios - 如何找到 EXC_BAD_ACCESS 异常的地址?

java - ULIMIT:如何永久设置限制