本文的内容还在编写中,示例代码还未进行严格测试。
引言
在AI模型开发、训练和推理场景中,计算密集型任务对硬件资源的高效利用提出了极高要求。除了GPU算力本身,CPU和内存的访问效率同样是影响整体性能的关键因素。不合理的CPU与内存分配可能导致跨NUMA节点的内存访问、频繁的进程迁移等问题,从而显著降低系统性能。
CPU亲和性(CPU Affinity)和NUMA亲和性(NUMA Affinity)调度技术通过精确控制进程与CPU核心、内存节点的绑定关系,最大化利用硬件拓扑结构,减少资源访问延迟,提升AI工作负载的性能表现。本文将深入介绍这些核心技术的原理、应用场景及在Docker和Kubernetes环境下的具体实现方法。
NUMA架构简介
什么是NUMA
NUMA(Non-Uniform Memory Access,非统一内存访问)是现代多处理器系统采用的一种内存访问架构。在NUMA架构中,系统内存被划分为多个NUMA节点(NUMA Node),每个节点包含一组CPU核心和本地内存。
与传统的UMA(Uniform Memory Access,统一内存访问)架构相比,NUMA架构具有以下特点:
- 本地访问优化:
CPU访问本地NUMA节点的内存速度最快 - 远程访问代价:
CPU访问其他NUMA节点的内存(跨节点访问)会产生额外延迟 - 可扩展性强:通过增加
NUMA节点可以线性扩展系统规模
NUMA架构的层级结构
例如一个典型的NUMA系统具有以下层级结构:
┌─────────────────────────────────────────────────────────────┐
│ NUMA 系统 │
├──────────────────────────┬──────────────────────────────────┤
│ NUMA Node 0 │ NUMA Node 1 │
├──────────────────────────┼──────────────────────────────────┤
│ CPU 0-31, 64-95 │ CPU 32-63, 96-127 │
│ Local Memory │ Local Memory │
│ PCIe Devices (GPU0-3) │ PCIe Devices (GPU4-7) │
└──────────────────────────┴──────────────────────────────────┘
在上述架构中:
- 每个
NUMA节点包含一组CPU核心 - 每个
NUMA节点有自己的本地内存 PCIe设备(如GPU)也归属于特定的NUMA节点
NUMA对性能的影响
在AI训练和推理场景中,NUMA架构对性能的影响主要体现在:
-
内存访问延迟:本地内存访问延迟通常为
100-200ns,而跨NUMA节点访问延迟可达300-500ns,差距达2-3倍 -
内存带宽:跨节点访问会占用
NUMA互连总线,降低整体内存带宽 -
PCIe通信延迟:
GPU物理连接在特定NUMA节点的PCIe总线上CPU访问非本地NUMA节点的GPU需要经过NUMA互联(QPI/UPI)- 跨
NUMA的PCIe访问会增加100-200ns额外延迟 DMA(Direct Memory Access)传输带宽可能降低50%以上
-
GPU-CPU通信效率:
GPU kernel启动、状态查询、寄存器访问等PCIe事务受跨NUMA影响- 频繁的
CPU-GPU交互会放大跨NUMA开销 - 影响整体
GPU利用率和吞吐量
-
数据传输效率:跨
NUMA节点的数据传输会影响GPU与CPU之间的数据交换效率,包括:- 主机到设备(
Host-to-Device)传输 - 设备到主机(
Device-to-Host)传输 - 统一内存(
Unified Memory)的页面迁移
- 主机到设备(
CPU&NUMA亲和性的重要性
CPU亲和性的作用
CPU亲和性(CPU Affinity)是指将进程或线程绑定到特定的CPU核心上运行。在AI工作负载中,合理的CPU亲和性配置可以:
- 减少上下文切换:避免进程在不同
CPU核心间频繁迁移,减少上下文切换开销 - 提升缓存命中率:进程固定在特定核心运行,可以更好地利用
CPU的L1、L2、L3缓存 - 降低延迟抖动:避免进程迁移带来的性能波动,提供更稳定的延迟表现
- 避免资源竞争:将不同任务绑定到不同的核心,减少
CPU资源争抢
NUMA亲和性的作用
NUMA亲和性(NUMA Affinity)是指将进程、内存分配和I/O设备绑定到同一NUMA节点,以优化内存访问性能。在AI场景中的价值包括:
- 降低内存访问延迟:确保进程访问本地内存,避免跨
NUMA节点的远程内存访问 - 提升内存带宽:本地内存访问可以充分利用
NUMA节点的内存带宽 - 优化GPU-CPU通信:将
GPU、对应的CPU核心和内存绑定到同一NUMA节点,最小化数据传输延迟 - 提高整体吞吐量:通过减少跨节点通信,提升系统整体的数据处理能力
AI模型训练推理场景中的影响
在AI模型训练和推理场景中,不合理的亲和性配置可能导致:
- 训练速度下降:数据加载、预处理过程中的跨
NUMA访问会拖累整体训练速度 - 推理延迟增加:推理服务中的请求处理涉及频繁的
CPU-GPU交互,跨NUMA访问会增加延迟 - 吞吐量降低:在高并发推理场景下,跨
NUMA访问会成为系统瓶颈 - 性能不稳定:进程迁移和非本地内存访问会导致性能抖动
通过合理配置CPU亲和性和NUMA亲和性,通常可以获得10%-30%的性能提升,在某些场景下甚至可以达到50%以上的优化效果。
CPU&NUMA亲和性示例分析
理解nvidia-smi topo命令输出
NVIDIA提供了nvidia-smi topo -m命令来查看GPU之间以及GPU与CPU之间的拓扑关系。让我们详细分析提供的拓扑信息:
GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7 CPU Affinity NUMA Affinity GPU NUMA ID
GPU0 X PIX NODE NODE SYS SYS SYS SYS 0-31,64-95 0 N/A
GPU1 PIX X NODE NODE SYS SYS SYS SYS 0-31,64-95 0 N/A
GPU2 NODE NODE X PIX SYS SYS SYS SYS 0-31,64-95 0 N/A
GPU3 NODE NODE PIX X SYS SYS SYS SYS 0-31,64-95 0 N/A
GPU4 SYS SYS SYS SYS X PIX NODE NODE 32-63,96-127 1 N/A
GPU5 SYS SYS SYS SYS PIX X NODE NODE 32-63,96-127 1 N/A
GPU6 SYS SYS SYS SYS NODE NODE X PIX 32-63,96-127 1 N/A
GPU7 SYS SYS SYS SYS NODE NODE PIX X 32-63,96-127 1 N/A
连接类型说明
矩阵中的符号表示GPU之间的连接类型,按照性能从高到低排列:
| 连接类型 | 说明 | 典型带宽 | 适用场景 |
|---|---|---|---|
X | 自身 | N/A | 同一GPU |
NV# | NVLink连接(#表示链接数量) | 300-900 GB/s | 高性能GPU间通信(如NVLink 3.0/4.0) |
PIX | 同一PCIe交换机可能包含 NVLink Bridge | PCIe: 16-64 GB/sNVLink Bridge: 100-200 GB/s | 同PCIe树GPU通信部分消费级 GPU使用NVLink Bridge互联 |
NODE | 同一NUMA节点,不同PCIe交换机 | 16-32 GB/s | 同NUMA节点GPU跨PCIe交换机通信 |
SYS | 跨NUMA节点,通过CPU互联 | 8-16 GB/s | 跨NUMA节点GPU通信,性能最低 |
CPU Affinity字段解析
CPU Affinity列显示了每个GPU关联的最优CPU核心范围:
-
GPU0-GPU3:
0-31, 64-95- 物理核心:
0-31 - 超线程核心:
64-95 - 总共
32个物理核心,64个逻辑核心(启用超线程)
- 物理核心:
-
GPU4-GPU7:
32-63, 96-127- 物理核心:
32-63 - 超线程核心:
96-127 - 总共
32个物理核心,64个逻辑核心(启用超线程)
- 物理核心:
关键理解:当进程需要使用特定GPU时,应将其绑定到该GPU的CPU Affinity范围内的核心,以实现最优性能。
NUMA Affinity字段解析
NUMA Affinity列显示了每个GPU所属的NUMA节点:
- GPU0-GPU3: 属于
NUMA Node 0 - GPU4-GPU7: 属于
NUMA Node 1
这意味着:
- 使用
GPU0-GPU3的任务应绑定到NUMA Node 0的CPU核心和内存 - 使用
GPU4-GPU7的任务应绑定到NUMA Node 1的CPU核心和内存
NUMA与PCIe拓扑的关系:
NUMA Node 0 NUMA Node 1
├── CPU 0-31, 64-95 ├── CPU 32-63, 96-127
├── Local Memory ├── Local Memory
└── PCIe Root Complex └── PCIe Root Complex
├── PCIe Switch 0 ├── PCIe Switch 2
│ ├── GPU0 │ ├── GPU4
│ └── GPU1 │ └── GPU5
└── PCIe Switch 1 └── PCIe Switch 3
├── GPU2 ├── GPU6
└── GPU3 └── GPU7
关键理解:
- 每个
GPU物理连接到特定NUMA节点的PCIe总线 CPU访问非本地NUMA节点的GPU需要经过NUMA互联(QPI/UPI)- 跨
NUMA的PCIe访问会显著增加延迟并降低带宽 - 最佳性能需要
CPU、内存、GPU都在同一NUMA节点
拓扑分析总结
从上述拓扑信息可以得出以下结论:
-
GPU分组:
- 组1:
GPU0-GPU3(NUMA Node 0) - 组2:
GPU4-GPU7(NUMA Node 1)
- 组1:
-
GPU间连接模式:
GPU0-GPU1通过PIX连接(同PCIe交换机)GPU2-GPU3通过PIX连接(同PCIe交换机)GPU0/1与GPU2/3通过NODE连接(同NUMA节点,不同PCIe交换机)- 跨
NUMA节点的GPU通过SYS连接(性能最低)
-
最佳实践:
- 单卡任务:使用任意一张
GPU,绑定到对应的CPU核心和NUMA节点 - 2卡任务:优先选择
GPU0-GPU1或GPU2-GPU3等PIX连接的GPU对 - 4卡任务:选择
GPU0-GPU3或GPU4-GPU7(同NUMA节点,性能最优) - 5卡任务:例如
GPU0-GPU4,会跨NUMA节点,GPU4与GPU0-3通信性能较低(SYS连接) - 跨
NUMA任务:尽量选择4+4的组合(如GPU0-3+GPU4-7在不同节点),避免5卡这种不均衡配置
- 单卡任务:使用任意一张
Docker中的CPU&NUMA亲和性配置
Docker的亲和性参数
Docker提供了多个参数来控制容器的CPU和NUMA亲和性:
| 参数 | 说明 | 示例 |
|---|---|---|
--cpuset-cpus | 指定容器可使用的CPU核心 | --cpuset-cpus="0-31,64-95" |
--cpuset-mems | 指定容器可使用的NUMA内存节点 | --cpuset-mems="0" |
--cpus | 限制容器可使用的CPU核心数量 | --cpus="8.0" |
--cpu-shares | 设置CPU权重(相对值) | --cpu-shares=1024 |
示例1:单GPU训练任务
假设我们要运行一个使用GPU0的训练任务:
# 查看GPU0的CPU亲和性和NUMA亲和性
# GPU0: CPU Affinity: 0-31,64-95, NUMA Affinity: 0
docker run -d \
--name ai-training-gpu0 \
--gpus '"device=0"' \
--cpuset-cpus="0-31,64-95" \
--cpuset-mems="0" \
--shm-size=16g \
-v /data:/data \
my-training-image:latest \
python train.py --gpu 0
参数说明:
--gpus '"device=0"':使用GPU0--cpuset-cpus="0-31,64-95":将容器绑定到GPU0的亲和CPU核心--cpuset-mems="0":将容器的内存分配限制在NUMA Node 0--shm-size=16g:设置共享内存大小(AI训练通常需要较大的共享内存)
为什么单GPU也需要设置CPU亲和性?
虽然是单GPU任务,设置CPU和NUMA亲和性仍然非常重要:
-
优化CPU-GPU数据传输(内存维度):
GPU0连接在NUMA Node 0,即使进程运行在Node 0的CPU上,如果内存分配来自NUMA Node 1,数据从CPU内存传输到GPU时仍需要跨NUMA节点,延迟会增加2-3倍。 -
优化CPU-GPU通信(PCIe维度):
GPU物理连接在特定NUMA节点的PCIe总线上(如GPU0连接在Node 0的PCIe),如果CPU进程运行在其他NUMA节点(如Node 1),CPU与GPU的控制命令、状态查询等PCIe通信都需要经过NUMA互联总线(QPI/UPI),增加额外延迟。 -
提升数据预处理性能:训练任务通常需要大量
CPU进行数据加载和预处理(如图像解码、数据增强),这些操作的内存访问如果跨NUMA会显著降低吞吐量。 -
减少延迟抖动:即使
CPU绑核,内存分配策略不当或PCIe访问跨NUMA仍可能导致性能不稳定。 -
实际性能提升:根据测试,单
GPU训练任务正确设置亲和性后,通常可获得10%-20%的性能提升。
重要理解:CPU亲和性 ≠ NUMA内存亲和性
这是一个常见误解,需要特别说明:
--cpuset-cpus参数:控制容器进程可以在哪些CPU核心上执行(进程调度层面)。--cpuset-mems参数:控制容器进程的内存分配来自哪些NUMA节点(内存分配层面),同时也会影响GPU-内存之间的PCIe DMA传输效率(因为GPU物理连接在特定NUMA节点的PCIe总线上)。
为什么指定了CPU亲和性还需要指定NUMA亲和性?
即使使用--cpuset-cpus="0-31,64-95"将进程限制在NUMA Node 0的CPU上运行,并不意味着内存也会自动从NUMA Node 0分配。原因如下:
-
Linux内核的内存分配策略:
- 如果不指定
--cpuset-mems,内核可能使用默认的内存策略(如default或interleave) - 内核会根据内存压力从任何有可用内存的
NUMA节点分配 - 当
NUMA Node 0内存不足或碎片化时,会自动从Node 1分配
- 如果不指定
-
实际场景示例:
# 只指定CPU亲和性,不指定内存亲和性
docker run --cpuset-cpus="0-31,64-95" ...
# 容器内查看内存分布
numastat -p <pid>
# 结果可能显示:
# Node 0: 8GB
# Node 1: 24GB ← 大部分内存来自Node 1! -
PCIe通信与DMA传输的影响:GPU通过PCIe连接到特定NUMA节点(GPU0-3连接到Node 0的PCIe Root Complex)- 如果
CPU在Node 0但使用Node 1的GPU,或者CPU在Node 1但使用Node 0的GPU CPU与GPU之间的PCIe事务(寄存器访问、中断处理)都需要跨NUMA互联GPU-内存DMA传输同样受NUMA影响:如果GPU在Node 0但内存在Node 1,GPU读写内存时需要通过QPI/UPI跨NUMA访问,DMA带宽可能降低50%以上- 跨
NUMA的PCIe访问延迟增加,DMA传输效率降低,GPU利用率下降
示例2:多GPU训练任务(同NUMA节点)
使用GPU0-GPU3进行4卡训练:
docker run -d \
--name ai-training-4gpu \
--gpus '"device=0,1,2,3"' \
--cpuset-cpus="0-31,64-95" \
--cpuset-mems="0" \
--shm-size=32g \
-v /data:/data \
-e CUDA_VISIBLE_DEVICES=0,1,2,3 \
my-training-image:latest \
torchrun --nproc_per_node=4 train.py
关键点:
4张GPU都在NUMA Node 0,使用相同的CPU亲和性配置- 增加共享内存大小以支持多
GPU通信 - 使用
torchrun启动分布式训练
示例3:推理服务(优化延迟)
运行一个使用GPU0的推理服务,需要绑定特定的CPU核心以降低延迟:
docker run -d \
--name ai-inference-gpu0 \
--gpus '"device=0"' \
--cpuset-cpus="0-7,64-71" \
--cpuset-mems="0" \
--memory="32g" \
--memory-reservation="28g" \
-p 8080:8080 \
-v /models:/models \
my-inference-image:latest \
python serve.py --gpu 0 --port 8080
优化说明:
--cpuset-cpus="0-7,64-71":只使用8个物理核心(及其超线程),减少调度开销--memory-reservation:预留内存,减少内存回收带来的延迟抖动- 绑定到
NUMA Node 0确保本地内存访问
示例4:跨NUMA节点的5卡训练
当需要使用5张GPU时(GPU0-4,跨越两个NUMA节点),需要考虑跨NUMA节点的配置:
docker run -d \
--name ai-training-5gpu \
--gpus '"device=0,1,2,3,4"' \
--cpuset-cpus="0-63,64-127" \
--cpuset-mems="0,1" \
--shm-size=48g \
-v /data:/data \
-e CUDA_VISIBLE_DEVICES=0,1,2,3,4 \
-e OMP_NUM_THREADS=64 \
my-training-image:latest \
torchrun --nproc_per_node=5 train.py
注意事项:
- 跨NUMA场景:
GPU0-3在NUMA Node 0,GPU4在NUMA Node 1,必然存在跨NUMA通信 --cpuset-mems="0,1":允许使用两个NUMA节点的内存- 增加
OMP_NUM_THREADS以充分利用所有CPU核心 - 训练代码应注意
GPU间通信模式,GPU4与GPU0-3的通信会经过SYS连接(性能较低) - 性能优化建议:如果可能,优先使用
4卡(GPU0-3或GPU4-7,单NUMA节点)而非5卡,可避免跨NUMA开销
Docker亲和性配置验证
在容器内可以使用以下命令验证亲和性配置:
# 查看容器的CPU亲和性
docker exec ai-training-gpu0 taskset -cp 1
# 查看容器的NUMA策略
docker exec ai-training-gpu0 numactl --show
# 查看容器可见的GPU
docker exec ai-training-gpu0 nvidia-smi -L
# 查看进程的CPU绑定情况
docker exec ai-training-gpu0 ps -eLo pid,tid,psr,comm | grep python
Kubernetes中CPU&NUMA亲和性配置
Kubernetes的亲和性机制
Kubernetes提供了多种机制来控制Pod的CPU和NUMA亲和性:
- CPU Manager:静态策略下实现
CPU绑核 - Topology Manager:协调
CPU Manager和Device Manager实现拓扑感知调度 - Device Plugin:管理
GPU等设备资源 - 节点亲和性:控制
Pod调度到特定节点
前置条件配置
1. 启用Kubelet特性
需要在Kubelet配置中启用以下特性:
# /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: static
cpuManagerReconcilePeriod: 10s
topologyManagerPolicy: single-numa-node # 或 best-effort、restricted
topologyManagerScope: pod
reservedSystemCPUs: "0,64" # 为系统预留CPU核心
# ...
Topology Manager策略说明:
| 策略 | 说明 | 适用场景 |
|---|---|---|
none | 默认策略,不进行拓扑对齐 | 不关心NUMA亲和性 |
best-effort | 尽力对齐,对齐失败也允许调度 | 希望优化但不强制要求 |
restricted | 优先对齐,失败时放宽限制 | 平衡性能和调度成功率 |
single-numa-node | 强制所有资源在同一NUMA节点 | 对性能要求极高的场景 |
2. 重启Kubelet使配置生效
systemctl restart kubelet
示例1:单GPU训练任务(NUMA Node 0)
创建一个使用GPU0的训练任务,绑定到NUMA Node 0:
apiVersion: v1
kind: Pod
metadata:
name: ai-training-gpu0
labels:
app: ai-training
gpu-id: "0"
spec:
restartPolicy: Never
# 节点选择器:确保调度到有GPU0的节点
nodeSelector:
nvidia.com/gpu.present: "true"
containers:
- name: training
image: my-training-image:latest
command: ["python", "train.py", "--gpu", "0"]
resources:
requests:
cpu: "16" # 请求16个CPU核心
memory: "64Gi" # 请求64GB内存
nvidia.com/gpu: 1 # 请求1个GPU
limits:
cpu: "32" # 限制最多使用32个CPU核心
memory: "128Gi" # 限制最多使用128GB内存
nvidia.com/gpu: 1
env:
- name: CUDA_VISIBLE_DEVICES
value: "0"
- name: OMP_NUM_THREADS
value: "16"
# NUMA绑定环境变量(需要容器支持)
- name: GOMP_CPU_AFFINITY
value: "0-31 64-95"
volumeMounts:
- name: data
mountPath: /data
- name: shm
mountPath: /dev/shm
volumes:
- name: data
hostPath:
path: /data
type: Directory
- name: shm
emptyDir:
medium: Memory
sizeLimit: 32Gi
关键配置说明:
-
CPU请求和限制:
requests.cpu: "16"确保Pod获得足够的CPU资源- 在
static策略下,Kubernetes会为该Pod独占分配16个CPU核心
-
GPU资源:
nvidia.com/gpu: 1请求一个GPUDevice Plugin会根据调度策略分配合适的GPU
-
共享内存:
- 使用
emptyDir卷挂载到/dev/shm,提供足够的共享内存
- 使用
示例2:多GPU训练任务(4卡,同NUMA节点)
使用GPU0-GPU3进行4卡分布式训练:
apiVersion: v1
kind: Pod
metadata:
name: ai-training-4gpu
labels:
app: ai-training-distributed
gpu-count: "4"
spec:
restartPolicy: Never
# 节点亲和性:选择有足够GPU的节点
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.count
operator: Gt
values: ["3"]
containers:
- name: training
image: my-training-image:latest
command:
- torchrun
- --nproc_per_node=4
- --nnodes=1
- --node_rank=0
- train.py
resources:
requests:
cpu: "32" # 4卡任务请求更多CPU
memory: "128Gi"
nvidia.com/gpu: 4 # 请求4个GPU
limits:
cpu: "64"
memory: "256Gi"
nvidia.com/gpu: 4
env:
- name: CUDA_VISIBLE_DEVICES
value: "0,1,2,3"
- name: NCCL_DEBUG
value: "INFO"
- name: NCCL_IB_DISABLE
value: "0" # 启用InfiniBand(如果可用)
- name: NCCL_SOCKET_IFNAME
value: "eth0"
- name: OMP_NUM_THREADS
value: "32"
volumeMounts:
- name: data
mountPath: /data
- name: shm
mountPath: /dev/shm
volumes:
- name: data
persistentVolumeClaim:
claimName: training-data-pvc
- name: shm
emptyDir:
medium: Memory
sizeLimit: 64Gi
示例3:推理服务(固定GPU和CPU绑核)
部署一个低延迟的推理服务:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-inference-service
spec:
replicas: 1
selector:
matchLabels:
app: ai-inference
template:
metadata:
labels:
app: ai-inference
spec:
# 使用Guaranteed QoS确保独占CPU
containers:
- name: inference
image: my-inference-image:latest
command: ["python", "serve.py", "--gpu", "0", "--port", "8080"]
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
# requests和limits相同,确保Guaranteed QoS
requests:
cpu: "8"
memory: "32Gi"
nvidia.com/gpu: 1
limits:
cpu: "8"
memory: "32Gi"
nvidia.com/gpu: 1
env:
- name: CUDA_VISIBLE_DEVICES
value: "0"
- name: OMP_NUM_THREADS
value: "8"
# 固定CPU亲和性
- name: GOMP_CPU_AFFINITY
value: "0-7 64-71"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
volumeMounts:
- name: models
mountPath: /models
readOnly: true
volumes:
- name: models
persistentVolumeClaim:
claimName: models-pvc
推理服务优化要点:
- Guaranteed QoS:requests和limits相同,确保Pod获得独占CPU资源
- 固定CPU数量:使用较少的CPU核心,减少调度开销
- 健康检查:配置liveness和readiness探针确保服务稳定
示例4:跨NUMA节点的5卡训练
使用5张GPU进行分布式训练(跨NUMA节点):
apiVersion: v1
kind: Pod
metadata:
name: ai-training-5gpu
labels:
app: ai-training-distributed
gpu-count: "5"
spec:
restartPolicy: Never
containers:
- name: training
image: my-training-image:latest
command:
- torchrun
- --nproc_per_node=5
- --nnodes=1
- --node_rank=0
- train.py
resources:
requests:
cpu: "48"
memory: "192Gi"
nvidia.com/gpu: 5
limits:
cpu: "96"
memory: "384Gi"
nvidia.com/gpu: 5
env:
- name: CUDA_VISIBLE_DEVICES
value: "0,1,2,3,4"
- name: NCCL_DEBUG
value: "INFO"
- name: NCCL_IB_DISABLE
value: "0"
- name: NCCL_SOCKET_IFNAME
value: "eth0"
# 跨NUMA节点,允许使用所有CPU
- name: OMP_NUM_THREADS
value: "48"
# NCCL拓扑感知
- name: NCCL_TOPO_FILE
value: "/etc/nccl/topo.xml"
volumeMounts:
- name: data
mountPath: /data
- name: shm
mountPath: /dev/shm
- name: nccl-topo
mountPath: /etc/nccl
readOnly: true
volumes:
- name: data
persistentVolumeClaim:
claimName: training-data-pvc
- name: shm
emptyDir:
medium: Memory
sizeLimit: 96Gi
- name: nccl-topo
configMap:
name: nccl-topology-config
跨NUMA配置说明:
- 资源分配:
5卡场景下,4卡在NUMA Node 0,1卡在NUMA Node 1 - CPU配置:分配
48个物理核心,足够支持5卡训练的数据预处理 - 内存配置:总共
192GB请求内存,Topology Manager会尽量从两个NUMA节点分配 - 性能考虑:
GPU4与GPU0-3之间的通信会通过SYS连接,带宽较低(8-16 GB/s) - 替代方案:如果性能要求高,建议使用
4卡(单NUMA节点)或8卡(双NUMA均衡)方案
使用Topology Manager实现自动NUMA对齐
当启用Topology Manager并设置为single-numa-node策略时,Kubernetes会自动确保:
Pod请求的所有GPU在同一NUMA节点Pod分配的CPU核心在同一NUMA节点Pod的内存分配优先从同一NUMA节点分配
验证Topology对齐:
# 进入Pod查看CPU绑定
kubectl exec -it ai-training-gpu0 -- taskset -cp 1
# 查看NUMA策略
kubectl exec -it ai-training-gpu0 -- numactl --show
# 查看GPU拓扑
kubectl exec -it ai-training-gpu0 -- nvidia-smi topo -m