我试图理解这是什么node distances意思numactl --hardware?
在我们的集群上,它输出以下内容
numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17
node 0 size: 32143 MB
node 0 free: 188 MB
node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23
node 1 size: 32254 MB
node 1 free: 69 MB
node distances:
node 0 1
0: 10 21
1: 21 10
到目前为止,这是我的理解:
考虑以下场景:在 NUMA 计算机上运行的用户进程调用 mmap 在虚拟地址空间中创建新映射。然后它使用 mmap 返回的内存进行处理(存储其数据,...)。现在由于某些原因,用户进程被调度到不同的NUMA节点。用户进程是否可以告诉操作系统在保留数据的同时重新定位已映射的内存(到不同的 NUMA 节点)?
我正在使用为以下问题提供的代码numa+mbind+segfault,每次调用 mbind 都会返回 EINVAL。我怎样才能得到什么是完全错误的?我问这个是因为 EINVAL 可以出于多种原因返回。
page_size = sysconf(_SC_PAGESIZE);
objs_per_page = page_size/sizeof(A[0]);
assert(page_size%sizeof(A[0])==0);
split_three=num_items/3;
aligned_size=(split_three/objs_per_page)*objs_per_page;
remnant=num_items-(aligned_size*3);
piece = aligned_size;
nodemask=1;
mbind(&A[0],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
nodemask=2;
mbind(&A[aligned_size],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
nodemask=4;
bind(&A[aligned_size*2+remnant],piece*sizeof(double),MPOL_BIND,
&nodemask,64,MPOL_MF_MOVE);
Run Code Online (Sandbox Code Playgroud)
运行程序后(通过将每个 mbind 调用之前的节点掩码分别更改为 1,2 和 4)如下所示(作为 Mats Petersson 的回答)。它有时会出现段错误,有时运行良好。当它出现段错误时,dmesg 如下:
Stack:
Call Trace:
mpol_new+0x5d/0xb0
sys_mbind+0x125/0x4f0
finish_task_switch+0x4a/0xf0
? __schedule+0x3cf/0x7c0
system_call_fastpath+0x16/0x1b
Code: ...
kmem_cache_alloc+0x58/0x130
Run Code Online (Sandbox Code Playgroud) 据我所知,对于NUMA系统的性能,有两种情况需要避免:
一个简单的例子会有帮助.假设我有一个双插槽系统,每个插槽都有一个带有两个物理内核的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相同的虚拟页面.
但是,我被告知在现代处理器上,第二种情况不再是一个问题.套接字之间的线程可以有效地写入同一个虚拟页面(只要它们不写入同一个缓存行).
案例二不再是问题吗?如果仍然存在问题,那么正确的术语是什么?将这两种情况称为虚假共享是否正确?
我正在开发一个有两个内存节点的 NUMA 服务器。
我想创建一个将加载到主内存中的文件系统,例如 tmpfs 或 ramfs,并且我想将其绑定到特定的内存节点。换句话说,我不希望 ramfs 内容在两个内存节点上交错。
那么我怎样才能实现这一目标呢?
我尝试了带有 --file 选项的 numactl 命令,但它似乎只适用于单个文件(我需要加载一个目录)。
谢谢
我目前正在尝试在 Maestro 处理器上使用 OpenMP 加速简单的矩阵减法基准测试,该处理器具有 NUMA 架构并基于 Tilera Tile64 处理器。Maestro 主板有 49 个处理器,以 7x7 配置排列成二维阵列。每个核心都有自己的 L1 和 L2 缓存。可以在此处查看电路板的布局:https ://i.stack.imgur.com/RG0fC.png
我对编写“NUMA 感知”应用程序的想法很陌生,但我读到的主要共识是数据局部性是最大化性能的重要组成部分。在核心之间并行化代码时,我应该尽可能将数据保留在执行处理的线程本地使用。
对于这个矩阵减法基准(C[i] = A[i] - B[i]),我认为最好为每个线程分配自己的私有 A、B 和 C 数组,其大小为总大小工作大小除以线程数。例如,如果数组的总大小为 6000*6000,并且我尝试在 20 个线程上并行化它,我将分配大小为 (6000*6000)/20 的私有数组。每个线程都会对其自己的私有数组执行此减法,然后我会将结果收集回总大小为 6000*6000 的最终数组中。例如(无需将每个线程的结果收集到最终数组中):
int threads = 20;
int size = 6000;
uint8_t *C_final = malloc(sizeof(uint8_t)*(size*size));
#pragma omp parallel num_threads(threads) private(j)
{
uint8_t *A_priv = malloc(sizeof(uint8_t)*((size*size)/threads));
uint8_t *B_priv = malloc(sizeof(uint8_t)*((size*size)/threads));
uint8_t *C_priv = malloc(sizeof(uint8_t)*((size*size)/threads));
for(j=0; j<((size*size)/threads); j++)
{
A_priv[j]=100;
B_priv[j]=omp_get_thread_num();
C_priv[j]=0;
}
for(j=0; j<((size*size)/threads); j++) …Run Code Online (Sandbox Code Playgroud) MPI-3 标准引入了共享内存,共享该内存的所有进程都可以读取和写入该内存,而无需调用 MPI 库。虽然有使用共享或非共享内存的单方面通信的示例,但我没有找到太多有关如何通过直接访问正确使用共享内存的信息。
我最终做了这样的事情,效果很好,但我想知道 MPI 标准是否保证它总是有效?
// initialization:
MPI_Comm comm_shared;
MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, i_mpi, MPI_INFO_NULL, &comm_shared);
// allocation
const int N_WIN=10;
const int mem_size = 1000*1000;
double* mem[10];
MPI_Win win[N_WIN];
for (int i=0; i<N_WIN; i++) { // I need several buffers.
MPI_Win_allocate_shared( mem_size, sizeof(double), MPI_INFO_NULL, comm_shared, &mem[i], &win[i] );
MPI_Win_lock_all(0, win);
}
while(1) {
MPI_Barrier(comm_shared);
... // write anywhere on shared memory
MPI_Barrier(comm_shared);
... // read on shared memory written by other processes
}
// deallocation
for (int i=0; i<N_WIN; …Run Code Online (Sandbox Code Playgroud) Linux 可以同时拥有标准 4KiB 页面内存和 1GiB(巨大)页面内存(以及 2MiB 页面,但我不知道是否有人使用它)。
是否有从任意虚拟地址获取页面大小的标准调用?指针可能指向 4K 页或大页。
手头的问题是对assert(...)需要基地址和区域大小必须是页面大小的倍数的函数的参数进行健全 ( ) 检查,然后传递给mbind. 但是页面大小因系统而异。如果没有健全性检查,mbind只给出的返回值Invalid argument对调试没有帮助。
我看过这个答案How to get linux kernel page size programmatically但它给出的答案假设整个系统是相同的,而且它们也是编译时常量。也getpagesize()做同样的事情,无论如何它都被弃用了。
在Intel发布的技术概述中,“Sub-NUMA Clustering”和“Hemisphere and Quadrant Modes”分别进行了描述。但它们之间的主要区别尚不清楚。
在这个答案中,它说“在象限或半球模式内,与 SNC 完成相同的 LLC 映射,但它公开为一个 numa 域和一个物理内存映射。”
在Intel 64和IA-re架构优化参考手册中,第10章仅描述了“Sub-NUMA Clustering”,没有提及“半球和象限模式”。
在本文档中,“半球和象限模式”被归为“基于UMA的聚类”并与SNC冲突。
我是不是可以这样理解:对于CPU端和LLC行为端来说,这两种模式是完全一样的,除了暴露给操作系统的NUMA节点数量不同之外。