我上周刚好被问到这个问题两台GPU机器每台8卡想跑一个比较大的模型是不是得先把Ray搭起来这个问题其实挺有代表性的因为vLLM最近几个版本变化很大默认执行后端也不再强制绑定Ray了不少人是被旧教程带偏的。这篇就围绕“两台机器跑vLLM到底什么时候才值得引入Ray”这件事把判断逻辑、成本收益和实操流程都捋一遍。我默认你至少已经在一台机器上用vLLM部署过模型知道tensor-parallel-size是干什么的但如果只是刚接触也能跟着思路走重点看第3节和第4节的结论与命令。1. 先别急着上RayvLLM的分布式到底是按什么维度拆的很多人一提“多机跑模型”脑子里第一反应就是“要组Ray集群”。但实际上vLLM在一台机器内和跨机器分布的底层逻辑是两回事。搞懂了这个才知道Ray到底该不该出现在你的架构里。1.1 张量并行、流水线并行和数据并行vLLM各自是怎么处理的vLLM支持三种并行维度张量并行TP、流水线并行PP和数据并行DP。这三个词在推理场景里的含义和训练时略有不同需要分开理解。张量并行是把一个权重矩阵切碎分到多张卡上。比如tensor-parallel-size8就是让8张卡联合算同一个线性层。每前向一次卡之间都要做all-reduce通信量巨大。在单机内用NVLink或PCIe Switch通信成本可控一旦跨了机器走的是以太网或者IB性能就非常依赖网络带宽和延迟。所以vLLM跨节点的TP实际是小众需求。流水线并行则按层切分卡0算完第1到第N层把中间激活传给卡1继续算。通信量远小于TP但对显存的均匀分布有要求而且会产生流水线气泡。vLLM里PP的成熟度和易用性一直不如TP我自己踩过几次坑之后除非模型大到单卡根本放不下否则不优先考虑。数据并行在推理里不是真正的“数据并行”而是同一个模型的多个副本同时处理不同请求。vLLM天然就能在多实例或多DP组之间分摊请求不需要额外的权重同步。这也是为什么两台机器各跑一个实例、前面挂个负载均衡这么朴素的做法在吞吐场景里效果反而很好。1.2 Ray在vLLM里到底是干什么的从调度器到执行器vLLM和Ray的关系有个演变过程。早期版本直接在内部依赖Ray来启动多卡worker哪怕是单机多卡也要装Ray。后来vLLM引入了自己的multiprocessing执行后端单机内默认不再依赖Ray。现在的架构里Scheduler和Executor分离Ray主要作用在Executor这一层负责跨节点的worker调度、显存资源感知和任务分发。因此在最新版本中Ray在vLLM中的角色已经被压缩成“跨节点执行器协调器”。如果模型能在一台机器装下vLLM用的是自带的多进程后端还是Ray性能差距不大反而去掉Ray还能少一层依赖。真正离不开Ray的场景是vLLM必须感知到另一台机器上的GPU并且把这些GPU作为同一个计算图的一部分来调度。1.3 一个容易被忽略的关键事实单机多卡不需要Ray也能跑vLLM默认的单卡或单机多卡启动连安装都不一定需要ray[default]。在装有2张A100的机器上直接跑vllm serve meta-llama/Llama-3.1-70B-Instruct \ --tensor-parallel-size 2 \ --gpu-memory-utilization 0.9这个命令内部会用multiprocessing拉起2个worker不会隐式去连Ray。只有当你在启动参数里明确指定--distributed-executor-backend ray或者确实需要跨节点执行时vLLM才会去找一个可用的Ray集群。明白了这一层再回头看“两台机器要不要上Ray”这个问题本质就变成了你到底是想把两台机器合并成一台大机器还是只是多拿一台机器分摊请求2. 两台机器跑vLLM先看三种常规方案再决定工具买了两台8卡机器很多人第一反应是把它们“捏”成一台16卡机器。但捏在一起是不是最优解取决于你的模型和服务目标。这里展开三种方案我逐一说明适用场景。2.1 方案A两台各自独立提供服务外层负载均衡这是最常见、也最稳的方案。机器A和机器B各跑一份vLLM服务比如都加载同一个Qwen2.5-72B各自--tensor-parallel-size 8然后用Nginx、HAProxy或者一个轻量级的路由层把请求分发到两个IP上。这种做法的好处是故障域小。机器A挂了B还在跑不会整个服务不可用。吞吐量方面因为是两份独立实例等于天然的数据并行可以线性吃满两台机器的算力。缺点是显存被两份模型参数重复占用模型权重各存一份等于可用的“总面积”打了对折。因此这个方案适合模型显存占用不超过单机容量一半的场景。以两台8卡A100 80G为例单机可用的模型显存约640G但一般只能用到90%也就是576G。跑Llama-3.1-70B这类量化或BF16权重大约需要140G单机放两份都绰绰有余走方案A非常划算。甚至如果是部署DeepSeek-R1这种671B的MoE模型方案A直接失败因为单台放不下完整权重这就引出方案B。2.2 方案B跨节点TP把两台机器合并成一个“大卡池”当模型权重大到单机装不下或者需要超大KV Cache来支撑超长上下文时就必须让模型权重跨机器切分。启动时设置--tensor-parallel-size 16让vLLM把16张卡组成一个TP组。跨节点TP需要一套机制在机器之间交换中间激活这是Ray出场的第一个必要条件。但同时要注意跨节点TP对网络极其苛刻如果两台机器之间只有1Gbps以太网TP16带来的通信开销可能让吞吐还不如单机TP8跑同模型的子集。跨节点TP真正可行一般要求节点间至少10Gbps以上网卡理想情况是InfiniBand或RoCE并且要配置好NCCL。还有一个容易被忽视的隐性成本故障域扩大。两台机器合体后只要一张卡出问题整个16卡的服务全挂。这跟方案A的可用性水平完全不在一个量级。2.3 方案C用Ray Serve做统一服务编排兼顾路由和扩缩容第三种形态是典型的Ray应用场景用Ray Serve承载vLLM的多个实例而不是用vLLM自带的--api-server。你可以在一套Ray集群里同时跑多个模型副本设置自动扩缩容策略比如每个副本至少保留1个负载高时自动再加1个实例。Ray Serve还能做版本路由、灰度发布和多模型分治。这个方案和方案A的区别在于编排粒度。方案A是两台机器各自为政方案C是把两台机器纳入一个集群视图统一管理副本数和部署单元。如果你只是两个模型固定跑方案C带来的收益不明显但如果你要频繁更新模型、做多租户路由或者需要根据请求量自动增减实例Ray Serve这套能力就非常值钱。3. 什么时候才值得引入Ray算一笔成本收益账引入Ray不是零成本。哪怕现在的vLLM对Ray已经很透明部署Ray集群依然会引入新的进程、新的端口、新的故障模式。所以我习惯把“值不值得”拆成四个维度打分。3.1 Ray真正提供的三项核心能力全局调度、资源感知、弹性伸缩Ray不可替代的三项能力对应三类需求。第一是全局调度Ray可以同时管理两台机器上的GPU资源vLLM要跨节点拉worker时只需要问Ray要资源而不用自己维护节点列表。第二是资源感知Ray知道哪张卡空闲、哪张卡还跑着别的任务可以避免资源冲突。第三是弹性伸缩Ray集群允许随时加节点、减节点结合Ray Serve自动扩缩容比手工管理多机服务轻松得多。但这三项能力都在“服务编排层”工作vLLM自身的模型执行并不需要它们参与。如果你的场景只是固定跑一个模型不需要动态加卡不需要自动扩容那这三项能力只有“跨节点执行”这一项可能用到。3.2 引入Ray的成本部署复杂度、故障域和版本耦合我见过不少团队在生产环境不敢用Ray核心原因不是Ray本身不稳定而是又多了一个分布式系统要维护。部署Ray要管主节点的GCSGlobal Control Store、Dashboard、Worker节点间的内部通信vLLM升级如果锁的Ray版本不一致还可能出现启动失败。另外Ray主节点是集群的“单片玻璃”它挂了整个集群的任务状态和服务发现都会受影响。还有一点容易踩坑在Kubernetes里跑Ray需要处理Ray head的固定地址、PVC、探活等一堆细节在裸机上组Ray则要注意防火墙放行端口。这些成本都是实打实的。为了量化我习惯用这样一张决策表来判断场景单机可装下模型权重需要自动扩缩容需要跨节点共享显存结论多实例负载均衡是否否不用Ray直接多开实例超大模型跨机TP否否是需要Ray否则无法启动动态伸缩/灰度发布任意是否用Ray Serve但可不用Ray做TP执行多模型统一路由任意任意否可选Ray Serve非必须3.3 我推荐的判断公式先看模型显存再看运维目标我把自己的判断逻辑总结成一句话“只有模型在单台装不下或者你明确需要动态编排时才值得为两台机器引入Ray。”具体判断顺序是先用显存估算工具或人工估算模型权重KV Cache需要多少显存如果单机可用显存够就不要碰跨节点TP此时第二台机器拿来跑另一个实例或是跑不同模型都比硬合体更划算。如果模型确实大到单机装不下比如DeepSeek V3/R1这类MoE大模型继续看你的网络条件有没有高速互联能不能承受NCCL通信开销如果没有跨节点TP本身就是伪需求这时该做的是模型剪枝、量化或者换更小的模型。只有在“模型必须跨机器切分”和“网络条件允许”两个条件都成立时Ray才从“可选”变成“必须”。这和你用了多少台机器没有必然关系只和模型尺寸与单机容量有关。4. 双机Ray集群驱动vLLM实操记录从零到跑通如果你确认走到了必须用Ray的那一步下面这套流程可以照着执行。我用两台8卡A100服务器做过同样的部署这里把关键的坑都标出来。4.1 环境准备统一镜像和依赖版本是第一优先级跨节点分布式执行最容易翻车的地方不是Ray本身而是两台机器的环境不一致。CUDA版本、PyTorch版本、vLLM版本、Ray版本任何一项不一致都可能让worker之间出现奇怪的兼容性问题。建议的做法是直接用Docker镜像以vLLM官方镜像为基础锁定版本tag比如vllm/vllm-openai:v0.27.1然后在两台机器上都用同一镜像启动容器。容器内额外装Ray命令大致为pip install ray[default]2.31.0这里提醒一下vLLM升级频繁换了新版本往往伴随性能变化这是社区里常提到的问题。生产环境务必锁定vLLM版本不要随手latest。镜像打好后在两台机器上都验证一下能不能正常执行单机命令确认GPU能被容器看到再继续。4.2 启动Ray集群Head节点和Worker节点怎么配假设机器A的IP是192.168.1.10机器B是192.168.1.11。在机器A上启动Ray headray start --head --port6379 --dashboard-host0.0.0.0 --num-gpus8这里--dashboard-host0.0.0.0是为了让另一个节点也能访问Dashboard--num-gpus8让Ray显式感知到8张卡。如果不写Ray可能因为看不到GPU资源导致后续vLLM找不到卡。机器B上执行ray start --address192.168.1.10:6379 --num-gpus8启动后在任意一台机器执行ray status确认两个节点都在线、GPU数量合计为16。这一步如果看不到节点优先排查6379端口连通性和防火墙。Ray Head默认还会监听8265端口提供Dashboard浏览器访问http://192.168.1.10:8265能看到节点和GPU资源列表。4.3 用vLLM加载超大模型并验证跨节点TPRay集群就绪后在机器A的容器内启动vLLM服务。注意要显式指定使用Ray作为后端vllm serve /models/deepseek-v3 \ --tensor-parallel-size 16 \ --distributed-executor-backend ray \ --gpu-memory-utilization 0.85 \ --max-model-len 8192 \ --trust-remote-code这里的关键参数是--distributed-executor-backend ray它告诉vLLM通过ray.init(addressauto)连接现有集群而不是启动本地multiprocessing。启动日志里如果能看到类似“Connecting to existing Ray cluster”的字样说明vLLM正确识别了双机集群。启动完成后用curl验证一下服务是否正常curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d {model: /models/deepseek-v3, messages: [{role: user, content: 你好}]}4.4 网络和存储的实测要点别让NCCL拖垮吞吐跨节点TP对网络环境的依赖性在实操里体现得很充分。第一次跑16卡TP时如果推理极慢大概率是NCCL选错了网络接口。建议在启动vLLM前设置export NCCL_SOCKET_IFNAMEens5 export NCCL_IB_DISABLE1ens5替换为你机器上的实际高速网卡名。如果不设置NCCL可能会去走管理口或者docker网桥通信性能一落千丈。如果机器间有RDMA或RoCE还需要额外配置NCCL_IB_HCA等参数这里不展开。存储同样要考虑。两台机器如果要读同一个模型权重目录最好用共享存储挂载到相同路径或者确保路径在每台机器上都存在且内容一致。vLLM跨节点启动时每个worker都要读取权重文件如果只有机器A有模型文件机器B的worker就会报找不到文件的错。5. 常见问题与排查实录我踩过的那些坑分布式部署的问题往往不像单机那么直观我整理了最常遇到的几类问题按排查顺序给到参考。5.1 Ray集群启动正常但vLLM找不到足够GPU现象ray status显示16卡但vLLM启动时报GPU数量不足或者tensor_parallel_size超过可用卡数。排查思路先看vLLM日志里Ray的节点视图是否完整。如果只看到本机8卡说明另一台机器的GPU没有被Ray感知。检查worker节点启动时是否指定了--num-gpus以及ray head的Dashboard里GPU有没有显示为1.0。另一个常见原因是vLLM的worker和Ray的资源配置不在同一套资源组里这时给worker节点设置自定义资源标签比如ray start --address192.168.1.10:6379 --num-gpus8 --resources{nodeB_gpu: 8}5.2 NCCL初始化超时或通信失败现象vLLM启动到一半卡住日志出现NCCL相关错误或者首次请求耗时极长。排查思路先用nccl-tests或者简单的深度学习通信测试脚本确认两卡之间的NCCL通信是否正常。重点看两个方向端口是否被封NCCL使用TCP时会随机使用端口尤其是UDP端口以及网卡选择是否错误。设置NCCL_DEBUGINFO重新启动日志里会明确打印用的哪块网卡、哪个IP。如果网络本身就不达标跨节点TP再怎么调参也是负优化这时候回头考虑减小TP或者换方案。5.3 性能不升反降甚至不如单机跑小模型现象两台机器合体后吞吐量并没有翻倍反而明显下降。排查思路很遗憾这在跨节点TP场景里太常见了。原因主要有三类节点间网络带宽不够、TP通信次数过多、KV Cache碎片化导致有效吞吐下降。先把网络延迟和带宽测试一遍如果只有1Gbps网络建议直接放弃跨节点TP如果是10Gbps以上还要确认是否启用了巨型帧MTU 9000以及NCCL是否走对了网卡。其次检查--gpu-memory-utilization不要把显存拉满到0.95留出NCCL buffer空间往往能减少通信抖动。5.4 避坑清单速查问题常见原因解决动作Ray节点互相看不到防火墙/安全组未放行6379放行6379、8265及内部通信端口vLLM找不到模型文件权重只存在一台机器使用共享存储或同步权重到所有节点跨节点TP启动极慢NCCL选错网卡或网络不通设置NCCL_SOCKET_IFNAME用NCCL_DEBUGINFO定位吞吐比单机还差节点间带宽不足降TP、改多实例负载均衡方案vLLM新老版本性能变化未锁定镜像版本固定vLLMRay版本升级前做基准测试这里再提一个个人习惯我刚接触vLLM多机部署时总是先想“怎么把Ray配置出来”后来发现顺序反了。正确顺序是先确定“要不要跨节点”再确定“要不要Ray”。遇到性能问题先怀疑网络和配置不要第一时间怀疑Ray本身。毕竟大多数场景下Ray只是个传令兵真正拖后腿的往往是节点之间的物理链路。最后分享一个小技巧如果你只是想验证跨节点TP在你的网络环境里能跑到什么水平不必急着加载大模型可以先在两个节点上各跑几个小的矩阵乘法通信测试看看传输延迟和带宽。这个成本极低却能帮你避开一整个下午的无效调试。两台机器本身不是问题问题在于你希望它们怎么协作想清楚了再动手Ray就是顺手的工具而不是负担。
阅读完成 · 觉得有帮助?