numa
NUMA(Non-Uniform Memory Access,非统一内存访问)是一种计算机内存架构,广泛应用于多处理器系统(如服务器和高性能计算系统),用于提高系统性能。
NUMA 的基本概念
在 NUMA 架构中,每个 CPU(或 CPU 核心)都有直接连接的本地内存(local memory)。
- 本地内存访问:CPU 访问自己本地内存时,延迟低,性能高。
- 远程内存访问:CPU 需要通过其他 CPU 的互连(Interconnect)访问远程内存,延迟较高,性能较低。
与传统的 UMA(Uniform Memory Access,统一内存访问) 相比,NUMA 的特点是内存访问的延迟和带宽不统一,依赖于内存的物理位置。
NUMA 的核心组成
- NUMA 节点(Node):
- 每个节点包含一组 CPU 和直接连接的内存。
- CPU 在其节点的内存访问速度更快,访问其他节点的内存速度较慢。
- CPU 间互连(Interconnect):
- 用于连接不同 NUMA 节点,允许跨节点共享内存。
- 常见技术:Intel QPI、AMD Infinity Fabric。
- 本地与远程内存:
- 本地内存:CPU 节点直接连接的内存。
- 远程内存:通过互连访问的其他节点的内存。
NUMA 的优点
- 提高内存访问性能:
- 通过尽量使用本地内存,减少访问远程内存的频率,优化延迟。
- 扩展性强:
- 系统可以增加更多的 NUMA 节点,而不会因共享总线的瓶颈而显著降低性能。
NUMA 的挑战
- 远程访问开销高:
- 远程内存访问的延迟和带宽会显著影响性能。
- 需要软件优化:
- 操作系统、数据库、虚拟机等需要针对 NUMA 架构进行优化(如合理的任务调度和内存分配)。
- 复杂性:
- 开发者需要考虑内存和任务的绑定策略。
NUMA 的典型应用
- 服务器和数据中心:
- 例如数据库(如 MySQL、PostgreSQL)、虚拟化平台(如 VMware、KVM)。
- 高性能计算(HPC):
- 科学计算和工程仿真等任务需要高效的内存使用。
- 多核 CPU 环境:
- 提高多线程程序的内存访问效率。
与 NUMA 相关的工具
numactl
:- 控制进程运行在哪个 NUMA 节点,指定内存分配策略。
numastat
:- 查看 NUMA 节点的内存使用情况。
- Linux 内核的 NUMA 支持:
- 如自动内存分配优化(Transparent Huge Pages 和 AutoNUMA)。
NUMA 系统示例
假设一个 NUMA 系统有两个节点:
- 节点 0:CPU 0-31,内存 128 GB。
- 节点 1:CPU 32-63,内存 128 GB。
CPU 0 访问节点 0 的内存延迟为 10,访问节点 1 的内存延迟为 20。合理分配任务和内存可以极大提升性能,比如将需要大量内存的任务绑定到节点 0 的 CPU 和内存。
[root@ ~]# numactl --hardware
available: 2 nodes (0-1) # 系统中有 2 个 NUMA 节点,编号分别为 0 和 1
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # NUMA 节点 0 包含 CPU 核心编号为 0 到 31 的处理器核心
node 0 size: 388457 MB # NUMA 节点 0 的总物理内存大小为 388457 MB(约 379 GB)
node 0 free: 178917 MB # NUMA 节点 0 当前未分配的内存大小为 178917 MB(约 174 GB)
node 1 cpus: 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 # NUMA 节点 1 包含 CPU 核心编号为 32 到 63 的处理器核心
node 1 size: 389212 MB # NUMA 节点 1 的总物理内存大小为 389212 MB(约 380 GB)
node 1 free: 178121 MB # NUMA 节点 1 当前未分配的内存大小为 178121 MB(约 173 GB)
node distances: # 显示不同 NUMA 节点之间的内存访问延迟
node 0 1 # 表示节点编号
0: 10 15 # 节点 0 访问自身内存的延迟为 10,访问节点 1 内存的延迟为 15
1: 15 10 # 节点 1 访问节点 0 内存的延迟为 15,访问自身内存的延迟为 10
numactl
numactl
是一个用于管理和优化 NUMA(非统一内存访问架构)系统性能的工具。NUMA 是一种内存架构,在这种架构中,每个 CPU 都有自己直接连接的本地内存,同时也可以访问其他 CPU 的内存(称为远程内存),但远程内存的访问延迟通常比本地内存高。
numactl
的主要功能:
-
绑定进程到特定的 CPU 或内存节点:
-
可以将进程或线程绑定到特定的 NUMA 节点上的 CPU 或内存,以减少远程内存访问的开销,从而提升性能。
-
示例:
numactl --cpunodebind=0 --membind=0 myprogram
上述命令将
myprogram
绑定到 NUMA 节点 0 的 CPU 和内存上。 -
指定内存分配策略:
-
控制进程如何分配内存,例如优先使用本地内存、跨节点分配内存等。
-
常见策略:
--membind
: 将内存分配绑定到特定 NUMA 节点。--interleave
: 让内存分配在多个节点之间交错分布,适合需要均匀分布内存负载的场景。--localalloc
: 优先分配本地内存。
-
示例:
numactl --interleave=all myprogram
上述命令将
myprogram
的内存分配在所有 NUMA 节点之间交错分布。 -
查询 NUMA 系统信息:
-
使用
numactl --hardware
可以查看当前系统的 NUMA 拓扑信息,包括节点数、每个节点的内存大小和 CPU 分布等。 -
示例:
numactl --hardware
-
提高性能:
-
在多核、多内存节点的系统中,合理使用
numactl
可以显著降低内存访问延迟,提高应用的吞吐量和性能。
常用选项:
-
--cpunodebind=<nodes>
: 绑定进程到指定的 CPU 节点。 -
--membind=<nodes>
: 将进程的内存绑定到指定的 NUMA 节点。 -
--interleave=<nodes>
: 在指定节点间交错分配内存。 -
--localalloc
: 仅分配本地内存。
使用场景:
- 高性能计算:减少跨 NUMA 节点的内存访问,优化计算密集型任务的性能。
- 数据库应用:绑定数据库实例到特定节点,降低内存和 CPU 的争用。
- 容器部署:在多 NUMA 节点的机器上合理分配资源,提高容器性能。
如果你的应用对延迟敏感或运行在多 NUMA 节点的服务器上,了解和使用 numactl
是非常有价值的。