AI训练加速30%!用numactl玩转多显卡绑核的隐藏技巧
如果你正在用多张GPU跑PyTorch或TensorFlow训练,大概率遇到过这样的困惑:明明硬件配置拉满,为什么训练速度就是上不去?日志里GPU利用率看着还行,但总感觉系统“有劲使不出”。你可能已经尝试过调整batch size、优化数据加载器,甚至换上了更快的NVMe硬盘,但性能瓶颈似乎依然存在。很多时候,问题的根源并不在GPU本身,而在于你忽略了CPU与GPU之间那层隐秘的“地理关系”——NUMA架构。
现代多路服务器早已不是简单的对称多处理器(SMP)世界。在NUMA架构下,内存被划分到不同的节点,每个节点直接连接着一组CPU核心。访问“本地”节点的内存速度飞快,而访问“远端”节点的内存则要慢得多,这种延迟差异在数据密集型任务中会被急剧放大。当你的AI训练进程随机地在不同NUMA节点的CPU核心上调度,并且需要频繁访问跨节点的内存时,性能损耗就悄无声息地产生了。这就像把仓库建在城市的另一端,工人每天取货都要长途跋涉,效率自然低下。
numactl这个看似古老的系统工具,正是解开这道枷锁的钥匙。它允许你将进程及其内存分配,精准地“钉”在特定的NUMA节点上。对于多卡训练场景,精髓在于:将控制每张GPU的进程,绑定到该GPU所在的本地NUMA节点对应的CPU核心上。这能最大程度减少跨节点内存访问,降低延迟,让数据流像在高速公路上一样畅通无阻。不少团队在实施精确的NUMA绑核后,在多卡训练任务中获得了高达20%-30%的吞吐量提升,这绝非理论上的数字游戏,而是实实在在的工程优化。
1. 理解你的战场:NUMA拓扑与GPU的隐秘关联
在开始绑核之前,我们必须先摸清自家服务器的“底细”。NUMA拓扑决定了CPU、内存和PCIe设备的物理布局,而GPU通常通过PCIe总线连接到特定的CPU插槽,进而归属于某个NUMA节点。
首先,使用numactl --hardware或lscpu来绘制你的系统地图。下面是一个典型双路服务器(两个CPU插槽)的输出示例:
$ numactl --hardware
available: 2 nodes (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
node 0 size: 128763 MB
node 0 free: 10240 MB
node 1 cpus: 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
node 1 size: 129020 MB
node 1 free: 56320 MB
node distances:
node 0 1
0: 10 21
1: 21 10
这里我们看到两个NUMA节点(Node 0和Node 1)。node distances显示的距离值是个相对权重,10表示本地访问,21表示跨节点访问,延迟大约是本地访问的2倍。关键信息在于每个节点管辖的CPU核心列表(cpus)。
接下来,需要确定每张GPU“住在”哪个NUMA节点。这需要结合lspci和nvidia-smi的信息。一个更直接的方法是使用nvidia-smi topo -m命令,它会显示GPU与CPU之间的亲和性矩阵。
$ nvidia-smi topo -m
GPU0 GPU1 GPU2 GPU3 CPU Affinity
GPU0 X PHB SOC SOC 0-11,24-35
GPU1 PHB X SOC SOC 0-11,24-35
GPU2 SOC SOC X PHB 12-23,36-47
GPU3 SOC SOC PHB X 12-23,36-47
Legend:
X = Self
SOC = Connection traversing PCIe as well as the SMP link between CPU sockets(e.g. QPI)
PHB = Connection traversing PCIe as well as a PCIe Host Bridge (typically a CPU)
这个输出需要一点解读。CPU Affinity列指明了每张GPU偏好或直接连接的CPU核心范围。结合之前的numactl输出,我们可以推断:
- GPU0和GPU1的亲和CPU(0-11, 24-35)中,0-11属于Node 0,24-35属于Node 1。但通常,前一半(0-11)更可能是本地核心。我们需要进一步确认。
- GPU2和GPU3的亲和CPU(12-23, 36-47)中,12-23属于Node 0,36-47属于Node 1。
更精确的方法是检查PCIe设备的NUMA节点。在Linux中,可以通过/sys/bus/pci/devices/目录下的信息来查询。例如,找到GPU的PCI总线地址(通过nvidia-smi -q
2302




被折叠的 条评论
为什么被折叠?



