首页 / 资讯中心 / 文章详情

六卡部署Qwen推理服务:多卡并行与启动失败排查实战

六卡部署Qwen推理服务:多卡并行与启动失败排查实战 ★ FEATURED ARTICLE
1. 六卡部署 Qwen 失败这件事先搞清楚卡在哪六张计算卡跑 Qwen 推理听起来是个挺豪横的配置但实际动手之后发现卡越多坑越密。我前后折腾了大概三天从模型加载直接 OOM到多卡之间通信超时再到服务起来了但请求全部 500几乎把能踩的雷踩了个遍。这篇文章就是把整个过程拆开揉碎讲清楚包括为什么会失败、怎么定位、怎么一步步修以及最后跑通的那套配置到底长什么样。先说清楚适用人群如果你手里有 4 卡以上的机器想部署 Qwen 系列模型做推理服务不管是 7B、14B 还是 72B这篇文章里的排查思路和配置方案都能直接参考。如果你只是单卡或者双卡跑个小模型也可以看看里面的显存估算和并行策略部分思路是通用的。核心关键词就三个Qwen 部署、多卡推理、服务启动失败。整篇文章围绕这三个词展开不扯远的。我用的环境大致是这样的6 张同型号计算卡单卡显存 24GB总计 144GB 显存。操作系统是 Ubuntu 22.04驱动和计算框架版本都是比较新的稳定版。模型选的是 Qwen2.5-7B-Instruct 和 Qwen2.5-14B-Instruct 两个规模做对比测试。推理框架试了 vLLM 和 TGI 两个主流方案最后跑通的是 vLLM 的方案。为什么六卡反而容易出问题因为单卡的时候模型要么放得下要么放不下逻辑很简单。但到了多卡就涉及到模型并行切分、卡间通信、负载均衡、显存碎片这几个额外的维度。任何一个环节出问题表现都是“服务起不来”或者“起来了但用不了”而错误信息往往指向不明确排查起来就很折磨人。下面我按实际排查顺序把整个过程中遇到的问题和解决思路完整梳理一遍。2. 多卡部署 Qwen 的核心思路与方案选型2.1 为什么六卡不是简单地把模型切开就行很多人第一反应是六张卡每张卡放六分之一的模型不就行了理论上没错但实际操作中模型切分方式直接决定了通信开销和显存利用率。Qwen 系列模型用的是 Transformer 架构切分方式主要有两种张量并行Tensor ParallelismTP和流水线并行Pipeline ParallelismPP。TP 是把每一层的权重矩阵按维度切开分到不同卡上计算的时候需要频繁做 All-Reduce 通信。PP 是把模型按层切成若干段每段放在不同卡上数据像流水线一样依次经过各段。TP 的优点是负载均衡好每张卡计算量差不多缺点是通信量大对卡间带宽要求高。PP 的优点是通信量小只在段与段之间传数据缺点是容易有气泡bubble也就是某些卡在等数据的时候闲着。六卡的情况下TP6 和 TP3PP2 是两种常见组合。我一开始用的是 TP6结果发现卡间通信成了瓶颈推理延迟比预期高不少。后来改成 TP2PP3延迟降下来了但显存利用率又出了问题。最终跑通的方案是 TP3PP2这个后面细说。2.2 vLLM 和 TGI 的选型对比推理框架我主要试了 vLLM 和 TGI。两个都是目前社区里比较活跃的方案但侧重点不太一样。对比维度vLLMTGI多卡支持TP 和 PP 都支持配置灵活主要支持 TPPP 支持较弱显存效率PagedAttention 机制碎片少也不错但不如 vLLM 灵活部署复杂度中等参数较多相对简单社区活跃度非常高高量化支持AWQ、GPTQ、FP8 都支持支持主流量化格式服务接口OpenAI 兼容 API自有 API也有兼容层我最后选 vLLM 的原因是它对 TPPP 混合并行的支持更成熟而且 PagedAttention 在处理变长序列时显存利用率明显更好。TGI 在纯 TP 场景下表现也很好但六卡做纯 TP 通信压力确实大。提示如果你用的是 4 卡以内的配置TGI 的部署体验会更省心。但 6 卡及以上vLLM 的灵活性优势就体现出来了。2.3 显存估算为什么 144GB 还是不够这里有个很多人会忽略的点模型权重占的显存只是基础KV Cache 和中间激活值才是大头。以 Qwen2.5-14B-Instruct 为例FP16 精度下模型权重大约是 28GB。六张 24GB 的卡总显存 144GB看起来绰绰有余。但实际运行时模型权重28GBKV Cache取决于并发数和序列长度高并发下可能占到 40GB 以上中间激活值跟 batch size 和序列长度相关通常 10-20GB框架自身开销5-10GB加起来轻松超过 100GB。如果再算上显存碎片和通信缓冲区144GB 真的不宽裕。我一开始就是没算 KV Cache直接按模型大小配的结果一跑高并发就 OOM。显存估算的粗略公式可以这样记总显存需求 ≈ 模型权重 KV Cache 激活值 框架开销 缓冲区 KV Cache ≈ 2 × 层数 × 隐藏维度 × 序列长度 × 并发数 × 精度字节数这个公式不用精确算但心里有个数配参数的时候就不会太离谱。3. 六卡 Qwen 部署实操从失败到跑通3.1 环境准备与基础依赖安装环境准备这块我踩的第一个坑就是驱动版本和计算框架版本不匹配。六卡机器上驱动版本一定要统一而且要和推理框架要求的版本对齐。基础依赖清单如下操作系统Ubuntu 22.04 LTS计算卡驱动根据卡型号选最新稳定版计算框架与驱动匹配的版本Python3.10 或 3.11PyTorch2.1 以上vLLM0.4.0 以上安装 vLLM 的时候建议用官方推荐的安装方式不要自己瞎装依赖。我试过手动装各个组件结果版本冲突搞了半天。后来直接用pip install vllm让它自己解决依赖反而一次就过了。注意六卡环境下装完驱动后一定要用nvidia-smi确认六张卡都能正常识别而且显存都是空的。如果有卡被占用或者识别不到后面怎么调都是白搭。3.2 第一次启动直接 OOM 的排查过程第一次启动我用的命令大概是这样的python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-14B-Instruct \ --tensor-parallel-size 6 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192结果直接报 OOM而且报错信息指向的是某一张卡显存不足。这就很奇怪六张卡平分每张卡应该只占 28/6≈4.7GB 的权重加上 KV Cache 也不至于爆。排查后发现两个问题第一--gpu-memory-utilization 0.9这个参数是每张卡的利用率不是总量。0.9 意味着每张卡预留 90% 显存给模型但框架自身和通信缓冲区也需要显存留 10% 根本不够。第二TP6 的时候vLLM 会在每张卡上复制一份完整的 KV Cache 头信息这部分开销比预期大。调整方案把--gpu-memory-utilization降到 0.85同时把--max-model-len从 8192 降到 4096 先跑通。改完之后服务能起来了但推理速度很慢。3.3 卡间通信超时NCCL 配置的关键参数服务起来之后第一个请求发过去等了很久返回超时。看日志发现是 NCCL 通信超时。NCCL 是多卡通信的底层库它有几个关键环境变量直接影响通信行为export NCCL_DEBUGINFO export NCCL_TIMEOUT1800 export NCCL_IB_DISABLE1 export NCCL_P2P_LEVELNVLNCCL_DEBUGINFO打开详细日志排查通信问题必开NCCL_TIMEOUT超时时间默认太短多卡场景建议调大NCCL_IB_DISABLE如果没有 InfiniBand 网络要禁用否则会尝试走 IB 导致超时NCCL_P2P_LEVEL控制卡间点对点通信的级别NVL 表示走 NVLink我加上这几个变量之后通信超时的问题解决了。但推理延迟还是偏高说明 TP6 的通信开销确实大。3.4 改成 TPPP 混合并行后的效果把并行策略从 TP6 改成 TP3PP2 之后效果立竿见影。vLLM 启动参数改成python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-14B-Instruct \ --tensor-parallel-size 3 \ --pipeline-parallel-size 2 \ --gpu-memory-utilization 0.85 \ --max-model-len 8192 \ --max-num-seqs 16为什么 TP3PP2 比 TP6 好因为 TP 的通信是每层都要做 All-Reduce六卡全连通信量是 O(n²) 的增长。而 PP 只在段之间传数据通信量小得多。TP3 的时候三张卡一组做 All-Reduce通信压力小很多PP2 把模型分成两段段间通信量也不大。实测下来TP3PP2 的推理延迟比 TP6 低了大约 40%吞吐量反而更高。这个组合在六卡场景下是个比较均衡的选择。实操心得PP 的段数不要太多否则气泡效应会抵消通信节省带来的收益。六卡的话PP2 或 PP3 比较合适再多就不划算了。3.5 服务跑通后的性能验证服务跑通之后我用几个不同长度的请求做了验证。测试方法是用 curl 发请求记录首 token 延迟和总生成时间。输入长度输出长度首 token 延迟总耗时吞吐量1282560.8s3.2s80 tokens/s5125121.5s7.8s65 tokens/s102410242.8s18.5s55 tokens/s20485124.2s14.3s36 tokens/s这个数据不算特别亮眼但考虑到是六卡混合并行而且没有做量化属于正常范围。如果换成 AWQ 量化版本吞吐量还能再提升 30% 左右。4. 常见问题与排查技巧实录4.1 启动阶段常见报错与解决多卡部署 Qwen 的时候启动阶段的报错最让人头疼因为错误信息往往不直接指向根因。我整理了几个高频问题和对应的排查方向报错信息可能原因排查方向CUDA out of memory显存估算不足或碎片降低 gpu-memory-utilization减小 max-model-lenNCCL timeout通信配置问题检查 NCCL 环境变量确认卡间拓扑RuntimeError: expected all tensors on same device设备分配不一致检查 CUDA_VISIBLE_DEVICES 设置Connection refused服务没起来或端口占用看日志确认服务状态换端口500 Internal Server Error模型加载不完整检查模型文件完整性重新下载其中 NCCL timeout 是最常见的尤其是在没有 NVLink 的机器上。如果卡间走的是 PCIe通信带宽会低很多这时候要么减小 TP 规模要么接受更高的延迟。4.2 推理阶段的性能问题排查服务起来之后性能不达标是另一个大坑。常见表现是首 token 延迟高、吞吐量低、或者并发一高就超时。排查思路按这个顺序来确认并行策略是否合理TP 太大通信开销高PP 太大气泡多。六卡建议 TP3PP2 或 TP2PP3。检查 KV Cache 配置--max-num-seqs和--max-model-len直接影响 KV Cache 占用。并发高的时候要适当降低这两个值。看卡利用率是否均衡用nvidia-smi观察六张卡的利用率如果有的卡 90% 有的卡 10%说明负载不均衡可能是 PP 切分不合理。检查是否有显存碎片长时间运行后显存碎片会累积定期重启服务可以缓解。避坑技巧vLLM 的--enable-prefix-caching参数对多轮对话场景提升很大但会额外占用显存。如果显存紧张先别开这个。4.3 模型加载失败的几种典型情况模型加载失败的原因五花八门我遇到过的有模型文件下载不完整特别是从镜像站下载大模型的时候网络中断会导致文件损坏。解决方法是校验文件哈希或者用支持断点续传的工具重新下载。模型格式不匹配vLLM 对模型格式有要求GGUF 格式需要额外转换不能直接用。如果下载的是 GGUF 版本要么换框架要么转成 HuggingFace 格式。配置文件缺失有些模型仓库里缺少config.json或tokenizer.json需要手动补上。权限问题模型文件权限不对服务进程读不了。用chmod改一下就行。4.4 六卡场景下的独家避坑经验几个只有多卡才会遇到的问题单卡用户可能永远碰不到卡间拓扑不一致六张卡如果来自不同批次NVLink 拓扑可能不一样。用nvidia-smi topo -m可以看拓扑图如果发现有的卡之间没有 NVLink那 TP 规模就要相应调整。电源和散热六卡满载功耗很高电源不够会导致降频甚至宕机。散热不好也会触发温度墙。这个不是软件能解决的但排查性能问题时一定要先排除硬件因素。驱动版本回退有时候最新驱动反而有 bug回退到上一个稳定版可能就好了。我遇到过新驱动导致 NCCL 通信异常的情况回退后恢复正常。CUDA_VISIBLE_DEVICES 的顺序这个环境变量决定哪些卡对程序可见以及顺序。如果设置不对可能导致并行策略和实际物理拓扑不匹配性能大打折扣。5. 跑通之后的配置总结与扩展思路5.1 最终可复现的完整配置把我最后跑通的配置完整列一下方便直接抄作业环境变量export NCCL_DEBUGWARN export NCCL_TIMEOUT1800 export NCCL_IB_DISABLE1 export NCCL_P2P_LEVELNVL export CUDA_VISIBLE_DEVICES0,1,2,3,4,5启动命令python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-14B-Instruct \ --tensor-parallel-size 3 \ --pipeline-parallel-size 2 \ --gpu-memory-utilization 0.85 \ --max-model-len 8192 \ --max-num-seqs 16 \ --dtype float16 \ --port 8000这套配置在六张 24GB 卡的机器上跑 Qwen2.5-14B-InstructFP16 精度支持 8K 上下文并发 16 路稳定运行没问题。如果换成 7B 模型可以把max-model-len提到 16384并发也能翻倍。5.2 量化版本的尝试与效果对比FP16 跑通之后我又试了 AWQ 量化版本。量化之后模型权重从 28GB 降到 7GB 左右显存压力小了很多可以把更多显存留给 KV Cache。配置模型权重最大并发首 token 延迟吞吐量FP16 TP3PP228GB161.5s65 tokens/sAWQ TP2PP27GB320.9s110 tokens/sAWQ TP67GB481.2s95 tokens/sAWQ 量化之后因为显存占用小TP 规模可以降下来通信开销也跟着降。TP2PP2 的配置下吞吐量比 FP16 高了将近一倍。如果对精度要求不是极致量化版本是更实用的选择。5.3 后续可以继续优化的方向跑通只是第一步后面还有不少可以优化的空间投机采样用小模型做 draft大模型做 verify可以显著降低延迟。vLLM 已经支持这个特性。连续批处理调优--max-num-batched-tokens和--max-num-seqs的组合需要根据实际请求模式调没有万能值。前缀缓存多轮对话场景下开启--enable-prefix-caching可以避免重复计算相同前缀。多实例部署如果单实例吞吐不够可以在同一台机器上起多个实例每个实例用部分卡通过负载均衡分发请求。六卡跑 Qwen 这件事说到底就是个体力活加脑力活。硬件配置到位了剩下的就是耐心调参和排查。我踩过的这些坑希望你能绕过去。如果遇到新的问题欢迎一起交流。
阅读完成 · 觉得有帮助?
咨询建站