内存管理之NUMA与CPU

NUMA与CPU之间的关系,如系统中有2个CPU(可以超过2个CPU)时, NUMA内存访问模型

mmu_numa_cpu

平台:arm64
kernel:linux4.4

NUMA(Non Uniform Memory Access)

NUMA和SMP是两种CPU相关的硬件架构。在SMP架构里面,所有的CPU争用一个总线来访问所有内存,优点是资源共享,而缺点是总线争用激烈。随着PC服务器上的CPU数量变多(不仅仅是CPU核数),总线争用的弊端慢慢越来越明显,于是Intel在Nehalem CPU上推出了NUMA架构,而AMD也推出了基于相同架构的Opteron CPU。

NUMA最大的特点是引入了node和distance的概念。对于CPU和内存这两种最宝贵的硬件资源,NUMA用近乎严格的方式划分了所属的资源组(node),而每个资源组内的CPU和内存是几乎相等。资源组的数量取决于物理CPU的个数(现有的PC server大多数有两个物理CPU,每个CPU有4个核);distance这个概念是用来定义各个node之间调用资源的开销,为资源调度优化算法提供数据支持。

mmu_numa_intel_access

  • 查看NUMA相关情况
    1
    #numactl  --show

    ARM64内存在管理相当于单个node

mmu_one_node

1
2
3
4
5
On node 0 totalpages: 524288
DMA zone: 8192 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 524288 pages, LIFO batch:31
...

内核启动部分打印

node的初始化

在内核启动时进行初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
start_kernel
\->setup_arch //不同的CPU对node的使用不同
\->paging_init
\->bootmem_init
\->zone_sizes_init(arch/arm64/mm/minit.c)
\->free_area_init_node(nid=0, ...)
{
pg_data_t *pgdat = NODE_DATA(nid);

calculate_node_totalpages(pgdat, start_pfn, end_pfn,
zones_size, zholes_size);
alloc_node_mem_map(pgdat);
}

物理内存与node之间的关系

numa编码

将当前进程绑定到node0或node1,及在当前node上的CPU运行与申请内存

1
2
3
4
5
6
7
8
9
10
11
12
static int set_numa_node(int node)
{
struct bitmask *bit;

bit = numa_bitmask_alloc(1);
numa_bitmask_clearall(bit);
numa_bitmask_setbit(bit, node);
numa_bind(bit); //将当前任务及其子任务绑定到nodemask中指定的节点。它们只会在指定节点的CPU上运行,并且只能从它们分配内存。
numa_bitmask_free(bit);

return 0;
}

numa_bind() binds the current task and its children to the nodes specified in nodemask. They will only run on the CPUs of the specified nodes and only be able to allocate memory from them. This function is equivalent to calling numa_run_on_node_mask(nodemask) followed by numa_set_membind(nodemask). If tasks should be bound to individual CPUs inside nodes consider using numa_node_to_cpus and the sched_setaffinity(2) syscall.

参考

  • NUMA的取舍与优化设置