Skip to main content

背景与价值

AI模型开发、训练和推理业务场景下,CPU亲和性与NUMA亲和性调度至关重要。现代服务器通常采用多Socket、多NUMA节点的架构,GPU等加速设备通过PCIe连接到特定的NUMA节点。如果CPU内存GPU分配在不同的NUMA节点上,数据访问将产生跨NUMA的内存延迟,显著降低训练和推理性能。通过合理配置CPU亲和性和NUMA亲和性,可以确保计算资源(CPU)、内存和加速设备(GPU)在同一NUMA节点内协同工作,最大化数据局部性,减少跨节点通信开销,从而提升AI工作负载的整体性能。

以典型的8GPU服务器为例,其拓扑结构如下:

        GPU0    GPU1    GPU2    GPU3    GPU4    GPU5    GPU6    GPU7    CPU Affinity    NUMA Affinity
GPU0 X PIX NODE NODE SYS SYS SYS SYS 0-31,64-95 0
GPU1 PIX X NODE NODE SYS SYS SYS SYS 0-31,64-95 0
GPU2 NODE NODE X PIX SYS SYS SYS SYS 0-31,64-95 0
GPU3 NODE NODE PIX X SYS SYS SYS SYS 0-31,64-95 0
GPU4 SYS SYS SYS SYS X PIX NODE NODE 32-63,96-127 1
GPU5 SYS SYS SYS SYS PIX X NODE NODE 32-63,96-127 1
GPU6 SYS SYS SYS SYS NODE NODE X PIX 32-63,96-127 1
GPU7 SYS SYS SYS SYS NODE NODE PIX X 32-63,96-127 1

可以看到:

  • GPU 0-3连接到NUMA 0,对应CPU 0-31, 64-95
  • GPU 4-7连接到NUMA 1,对应CPU 32-63, 96-127

通过KubernetesNUMA亲和性调度,可以确保使用GPU 0-3Pod被分配到NUMA 0对应的CPU核心上。

Kubernetes NUMA 亲和性关键组件

Kubernetes通过kubelet中的多个Manager组件协同工作来实现NUMA亲和性调度:

  ┌─────────────────────────────────────────────────────────────┐
│ Topology Manager │
└─────────────────────────────────────────────────────────────┘
↑ ↑ ↑
│ │ │
┌────────┴────────┐ ┌───────┴────────┐ ┌───────┴────────┐
│ CPU Manager │ │ Memory Manager │ │ Device Manager │
└─────────────────┘ └────────────────┘ └────────────────┘

组件功能概述

组件功能说明
CPU ManagerCPU亲和性管理Guaranteed QoS Pod分配独占CPU核心,提供CPU级别的拓扑提示
Memory Manager内存NUMA亲和性Pod分配特定NUMA节点的内存,确保内存访问本地化
Device Manager设备亲和性管理GPU等设备的分配,提供设备所在NUMA节点的拓扑提示
Topology Manager拓扑协调中心收集各Manager的拓扑提示,根据策略决定资源分配和Pod准入

工作流程

  1. Pod被调度到节点后,kubeletTopology Manager开始协调资源分配
  2. Manager作为Hint Provider,向Topology Manager提供拓扑亲和性提示(Hints
  3. Topology Manager根据配置的策略合并这些Hints,计算最优的NUMA节点分配
  4. 根据策略决定Pod的准入或拒绝
  5. 准入后,各Manager根据拓扑提示分配对应NUMA节点上的资源

关键组件配置详解

以下是启用CPU亲和性和NUMA亲和性调度的完整kubelet配置示例,该配置通常位于宿主机上的/var/lib/kubelet/config.yaml。随后我们会详细介绍每个组件的配置项:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration

# ============= CPU Manager 配置 =============
cpuManagerPolicy: static # 启用静态CPU管理策略
cpuManagerReconcilePeriod: 10s # 调和周期
cpuManagerPolicyOptions:
full-pcpus-only: "true" # 仅分配完整物理核心
distribute-cpus-across-numa: "true" # 跨NUMA均匀分配(可选)

# ============= Topology Manager 配置 =============
topologyManagerPolicy: restricted # 严格要求NUMA对齐
topologyManagerScope: pod # Pod级别对齐
topologyManagerPolicyOptions:
prefer-closest-numa-nodes: "true" # 优先选择距离最近的NUMA节点

# ============= Memory Manager 配置 =============
memoryManagerPolicy: Static # 启用静态内存管理策略
reservedMemory:
- numaNode: 0
limits:
memory: 2Gi # NUMA 0 预留内存
- numaNode: 1
limits:
memory: 2Gi # NUMA 1 预留内存

# ============= 资源预留配置 =============
kubeReserved:
cpu: "2"
memory: 2Gi
systemReserved:
cpu: "2"
memory: 2Gi
reservedSystemCPUs: "0-3" # 预留CPU 0-3给系统

# ============= 驱逐配置 =============
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
imagefs.available: "15%"

# ============= Feature Gates(可选)=============
featureGates:
CPUManagerPolicyOptions: true
CPUManagerPolicyBetaOptions: true
TopologyManagerPolicyOptions: true

CPU Manager

CPU Manager负责为Guaranteed QoSPod分配独占CPU核心,避免CPU资源竞争带来的性能抖动。

实现原理

  1. 共享池管理CPU Manager维护一个共享CPU池,初始包含节点所有CPU(除预留CPU外)
  2. 独占分配:对于Guaranteed QoSCPU请求为整数的容器,从共享池中分配独占CPU
  3. 亲和性设置:通过Linux cgroupscpuset将容器绑定到特定CPU核心
  4. 状态持久化:分配状态存储在/var/lib/kubelet/cpu_manager_state文件中

前置配置要求

前置要求说明
静态策略前提使用static策略时,必须配置CPU预留(kubeReservedsystemReservedreservedSystemCPUs中至少一个大于0
QoS要求只有Guaranteed QoSPod才能获得独占CPU
CPU请求要求CPUrequestslimits必须相等,且为整数

配置示例

# ============= CPU Manager 配置 =============
cpuManagerPolicy: static # 启用静态CPU管理策略
cpuManagerReconcilePeriod: 10s # 调和周期
cpuManagerPolicyOptions:
full-pcpus-only: "true" # 仅分配完整物理核心
distribute-cpus-across-numa: "true" # 跨NUMA均匀分配(可选)

# ============= 资源预留配置 =============
kubeReserved:
cpu: "2"
memory: 2Gi
systemReserved:
cpu: "2"
memory: 2Gi
reservedSystemCPUs: "0-3" # 预留CPU 0-3给系统

配置参数

参数名称可选值默认值是否必须说明
cpuManagerPolicynone, staticnoneCPU管理策略。none不提供亲和性;staticGuaranteed Pod分配独占CPU
cpuManagerReconcilePeriodDuration10sCPU Manager调和周期,定期检查并修正CPU分配
cpuManagerPolicyOptionsMapnil策略选项,用于精细调整static策略行为
reservedSystemCPUsCPU列表""static策略时必须为系统进程预留的CPU列表,如0-3,8-11

cpuManagerPolicyOptions(策略选项)

选项名称版本要求说明
full-pcpus-onlyv1.22+ (GA: v1.33+)仅分配完整物理核心:启用后,CPU Manager只会为容器分配完整的物理核心,而不会分配单个硬件线程(超线程)。这可以有效避免SMTSimultaneous Multithreading,超线程)带来的"吵闹邻居"问题,即多个进程共享同一物理核心的执行单元导致的性能干扰。对于CPU密集型和延迟敏感的AI训练任务,建议启用此选项以获得更稳定的性能表现。例如,在开启超线程的64核服务器上(128个逻辑核心),启用此选项后容器最多只能获得64个完整物理核心
distribute-cpus-across-numav1.23+跨NUMA均匀分配CPU:当容器请求多个CPU核心时,CPU Manager会尽可能将这些核心均匀分配到多个NUMA节点上,而不是集中在单个NUMA节点。这种策略适合能够感知NUMA拓扑并进行并行计算的应用程序,可以充分利用多NUMA节点的内存带宽。但需要注意,此选项可能会增加跨NUMA内存访问的开销,不适合需要严格NUMA局部性的场景。通常与Topology Managerbest-effort策略配合使用
align-by-socketv1.25+按Socket对齐:在多Socket服务器上,优先在物理Socket边界对齐CPU分配,而非逻辑NUMA边界。在某些服务器架构中,一个Socket可能包含多个NUMA节点,此选项会尝试将容器的所有CPU分配在同一个物理Socket上,以减少跨Socket通信延迟。这对于需要频繁CPU间通信的应用(如共享L3 Cache)有性能优势。注意:此选项为Alpha特性,默认隐藏,需要启用CPUManagerPolicyAlphaOptions Feature Gate
distribute-cpus-across-coresv1.31+跨物理核心分配虚拟核心:将虚拟核心(有时称为硬件线程)分配到不同的物理核心上,而不是集中在少数物理核心的多个硬件线程上。这样可以减少同一物理核心内多个线程之间的资源竞争(如执行单元、缓存冲突),提升整体吞吐量。例如,请求4CPU时,会分配4个不同物理核心的单个线程,而不是2个物理核心的4个线程。注意:此选项为Alpha特性,默认隐藏,需要启用CPUManagerPolicyAlphaOptions Feature Gate
strict-cpu-reservationv1.32+ (GA: v1.35+)严格CPU预留:启用后,会严格隔离通过reservedSystemCPUs预留的CPU核心,确保任何Pod(包括BestEffortBurstableGuaranteed QoS)都无法使用这些预留的CPU。未启用时,预留的CPU仅对Guaranteed QoS的独占分配有效,BestEffortBurstable Pod仍可能调度到这些核心上。对于需要为系统关键进程(如kubelet、容器运行时、系统守护进程)保证稳定CPU资源的生产环境,强烈建议启用此选项,避免节点过载导致的稳定性问题
prefer-align-cpus-by-uncorecachev1.32+优先按Uncore Cache对齐Uncore Cache通常指Last Level Cache(LLC,最后级缓存),它在多个CPU核心之间共享。启用此选项后,CPU Manager会尽最大努力将容器的所有CPU核心分配到共享同一LLC的核心组中。这可以显著提高缓存命中率,减少内存访问延迟,对于数据局部性要求高的应用(如AI推理服务、数据库)有明显性能提升。在现代服务器架构中,通常一个NUMA节点内的核心共享一个LLC,因此此选项与NUMA亲和性策略配合效果更佳

Topology Manager

Topology ManagerNUMA亲和性的核心协调器,负责收集各Manager的拓扑提示并做出准入决策。

实现原理

  1. Hint收集:从CPU ManagerMemory ManagerDevice Manager收集拓扑亲和性Hints
  2. Hint合并:根据配置的策略合并所有Hints,找出满足所有资源需求的最优NUMA节点组合
  3. 准入决策:根据策略决定是否允许Pod在该节点运行
  4. 资源协调:通知各Manager按照合并后的NUMA节点分配资源

配置示例

topologyManagerPolicy: restricted           # 严格要求NUMA对齐
topologyManagerScope: pod # Pod级别对齐
topologyManagerPolicyOptions:
prefer-closest-numa-nodes: "true" # 优先选择距离最近的NUMA节点

配置参数

参数名称可选值默认值是否必须说明
topologyManagerPolicynone, best-effort, restricted, single-numa-nodenone是(启用NUMA亲和性时)拓扑管理策略,决定NUMA对齐的严格程度
topologyManagerScopecontainer, podcontainer拓扑管理的作用范围
topologyManagerPolicyOptionsMapnil策略选项,用于精细调整策略行为

topologyManagerPolicy 详解

Policy说明适用场景
none不执行任何拓扑对齐,不影响资源分配默认行为,不需要NUMA亲和性
best-effort优先选择NUMA对齐,但不强制。即使没有最优NUMA对齐,Pod也会被准入希望NUMA对齐但允许降级
restricted仅允许NUMA对齐的Pod准入。如果无法满足最优对齐,Pod被拒绝推荐用于AI训练/推理场景
single-numa-node仅允许所有资源都在同一个NUMA节点Pod准入延迟极度敏感的工作负载

topologyManagerScope 详解

Scope说明特点
container在每个容器级别进行资源对齐同一Pod的不同容器可能分配到不同NUMA节点
podPod级别进行资源对齐推荐:所有容器分配到相同的NUMA节点集合,适合需要进程间通信的应用

topologyManagerPolicyOptions(策略选项)

选项名称说明
prefer-closest-numa-nodes优先选择距离最近的NUMA节点集合,减少跨NUMA通信延迟
max-allowable-numa-nodes允许超过8NUMA节点的系统启用Topology Manager(默认限制8个)

Memory Manager

Memory Manager负责为Pod分配特定NUMA节点的内存,确保内存访问本地化。

实现原理

  1. 内存计数:跟踪每个NUMA节点的可用内存和已分配内存
  2. NUMA感知分配:根据Topology Manager的决策,从指定NUMA节点分配内存
  3. Hint提供:向Topology Manager提供内存的NUMA亲和性提示
  4. 状态持久化:分配状态存储在/var/lib/kubelet/memory_manager_state文件中

配置示例

memoryManagerPolicy: Static                 # 启用静态内存管理策略
reservedMemory:
- numaNode: 0
limits:
memory: 2Gi # NUMA 0 预留内存
- numaNode: 1
limits:
memory: 2Gi # NUMA 1 预留内存

配置参数

参数名称可选值默认值是否必须说明
memoryManagerPolicyNone, StaticNone内存管理策略。StaticGuaranteed Pod提供内存NUMA亲和性
reservedMemoryMemoryReservation列表nilStatic策略时必须每个NUMA节点预留的内存量

Reserved Memory 配置

使用Static策略时,必须配置每个NUMA节点预留的内存,且需满足:

sum(reserved-memory) = kube-reserved + system-reserved + eviction-hard

其中:

  • kube-reserved:为Kubernetes系统组件(如kubelet、容器运行时)预留的资源
  • system-reserved:为操作系统守护进程(如sshdsystemd)预留的资源
  • eviction-hard硬驱逐阈值,当节点资源使用达到该阈值时,kubelet会立即驱逐Pod以回收资源,避免节点资源耗尽。常见的驱逐信号包括:
    • memory.available:可用内存低于阈值
    • nodefs.available:节点文件系统可用空间低于阈值
    • imagefs.available:镜像文件系统可用空间低于阈值
    • pid.available:可用PID数量低于阈值

evictionHard配置示例

# kubelet配置
evictionHard:
memory.available: "100Mi" # 可用内存低于100Mi时立即驱逐Pod
nodefs.available: "10%" # 节点文件系统可用空间低于10%时驱逐
imagefs.available: "15%" # 镜像文件系统可用空间低于15%时驱逐
nodefs.inodesFree: "5%" # 节点文件系统可用inode低于5%时驱逐

kubelet配置不满足sum(reserved-memory) = kube-reserved + system-reserved + eviction-hard规则时,会报类似如下的错误:

Failed to initialize memory manager" err="the total amount "xxx" of type "memory" is not equal to the value "xxx" determined by Node Allocatable feature"

Device Manager

Device Manager本身由设备插件(Device Plugin)实现,如NVIDIA GPUnvidia-device-plugin。它向Topology Manager提供GPU设备所在NUMA节点的信息。

工作机制

  1. NUMA拓扑检测Device Plugin启动时通过读取/sys/bus/pci/devices/<busid>/numa_node文件自动检测每个GPUNUMA节点信息
  2. 设备注册:向kubelet注册设备资源(如nvidia.com/gpu),并在设备的TopologyInfo字段中携带NUMA节点信息
  3. Hints提供:当Pod请求GPU时,通过GetPreferredAllocation接口返回NUMA感知的设备分配建议
  4. 拓扑协调Topology Manager结合CPUMemoryGPUHints,选择最优的NUMA节点组合

NUMA感知功能说明

重要特性NVIDIA Device Pluginv0.2.0版本开始原生支持NUMA感知功能,无需额外配置即可自动启用。该功能基于以下机制:

  1. 自动检测:通过NVML库和sysfs自动获取GPUNUMA节点信息
  2. 透明传递:通过Kubernetes Device Plugin APITopologyInfo结构体将NUMA信息传递给kubelet
  3. 智能分配:实现了GetPreferredAllocation接口,根据设备类型采用不同的分配策略:
    • 对齐分配:对于完整GPU,优先选择同一NUMA节点的设备
    • 分布式分配:对于MIGTime-slicing等共享模式,均匀分布设备

配置方式

NVIDIA Device Plugin支持多种配置方式,可以通过ConfigMap、命令行参数或Helm Chart进行配置。

ConfigMap配置示例
apiVersion: v1
kind: ConfigMap
metadata:
name: nvidia-device-plugin-config
namespace: nvidia-device-plugin
data:
config.yaml: |
version: v1
flags:
migStrategy: "none" # MIG策略: none, single, mixed
failOnInitError: true # 初始化失败时是否终止
nvidiaDriverRoot: "/" # NVIDIA驱动根目录
plugin:
passDeviceSpecs: false # 是否传递设备规范(与CPU Manager兼容时设为true)
deviceListStrategy: "envvar" # 设备列表策略: envvar, volume-mounts
deviceIDStrategy: "uuid" # 设备ID策略: uuid, index

关键配置参数

参数名称可选值默认值说明
migStrategynone, single, mixednoneMIG模式策略。none表示不使用MIGsingle表示每个MIG设备作为独立资源;mixed表示同时暴露完整GPUMIG设备
failOnInitErrortrue, falsetrue初始化失败时是否终止插件。建议生产环境设为true
passDeviceSpecstrue, falsefalse是否传递设备规范给容器。当启用CPU Managerstatic策略时,需要设为false以避免权限问题
deviceListStrategyenvvar, volume-mountsenvvar设备列表传递方式。envvar通过环境变量NVIDIA_VISIBLE_DEVICES传递;volume-mounts通过挂载/dev设备节点
deviceIDStrategyuuid, indexuuid设备标识策略。uuid使用GPU UUIDindex使用设备索引

关键组件配置更新

在执行测试之前,我们对kubelet的配置进行修改以启用NUMA亲和性特性:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration

# ============= CPU Manager 配置 =============
cpuManagerPolicy: static # 启用静态CPU管理策略
cpuManagerReconcilePeriod: 10s # 调和周期
cpuManagerPolicyOptions:
full-pcpus-only: "true" # 仅分配完整物理核心

# ============= Topology Manager 配置 =============
topologyManagerPolicy: restricted # 严格要求NUMA对齐
topologyManagerScope: pod # Pod级别对齐
topologyManagerPolicyOptions:
prefer-closest-numa-nodes: "true" # 优先选择距离最近的NUMA节点

# ============= Memory Manager 配置 =============
memoryManagerPolicy: Static # 启用静态内存管理策略
reservedMemory:
- numaNode: 0
limits:
memory: 2Gi # NUMA 0 预留内存
- numaNode: 1
limits:
memory: 2Gi # NUMA 1 预留内存

# ============= 资源预留配置 =============
# 注意需要保证公式:
# sum(reserved-memory) = kube-reserved + system-reserved + eviction-hard
kubeReserved:
cpu: "2"
memory: 1Gi
systemReserved:
cpu: "2"
memory: 1Gi
evictionHard:
memory.available: "2Gi" # 可用内存低于2Gi时立即驱逐Pod
nodefs.available: "10%" # 节点文件系统可用空间低于10%时驱逐
imagefs.available: "15%" # 镜像文件系统可用空间低于15%时驱逐
nodefs.inodesFree: "5%" # 节点文件系统可用inode低于5%时驱逐

# ============= Feature Gates(可选)=============
featureGates:
CPUManagerPolicyOptions: true
# 低版本K8S需要此项启用策略选项,如笔者当前的1.27.3版本
CPUManagerPolicyBetaOptions: true
TopologyManagerPolicyOptions: true
# 低版本K8S需要此项启用策略选项,如笔者当前的1.27.3版本
TopologyManagerPolicyAlphaOptions: true

# ... 其他配置项保持不变 ...

按照以下步骤更新kubelet配置并重启:

# 1. Drain节点(建议)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# 2. 停止kubelet
systemctl stop kubelet

# 3. 删除状态文件
rm /var/lib/kubelet/cpu_manager_state
rm /var/lib/kubelet/memory_manager_state

# 4. 修改kubelet配置
vim /var/lib/kubelet/config.yaml

# 5. 启动kubelet
systemctl start kubelet

# 6. Uncordon节点(若前面执行了drain)
kubectl uncordon <node-name>

需要注意切换策略需要清理状态文件,否则会报类似如下的错误:

start cpu manager error: could not restore state from checkpoint: configured policy "static" differs from state checkpoint policy "none", please drain this node and delete the CPU manager checkpoint file "/var/lib/kubelet/cpu_manager_state" before restarting Kubelet"

测试示例

验证NUMA亲和性

以下示例使用NVIDIA CUDA镜像,通过nvidia-smi topo -m命令验证GPUNUMA亲和性配置:

apiVersion: v1
kind: Pod
metadata:
name: numa-affinity-test
spec:
restartPolicy: Never
containers:
- name: cuda-container
image: nvidia/cuda:12.2.0-base-ubuntu20.04
command:
- /bin/bash
- -c
- |
echo "========== GPU Topology Information =========="
nvidia-smi topo -m
echo ""
echo "========== CPU Affinity Information =========="
echo "Current CPU affinity: $(taskset -p $$)"
cat /proc/self/status | grep -E "Cpus_allowed|Mems_allowed"
echo ""
echo "========== NUMA Information =========="
numactl --hardware 2>/dev/null || echo "numactl not available"
echo ""
echo "========== Process CPU Binding =========="
cat /proc/self/cpuset
echo ""
echo "========== Sleeping for observation =========="
sleep 3600
resources:
# Guaranteed QoS: requests == limits
# CPU必须是整数才能获得独占CPU
requests:
cpu: "4"
memory: "8Gi"
nvidia.com/gpu: "1"
limits:
cpu: "4"
memory: "8Gi"
nvidia.com/gpu: "1"

多GPU NUMA亲和性测试

以下示例请求同一NUMA节点的多个GPU

apiVersion: v1
kind: Pod
metadata:
name: multi-gpu-numa-test
namespace: default
spec:
restartPolicy: Never
containers:
- name: cuda-multi-gpu
image: nvidia/cuda:12.2.0-base-ubuntu20.04
command:
- /bin/bash
- -c
- |
echo "========== GPU Topology =========="
nvidia-smi topo -m
echo ""
echo "========== Allocated GPUs =========="
echo "NVIDIA_VISIBLE_DEVICES: $NVIDIA_VISIBLE_DEVICES"
echo ""
echo "========== GPU Details =========="
nvidia-smi --query-gpu=index,name,pci.bus_id,memory.total --format=csv
echo ""
echo "========== CPU Binding =========="
cat /proc/self/status | grep -E "Cpus_allowed_list|Mems_allowed_list"
echo ""
sleep 3600
resources:
requests:
cpu: "8"
memory: "16Gi"
nvidia.com/gpu: "2" # 请求2个GPU
limits:
cpu: "8"
memory: "16Gi"
nvidia.com/gpu: "2"

故障排查

TopologyAffinityError

Pod无法满足Topology Manager的策略要求时,会出现此错误:

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
numa-affinity-test 0/1 TopologyAffinityError 0 10s

排查步骤

  1. 检查节点可用资源是否满足NUMA对齐要求
  2. 降低策略严格程度(如从single-numa-node改为restricted
  3. 减少Pod的资源请求

切换CPU Manager Policy

切换策略需要清理状态文件:

# 1. Drain节点(建议)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# 2. 停止kubelet
systemctl stop kubelet

# 3. 删除状态文件
rm /var/lib/kubelet/cpu_manager_state
rm /var/lib/kubelet/memory_manager_state

# 4. 修改kubelet配置
vim /var/lib/kubelet/config.yaml

# 5. 启动kubelet
systemctl start kubelet

# 6. Uncordon节点
kubectl uncordon <node-name>

查看Kubelet日志

journalctl -u kubelet -f | grep -E "cpu_manager|topology_manager|memory_manager"

最佳实践

  1. AI训练场景推荐配置

    • topologyManagerPolicy: restricted
    • topologyManagerScope: pod
    • cpuManagerPolicy: static
  2. 资源请求规范

    • 确保PodGuaranteed QoS(requests == limits)
    • CPU请求使用整数值以获得独占CPU
  3. 多GPU场景

    • 使用single-numa-node策略确保多GPU在同一NUMA节点
    • 或使用prefer-closest-numa-nodes选项减少跨NUMA延迟
  4. 性能监控

    • 监控跨NUMA内存访问(通过numastat命令)
    • 监控CPU上下文切换和缓存命中率

参考资料