为什么单卡跑不动大模型?

面对 Llama 3.1 405B 这类超大参数模型,单张显卡的显存往往捉襟见肘。即便是在拥有 192GB HBM 的 AMD Instinct MI300X 上,若不加优化地加载全量权重加上 KV Cache,也极易触发 OOM(显存溢出)。这时候,多卡张量并行(Tensor Parallelism, TP)就成了必选项。它通过将模型权重切分到多张卡上,让集群共同承担计算和存储压力。但在 ROCm 环境下,要把这套机制跑顺,光会改参数还不够,底层的硬件拓扑和系统调度才是决定性能上限的关键。

动手前的“体检”:确认互联拓扑

在启动 vLLM 服务之前,必须先搞清楚显卡之间是怎么“连线”的。张量并行对卡间通信带宽极其敏感,如果参与计算的 GPU 跨越了 PCIe 交换机甚至位于不同 NUMA 节点,通信延迟会成倍增加,导致吞吐量不升反降。

在 Instinct GPU 集群上,最理想的拓扑是通过 Infinity Fabric 直连。我们可以使用 rocm-smi --showtopo 命令来查看当前的连接状态。输出结果中,如果看到 GPU 之间标记为 NV#(代表 NVLink 类似的高速互联,AMD 语境下通常指 XGMI/Infinity Fabric)或者直接显示为同一根总线下的紧密连接,那就是最佳状态。若发现显卡之间需要通过 PCIe Root Complex 进行多次跳转,建议在启动时通过 --device 参数手动指定那些物理位置相邻的卡,避免跨_socket_通信。

此外,rocminfo 也是个好帮手,它能详细列出每个 GPU 的架构代码(如 gfx942)和内存属性。确保所有参与并行的卡架构一致,否则在编译内核时可能会遇到指令集不兼容的尴尬。

核心配置:启动张量并行服务

确认硬件拓扑无误后,就可以通过 vLLM 启动推理服务了。核心参数是 --tensor-parallel-size,它直接告诉框架我们要用几张卡来切分模型。

假设我们有一个双卡环境,想要运行一个量化后的超大模型,启动命令大致如下:

vllm serve meta-llama/Llama-3.1-405B-Instruct \
    --tensor-parallel-size 2 \
    --gpu-memory-utilization 0.90 \
    --block-size 32 \
    --port 8000 \
    --host 0.0.0.0

这里有几个细节值得注意:

  • --gpu-memory-utilization:在多卡模式下,建议设置为 0.90 左右。虽然单卡时可以激进到 0.95,但多卡通信需要预留一定的显存作为缓冲区,过高的占用率容易在并发高峰时引发集体崩溃。
  • --block-size:对于长上下文场景,适当调大 block size(如 32 或 64)可以减少页表管理开销,提升显存碎片整理效率。

启动过程中,密切观察日志。正常的流程会显示模型权重正在被分片加载(Sharding),如果卡在 “Initializing process group” 阶段太久,通常是底层通信库 RCCL 出了问题。

拒绝 CPU 争抢:NUMA 绑核实战

很多开发者忽略了进程绑核(CPU Affinity)的重要性。在多卡服务器上,CPU 核心通常划分为多个 NUMA 节点,每个节点本地访问对应的内存和 PCIe 控制器速度最快。如果 vLLM 的工作进程被操作系统随机调度到远离 GPU 的 CPU 核心上,数据拷贝就要跨越 QPI/UPI 总线,延迟显著增加。

使用 numactl 可以强制将进程绑定到特定的 NUMA 节点。例如,在一个双路服务器上有两个 NUMA 节点(0 和 1),每张卡分别靠近一个节点,我们可以这样启动:

# 绑定第一个进程到 NUMA 节点 0,控制 GPU 0
numactl --cpunodebind=0 --membind=0 vllm serve ... --device 0

# 绑定第二个进程到 NUMA 节点 1,控制 GPU 1
numactl --cpunodebind=1 --membind=1 vllm serve ... --device 1

如果是通过 tensor-parallel-size 让 vLLM 自动 spawn 多个进程,可以在环境变量中设置 NUMACTL 相关参数,或者编写一个简单的 shell 脚本来包裹启动命令,确保每个 worker 进程都“就地取材”。实测表明,正确的绑核策略能让 P99 延迟降低 15% 以上,尤其在高频小包请求场景下效果明显。

性能观测与通信瓶颈排查

多卡并行并非总是线性的性能提升。在理想状态下,双卡吞吐量应接近单卡的 1.8 倍以上(扣除通信损耗)。如果发现并发升高后 Token/s 增长停滞,甚至下降,大概率是通信带宽成了瓶颈。

此时可以利用 rccl-test 工具(ROCm 集合通信库测试套件)来验证卡间带宽。运行 all_reduce_perf 测试,观察带宽是否达到了 Infinity Fabric 的理论值。如果数值偏低,检查是否开启了 IOMMU 或者防火墙规则干扰了 RDMA 流量。

另外,RCCL 报错也是常见问题。如果遇到 unhandled system errorconnection reset,首先检查 /dev/kfd/dev/dri 的权限是否正确(当前用户需在 video/render 组)。其次,确认环境变量 NCCL_DEBUG=INFO 开启,查看详细握手日志。很多时候,仅仅是因为不同卡片间的时钟频率未同步,或者驱动版本微不一致,都会导致集合通信初始化失败。

当一切配置妥当,你会看到模型加载时间虽比单卡略长(因为涉及权重分发),但一旦进入推理阶段,高并发下的吞吐量会有质的飞跃。这种通过软硬协同优化带来的性能红利,正是构建生产级大模型服务的基石。

200小时GPU算力已就位,快来领取:https://marketing.csdn.net/questions/Q2604140858304426315?utm_source=AIpaper

在这里插入图片描述

Logo

免费领 200 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐