资讯详情

资讯详情

POWER9+三卡V100并行跑LLM:AC922网络安装与实战记录

说实话接到这个任务的时候我下意识先问了一句这年头还有人折腾 POWER9 跑 LLM然后我看了眼手边这台正在嗡嗡作响的机器——AC922双路 POWER9三张 V100 挂着 NVLink心里那点抵触瞬间变成了“真香”。这台机器是某团队淘汰下来的 AI 训练服务器机缘巧合到了我们手里。本身 Power 平台在国内就小众再加上网络安装、驱动、框架适配这一连串坑网上能查到的中文资料少得可怜我啃了好几天英文文档加官方手册才把整条链路跑通。这篇记录就是把从零开始到三卡并行跑起 LLM 的全过程复盘一遍你如果有同类机器或者准备接手类似的 Power 服务器照着走应该能省掉不少弯路。先交代一下背景AC922 是 IBM 针对 AI 训练场景设计的双路 POWER9 服务器单颗 POWER9 有 44 核SMT4 下等效 176 线程关键是它每颗 CPU 通过 NVLink 直连 2 块 V100 GPUCPU-GPU 带宽远超传统的 PCIe 方案。这机器原配 4 卡我们手里这台实际能用的只有 3 卡第 4 卡硬件故障且暂时没货源所以标题就叫“三卡”。目标很明确让这台机器从裸机状态通过网络安装跑起最新系统装好驱动和 AI 软件栈最后把开源 LLM 在 3 张 V100 上并行跑起来做推理和实验。接下来全文分成五个部分先从项目拆解讲清楚整体思路然后一路讲网络安装、软件栈、三卡并行、问题排查几乎每一步都会带上我实测过的参数和踩过的坑。1. 项目整体设计和任务拆解1.1 为什么选 AC922 这种“非主流”机器跑 LLM大多数人做 LLM 实验第一反应是攒一台 x86 服务器插几块 RTX 4090 或者 A100。AC922 这种 Power 架构机器在圈子里属于异类但它当时被 IBM 专门用来对标 AI 训练市场的旗舰产品设计目标就是大规模深度学习训练。整机的核心卖点有三个POWER9 CPU 的高内存带宽、NVLink 直连 GPU、以及 CPU 对 GPU 的统一寻址能力。具体到我们这个场景为什么放着好好的 x86 不用非要啃这块硬骨头原因很现实这台机器是闲置资产配置白放着吃灰太可惜而且它的 NVLink 拓扑决定了在多卡训练和推理场景下通信效率比普通 PCIe 交换机方案高不少。V100 单卡 16GB 显存跑 7B 参数的量化模型勉强够但如果用 3 卡做张量并行就能把模型切分到三张卡上跑更大参数量的模型这正是 AC922 的用武之地。不过Power 平台的坑也显而易见软件生态远不如 x86很多基础组件没有现成的二进制包部分框架需要源码编译甚至操作系统的安装引导方式都和 x86 完全不同。所以动手之前我先把任务拆成了三条线操作系统部署、GPU 软件栈搭建、LLM 并行推理验证。三条线互相依赖任何一条断掉都跑不通后面所有工作基本都围绕这三条线展开。1.2 关键方案选型系统、引导方式、LLM 框架确定网络安装的第一步是选定操作系统。AC922 支持 RHEL、SUSE Linux EnterpriseSLE、Ubuntu 的 Power 版本。我最终选了 SUSE Linux Enterprise 15 SP5 的 ppc64le 版本原因是它在 POWER9 上的硬件支持最全内核自带的驱动和 petitboot 引导配合得比较好而且官方仓库里能直接拉到 CUDA 相关依赖。如果你更习惯 RedHat 系RHEL 9 for POWER 也可以但要注意版本必须选 ppc64le 架构不要下成 x86 的 ISO。引导方式也要提前定。Power 机器的固件是 OPAL引导层用的是 Petitboot——一个运行在 Linux 内核里的小型引导环境。它和 x86 上的 BIOS/UEFI GRUB 完全是两套思路网络安装不能照搬 x86 PXE 那套流程得用专门的方式把 Petitboot 的 netboot 镜像通过网络加载起来。这一步如果概念搞混后面 DHCP 配置、TFTP 路径全都会对不上。LLM 推理框架我选择了 vLLM做张量并行推理比较方便而且它对连续批处理和显存管理优化得很好。PyTorch 2.x 官方发布了 ppc64le 的 prebuilt wheel这是在 Power 上跑 LLM 的基础否则光是编译 PyTorch 就能耗掉半天。模型方面选了经典的 LLaMA-2 7B 量化版本GPTQ 4bit因为 V100 不支持 FP8 和 BF16 的 Tensor CoreFP16 下 7B 模型需要约 14GB 显存刚好卡在 16GB 的边缘量化之后压力小很多也方便后续做三卡并行时留出显存余量。2. 网络安装的完整实操记录2.1 POWER9 和 x86 网络引导的本质差异先帮大家把概念理清楚x86 的 PXE 引导过程是网卡固件通过 DHCP 拿到 IP 和 TFTP 路径然后下载 bootloader比如 GRUB/PXELINUX再通过 bootloader 加载内核和 initrd。而 Power 平台上的 Petitboot 本身就是一个完整的 Linux 环境它会在内存里运行一个小系统然后从各种源本地磁盘、网络、USB加载真正的安装程序。这就意味着网络安装时Petitboot 需要先通过 DHCP 获取网络配置再加载 petitboot 的 netboot 镜像进入 Petitboot 的 Shell接着才轮到安装器的内核登场。实际操作中我第一次就是按 x86 的思路配 DHCP option 67 指向grubaa64.efi结果机器压根不认。正确做法是DHCP 服务器上要同时提供 petitboot 的 netboot 镜像。以 dnsmasq 为例关键参数如下# /etc/dnsmasq.conf 的 PXE 部分 dhcp-range192.168.10.100,192.168.10.200,12h dhcp-boottag:power,petitboot-nettoot.img dhcp-optiontag:power,option:root-path,/srv/tftp dhcp-matchpower,option:client-arch,0xbclient-arch0xb是 PowerPC 的架构标识有了这个 tag只有 Power 客户端才会获取到对应的引导文件。TFTP 根目录/srv/tftp下放petitboot-nettoot.img这个镜像可以从 Petitboot 官方仓库或发行版提供的 netboot 包中获取。注意这个文件是给 Petitboot 自身用的和后面安装内核的 vmlinuz 完全是两回事别混在一起。提示如果 DHCP 服务器上还有别的设备在跑 PXE一定用 tag 区分客户架构否则 x86 设备会拿到 Power 的引导文件然后卡死。2.2 DHCP/TFTP/NFS/HTTP 一体化安装环境搭建我习惯用 dnsmasq 同时承担 DHCP 和 TFTP再单独起一个 NFS 或 HTTP 服务提供系统安装源。dnsmasq 配置里除了上面的引导参数还要注意分配 IP、网关、DNSdhcp-optiontag:power,option:router,192.168.10.1 dhcp-optiontag:power,option:dns-server,192.168.10.1 enable-tftp tftp-root/srv/tftp安装源我用的是 NFS。把 SLE 15 SP5 的 ppc64le DVD ISO 解压到/srv/install/sle15sp5然后导出 NFS# /etc/exports /srv/install/sle15sp5 192.168.10.0/24(ro,no_root_squash,no_subtree_check)为什么选 NFS 而不是 HTTP因为 Petitboot 和后续的安装程序对 NFS 源支持最成熟挂载后路径稳定不容易出现 HTTP 仓库源里相对路径解析失败的问题。如果你偏要用 HTTP也可以但一定要把整个 ISO 解压后的目录结构完整地映射到 Web 根目录下不能只放一个 ISO 文件否则安装器找不到仓库。之后启动 dnsmasq、NFS把机器网线插到对应交换机开机。Petitboot 会在启动时通过 DHCP 获取网络参数自动找到 TFTP 上的 netboot 镜像然后进入引导界面依次选择网络安装源加载安装内核。整个过程会走到一个文本界面的安装向导和 x86 的 Anaconda 类似但界面要朴素很多。2.3 分区、引导和固件参数避坑系统安装过程中有几个 Power 平台特有的点务必注意第一分区表建议用 GPT引导方式选“PREP 引导分区”PowerPC Reference Platform。在安装器的手动分区界面里需要划分一个 8MB 左右的 PREP 分区用来放引导程序再划分一个/boot建议 1GB其余给根目录和数据盘。如果没有 PREP 分区系统装完无法引导这一点是新手最容易踩的坑。第二系统的字节序必须是 little-endianppc64le。AC922 这类新平台只支持小端le安装盘镜像选错成 ppc64大端会直接无法启动。这点说起来简单但下载 ISO 时很容易忽略版本字符串里的le后缀我见过有人下了大端镜像折腾一整天才意识到类型不对。第三安装完首次重启建议立刻进 Petitboot 的 Shell 检查一下机器信息nvram -p这个命令查看的是 NVRAM 里的启动参数。常见的坑是启用了 Secure Boot但没导入对应的签名密钥导致 GRUB 被拒载遇到引导失败就优先看这里。另外如果机器之前跑过别的系统磁盘上可能残留旧的引导项Petitboot 会全部列出来要确认选中的是刚装好的那一个。系统起来后我通常会顺手做两件事一是把 SMT 开到最高POWER9 默认 SMT4但某些发行版默认 SMT1等于浪费了 4 倍的逻辑线程二是安装powerpc-utils工具包后面查 CPU 和电源信息都用得上。3. Power 平台上的 LLM 软件栈搭建3.1 CUDA 驱动的安装姿势和常用配置AC922 上的 V100 是 NVLink 版本需要 NVIDIA 官方提供的 Power 版驱动。和 x86 最大的区别是Power 平台没有“Nouveau 开源驱动抢占显卡”的问题安装前不需要像 x86 那样去 blacklist nouveau但需要内核头文件和 GCC 版本匹配。建议直接用 NVIDIA 提供的 runfile 安装这是我在 Power 上试过最稳的方案wget https://us.download.nvidia.com/tesla/535.161.08/NVIDIA-Linux-ppc64le-535.161.08.run chmod x NVIDIA-Linux-ppc64le-535.161.08.run ./NVIDIA-Linux-ppc64le-535.161.08.run --silent装完跑nvidia-smi如果能看到三张 V100 就说明驱动 OK。常见报错是 “Unable to load module nvidia”大概率是内核版本和驱动不匹配。解决方法是装驱动前先看uname -r再从 NVIDIA 官方选的对应版本。还有个小细节AC922 因为是 CPU 直连 GPU驱动加载后不要急着跑 CUDA 程序先确认 NVLink 状态执行nvidia-smi nvlink --status正常情况下三张卡之间应该显示 Active带宽速率是 NVLink2 的标称值。如果这里显示 Inactive说明虽然系统认到了卡但 NVLink 链路没起来后续多卡通信会退化为 PCIe性能大打折扣。我之前遇到过一次最后发现是 GPU 的电源线缆有问题重新插拔才解决。CUDA 本身我也装了 12.2 的 ppc64le 版本用官方 runfile 或 rpm 都行。需要注意Power 平台上 CUDA 的某些算子库如 cuDNN如果直接用 x86 的 tar 包去解压会报架构不支持。一定要下载 sbsa / ppc64le 专属包比如cudnn-linux-ppc64le-8.9.7_cuda12-archive.tar.xz。3.2 PyTorch 等 AI 框架在 ppc64le 上能用到什么份上这是整个项目里最“看人品”的部分。好消息是PyTorch 官方从 1.13 开始就持续发布 ppc64le 的预编译轮子直接 pip install 就能用。我用的版本是pip install torch2.1.2 torchvision0.16.2 --index-url https://download.pytorch.org/whl/cu121这里有个关键点--index-url必须明确指定 CUDA 版本的仓库默认的 PyPI 源虽然也有 Power 版但可能只带 CPU 版本没有 CUDA 支持跑 GPU 推理时会一直停留在 CPU 模式。装完后用torch.cuda.is_available()验证返回 True 才是真的把 CUDA 接上了。vLLM 这个框架的情况要复杂一些。它官方只发布 x86 的 wheelppc64le 需要源码编译。编译前建议先确认环境变量export MAX_JOBS16 export TORCH_CUDA_ARCH_LIST7.0 python setup.py installTORCH_CUDA_ARCH_LIST7.0对应 V100 的 Volta 架构这个参数能避免编译过程中 PyTorch 扩展四处找不存在的架构。整个 vLLM 源码编译在 AC922 上大约耗时 30~50 分钟取决于你给了多少编译线程和 CPU 核心。编译期间风扇声音会非常大属于正常现象。其他常用的组件比如 transformers、accelerate、bitsandbytes量化库大部分都有 ppc64le 的纯 Python 包或编译包直接 pip 即可。如果遇到某个包没有 Power 轮子优先看看有没有 AArch64 的轮子可以兼容尝试实在不行就只能源码编译了。我实测下来LLM 推理链路需要的核心依赖里最难搞的就是 vLLM其他基本都能顺利装完。3.3 三卡拓扑实测和显存/通信验证系统软件栈就绪后先做一个全面的硬件验证不要直接上模型否则出了问题都不知道是驱动问题还是框架问题。执行这几条命令nvidia-smi -L # 预期列出 3 张 Tesla V100-SXM2-16GB nvidia-smi nvlink --status # 预期显示 3 张卡的 NVLink 链路全部 Active nvidia-smi topo -m # 查看 NUMA 拓扑和 CPU-GPU 对应关系从实测看AC922 的拓扑是 CPU0 直连 GPU0/GPU1CPU1 直连 GPU2/GPU3。我们在用的三卡是 GPU0/1/2其中 GPU2 挂在 CPU1 上GPU0/1 在 CPU0 上。这带来一个调优点做张量并行时尽量让通信密集的进程绑定在同一个 CPU 管辖的卡上可以减少穿越 QPI 的延迟。不过由于三张卡最终都通过 NVLink 连到各自的 CPU实际通信和 x86 平台的 QPI/PCIe 组合相比已经好很多了。为了验证卡间通信带宽我用 PyTorch 写了个简单的 all_reduce 测试脚本看三卡之间的实际 P2P 传输速率。这个测试的意义在于提前暴露 NVLink 链路问题因为 LLM 的张量并行对通信带宽极度敏感。import os import torch import torch.distributed as dist os.environ[MASTER_ADDR] 127.0.0.1 os.environ[MASTER_PORT] 29500 os.environ[WORLD_SIZE] 3 os.environ[RANK] 0 dist.init_process_group(nccl, rank0, world_size3) t torch.ones(256, 256).cuda() dist.all_reduce(t, opdist.ReduceOp.SUM) print(fall_reduce ok, sum{t.sum().item()})跑的时候要配合torchrun --nproc_per_node3启动三个进程每个进程占一张卡。如果这一步能顺利通过三卡通信链路基本没问题后面可以放心跑模型。4. 三卡并行跑 LLM 的实操4.1 为什么选张量并行而不是数据并行很多人听到三卡第一反应是做数据并行DP/FSDP即每张卡放一个完整模型副本分批喂数据。但这是对 AC922 的错误用法。V100 单卡只有 16GB7B 模型即使量化后也有 4~5GB 权重加上 KV cache、激活值和 CUDA context单卡跑完整模型余量很紧张。更重要的是AC922 的 NVLink 直连通信能力最适合的是张量并行TP把模型权重按层切分到三张卡上每张卡只存 1/3 的权重推理时通过 NVLink 做 all-reduce 聚合。由于 NVLink 带宽远大于 PCIeTP 带来的通信开销小延迟低这是 AC922 的核心优势。vLLM 原生支持 TP在启动推理时直接指定--tensor-parallel-size 3就行。这里要提醒一句TP 的并行度最好能整除模型层数、注意力头数等维度通常是 2 或 43 这种“非对称”并行度有时会报错。不过 vLLM 对 TP3 的支持比我预期要好LLaMA-2 7B 直接跑没问题。如果遇到有的模型因为注意力头数无法被 3 整除报错可以用 TP1 的分片策略配合 KV cache 优化或者改用 pipeline parallelPP切层但配置复杂度会高不少。4.2 vLLM 启动参数和实测记录系统环境准备好后真正跑模型时的 vLLM 启动命令如下python -m vllm.entrypoints.openai.api_server \ --model /data/models/llama-2-7b-chat-gptq \ --tensor-parallel-size 3 \ --gpu-memory-utilization 0.90 \ --dtype float16 \ --max-model-len 2048 \ --quantization gptq \ --port 8000逐项解释一下关键参数--tensor-parallel-size 3三卡张量并行这是整个项目的核心。--gpu-memory-utilization 0.90允许 vLLM 使用单卡 90% 显存留 10% 给 CUDA context 和碎片。V100 16GB 卡7B 模型 4bit 量化后TP3 的显存占用大约每卡 3~4GB剩余空间可以给 KV cache正好适合 2048 上下文长度。--dtype float16V100 的 Tensor Core 支持 FP16但支持度不如 A100 全面GTPQ 量化后的权重按 FP16 计算效率和精度平衡比较好。--quantization gptq指定量化格式。如果你下载的是 GGUF 格式vLLM 会不太方便建议统一用 GPTQ 版本的模型。--max-model-len 2048限制最大序列长度这直接影响 KV cache 占用。7B 模型如果上下文设成 4096三卡也扛得住但我实测 2048 的综合吞吐更高能满足大部分测试需求。启动日志里最关键的几行是INFO: Model config: ... INFO: Loading model weights took X.XX GB INFO: GPU 0: 4.1 GiB, GPU 1: 4.2 GiB, GPU 2: 4.1 GiB INFO: Starting vLLM API server on http://0.0.0.0:8000如果三张卡的显存分配比较均匀说明 TP 切分成功。如果某张卡显存特别高而另一张几乎为空大概率是切分逻辑出了问题观察模型是否能正常响应。用 OpenAI 兼容接口跑几个测试请求用 curl 简单验证curl -X POST http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d {model: llama-2-7b-chat-gptq, messages: [{role: user, content: 写一段关于Python的简短介绍}], max_tokens: 200}第一次返回结果后我看了下生成速度大概 20~30 tokens/s对于 V100 组队的机器来说完全够用。而且整个推理过程中三张卡 GPU 利用率都稳定在 85% 以上证明并行切分是有效果的。4.3 性能调优三板斧SMT、NUMA绑定、电源模式模型能跑只是第一步。Power 平台上性能调优空间非常大我实测下面三项立竿见影第一确认 SMT 状态。AC922 的 POWER9 支持 SMT4也就是每个物理核同时运行 4 个线程。默认有时是 SMT1每个核只跑单线程等于把 CPU 算力砍了四分之三。用ppc64_cpu --smt4直接切换然后ppc64_cpu --info确认逻辑 CPU 数量从 88 变成 352。LLM 推理虽然算力瓶颈主要在 GPU但 vLLM 的调度器、tokenizer、预处理都跑在 CPU 上SMT4 开满对整体吞吐有帮助。第二NUMA 绑定。vLLM 的进程应该绑定在离 GPU 最近的 CPU 上。AC922 的 CPU0 管理 GPU0/GPU1CPU1 管理 GPU2。可以用numactl --cpunodebind0 --membind0启动主进程必要时再按 rank 拆成两个进程分别绑到两个 NUMA 节点。实测绑定后CPU 和 GPU 之间的数据传输延迟明显下降连续请求的 P99 延迟减少了 10% 左右。第三电源模式。Power 机器的默认电源策略偏保守GPU 频率可能被压在基础频率。检查一下ppc64_cpu --frequency如果频率明显低于标称值尝试切换电源模式到“性能优先”。某些固件版本里还有powerpc-utils提供的powernv相关参数可以调。另外AC922 支持 8 通道 DDR4 内存内存带宽很足但如果 BIOS/OPAL 层面开了内存镜像或冗余模式实际带宽可能减半有条件的话尽量关闭这些保守设置。5. 常见问题与排查技巧实录5.1 引导、驱动、框架三层问题速查表整个过程中我记录了一堆问题下面按层分类整理成表格。遇到类似问题可以直接对照排查现象可能原因排查和解决办法网卡找不到 DHCP 不分配 IPDHCP tag 未区分 Power 架构确认dhcp-matchpower,option:client-arch,0xb配置Petitboot 已启动但看不到安装内核TFTP 路径或文件名不对检查dhcp-boot指向的文件是否真实存在且有读取权限安装到一半找不到 NFS 源exports 配置或防火墙拦截showmount -e确认 NFS 导出firewall-cmd放行 NFS 服务nvidia-smi 报 “No devices”驱动和内核版本不匹配重新编译或安装对应内核版本的驱动必要时把内核升级到官方支持版本NVLink Active 但带宽低CPU/GPU 频率被限制检查电源模式关闭省电策略pip install torch 装成了 CPU 版未指定 CUDA 仓库源用--index-url https://download.pytorch.org/whl/cu121强制指定vLLM 编译报错缺少 CUDA.hCUDA 路径未导出在~/.bashrc添加export PATH/usr/local/cuda/bin:$PATH和export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATHvLLM 启动报 TP3 无法切分模型注意力头数不是 3 的倍数换 TP1 流水线或换模型结构也可以看是否支持 PP 参数推理时偶发 CUDA OOMKV cache 分配过大调低--gpu-memory-utilization到 0.85或减小--max-model-lenVRAM 分配不均一张卡占 90%其他空TP 未生效或 parallel 配置错误重启服务时确认日志中 3 张卡的显存占用关闭无用 CUDA context5.2 两次印象深刻的故障恢复过程值得单独说的是两个我卡了好久的故障每个都折腾了快一天。第一次是网络安装阶段所有配置看起来都对但 Petitboot 就是拿不到 DHCP 地址。后来才发现是机器上的网卡固件有个 bug部分网口在开机自检后没有置 up需要在 Petitboot Shell 里手动执行ip link set dev eth0 up再dhclient eth0。这个问题只在断电重启后偶发如果不清楚这个机制会一直以为 DHCP 服务器配置出了问题。第二次是 vLLM 编译完后一启动就报 NCCL 初始化失败。查了内核日志发现是nvidia-peermem模块没有加载这个模块是 NVLink 对等内存访问的关键vLLM 之类框架做跨卡通信时需要用到。解决办法是modprobe nvidia-peermem并把nvidia-peermem写进/etc/modules-load.d/保证开机自动加载。这个模块是 NVIDIA 驱动包自带的一般不需要额外安装但系统启动顺序如果不对就可能漏掉。5.3 一些零散但很管用的实操心得写到最后分享几条零散但很实用的经验。第一Power 平台的官方文档优先级高于一切。遇到问题先看 IBM 的 “Power Systems” 文档和 NVIDIA 的 ppc64le 驱动发行说明很多坑其实文档里都写过只是中文搜索不好找基本都是英文。第二所有安装脚本写完后先在一台测试环境跑一遍特别是那些改 NVRAM、改网络配置的命令。AC922 一旦引导配置乱了恢复起来比 x86 麻烦得多可能需要串口转接甚至重新刷固件。第三如果是给别人交付这套环境一定要记录显卡的序列号和 NVLink 拓扑图。因为 Power 机器上 GPU 和 CPU 的绑定关系是固定的换卡或改槽位可能导致 NVLink 拓扑变化进而影响性能。第四模型文件默认放本地磁盘没问题如果可能建议放 NVMe 盘而不是机械盘。加载 7B 的 GPTQ 文件大约 4GB机械盘读取要十几秒钟NVMe 只要两三秒实验迭代时的体感差别很大。说回这台 AC922虽然过程磕磕绊绊但最终三卡并行稳定跑起 LLaMA-2 7B 的那一刻我觉得之前所有的折腾都值了。Power 平台上跑 LLM 确实比 x86 要陡峭不少可一旦把引导、驱动、框架这条链路打通它的 NVLink 直连拓扑和多核 CPU 算力反而能带来一些 x86 平台不具备的优势。希望这份实战记录能帮你少走点弯路尤其是那些和我一样手上正好有台 Power 机器却不知道怎么下手的人。最后再分享一个小技巧AC922 的 BMC基板管理控制器支持远程串口和虚拟媒体如果你的机器不在手边强烈建议先把 BMC 网络配好后面所有安装和排错都能远程操作省去天天跑机房的痛苦。还有别忘了定期看 /var/log/messages 里的硬件错误日志Power 机器对内存错误很敏感尽早发现可以避免训练过程中突然宕机。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →