☰
多台DGX Spark组网构建大模型推理集群实践
2026/10/20 7:36:41 网站建设 项目流程

事说起因也挺简单:我手上陆续到了几台 DGX Spark,一开始只是当成单机推理盒子用,跑跑量化模型、做点 RAG demo 都挺顺手。但没过多久就发现单台的天花板太明显了——大模型权重大、并发一上来就卡,想要长上下文更是捉襟见肘。于是我把多台 DGX Spark 用高速网络组成了一个多节点集群,把一个大模型切碎了分别加载到每台机器上,对外提供一个统一的推理服务。这篇文章就是这套方案的完整记录:为什么这么组、网络怎么调、推理引擎怎么配、实测数据怎么样,以及我踩过的一堆坑。

本文适合手头有多个 DGX Spark(或类似单机大显存设备)的开发者、算法工程师和企业私有化部署团队参考。如果你正在纠结“单机跑不动/跑得慢,上专业 GPU 服务器又太贵”,那这篇内容应该能给你一个折中且可落地的方案。

1. 为什么要把 DGX Spark 组网成集群

1.1 单台 DGX Spark 的脾气

先说清楚这台机器的定位。DGX Spark 用的是某头部芯片厂的 GB10 超级芯片,CPU 和 GPU 封装在一块 SoC 里,对外提供 128GB 的统一内存/显存。注意,它不是传统显卡那样的独立 HBM 显存,CPU 和 GPU 共用这一大块内存,官方标称算力不低,跑 FP4/FP8 的推理表现相当猛。

这带来一个很实际的收益:一个 70B 级别的开源对话模型,FP8 量化后权重差不多 70GB,单台 DGX Spark 确实能塞进去,这一点比绝大多数显卡都从容。很多 80GB 显存的显卡反而装不下,得做更狠的量化或者上多卡。

但它的弱点也恰恰在这块统一内存上。内存带宽和 HBM 不是一个量级,通俗点说就是“仓库特别大,但传送带偏窄”。单台机器跑大模型,权重读取、KV cache 写入全挤在这条传送带上,模型越大越吃亏。实测下来,70B 模型单机跑,单并发还能看,一旦并发请求上来,tokens/s 掉得很快;想开 32K 长上下文再加上几个并发,基本就被内存带宽卡得死死的。

1.2 多节点带来的收益不只是“能跑”

把多台 DGX Spark 连成一个集群,核心手段是张量并行:一个大模型的每一层权重,按行或按列切分成 N 份,分别加载到 N 台机器上。计算一个 token 时,每台只算自己的那份,算完通过高速网络做一次 AllReduce 汇总。

这么做的收益有两个,一般人只注意到第一个。

第一个收益是容量。单机 128GB 听着不小,但模型权重只是一部分,KV cache 也要吃内存,上下文越长、并发越多,KV cache 占用越大。集群把多台机器的内存/显存池化,70B 模型拆到 4 台机器上,每台只放 1/4 权重,省下来的空间全部可以分给 KV cache,长上下文和并发处理能力瞬间宽裕。

第二个收益是性能。每台机器只算部分权重,单 token 的计算延迟实际上变短了,虽然多了一部分网络通信开销,但整体吞吐往往是净提升。我后面会放实测数据,单机 8-10 tokens/s 和四机 30+ tokens/s 的差距不是一点半点。

再解释一下“共享大模型”里的“共享”二字,它有两层意思:

  • 模型层面共享:一个模型分散在多台机器的内存里,作为一个整体对外服务;
  • 服务层面共享:多用户、多应用同时请求这一个模型服务,推理引擎统一调度。

这也是我选择 vLLM 做推理引擎的原因,它天然支持多节点张量并行、连续批处理和高并发请求调度,刚好覆盖这两个需求。

必须说清楚边界:这套多节点 DGX Spark 集群适合做推理、LoRA 微调、RAG 服务这类任务,不适合做大规模预训练。原因还是网络和内存带宽,训练过程通信量比推理大一个量级,4 台机器的以太网(哪怕是高速 RDMA)也顶不住频繁的梯度同步。硬要训练的话,效率会非常难看。

2. 集群网络和底层软件环境

2.1 网络拓扑怎么选

组多节点集群,第一步不是装软件,而是把网络想清楚。DGX Spark 板载了 400Gb/s 级别的高速网卡,默认支持 RoCE(RDMA over Converged Ethernet),这是整个集群的通信基础。

拓扑有两种做法:

第一种是四台机器两两直连。好处是省一个交换机,坏处是扩展性极差,三台以上机器的通信拓扑会变得很别扭,而且每个端口的带宽利用不均衡。我强烈不推荐超过三台的场景用全直连。

第二种是四台机器都接到一台支持 RoCE 的以太网交换机上,组成一个星型结构。这也是我实际采用的方式。交换机不用太高端,关键是支持 PFC 和 ECN 这两个无损网络特性,具体型号不点名了,市面上主流的数据中心交换机基本都带。

IP 规划我用了两套网段,一套管理网(千兆/万兆),一套业务数据网(高速 RDMA)。RDMA 网段独立开,避免管理和推理流量打架。

节点管理网 IPRDMA 数据网 IP角色
node110.0.1.11192.168.50.11Ray head / vLLM 主节点
node210.0.1.12192.168.50.12Ray worker
node310.0.1.13192.168.50.13Ray worker
node410.0.1.14192.168.50.14Ray worker

交换机上把 RDMA 数据网划分成独立 VLAN,四个口配置成 Access 模式就行。网线建议用 DAC 直连铜缆,短距离内延迟低、功耗小,比光模块省事。

2.2 无损网络三件套:MTU、PFC、ECN

RoCE 这玩意有个特点:它假设底层网络是“无损”的,一旦发生丢包,RDMA 性能会断崖式下跌,甚至直接卡死。所以配 RoCE 必须把三个东西同时搞定。

第一是 MTU。所有节点和交换机端口都要开 Jumbo Frame,把 MTU 从默认的 1500 调到 9000。这能减少相同数据量下的包数量,显著降低 CPU 开销和延迟。哪个节点忘改了,那个节点的通信带宽就会莫名其妙低一大截。

第二是 PFC(优先级流控)。这是一层基于优先级的 IEEE 802.1Qbb 流控,简单说就是把 RDMA 流量标记成高优先级队列,交换机在队列拥塞时暂停发送端,而不是直接丢包。这里有个关键细节:PFC 必须端到端配置,也就是交换机入口、出口和节点的网卡都要匹配,任何一个端口没开,整个链路都可能被反压拖死。

第三是 ECN(显式拥塞通知)。PFC 是“堵车了就让大家停下来”,ECN 更像是“提前告诉发送端你开慢点”,配合 WRED 算法在队列深度到达阈值时给报文打标记。开了 ECN 之后,拥塞管理会平滑很多,不会出现 PFC 频繁触发的次生问题。

配置完不是就完事了,得验证。我习惯每台机器跑一下网卡状态和实际的 RDMA 带宽,确认是不是真的协商到了预期速率,而不是“显示 400G,实际 20G”的假象。验证工具可以用网卡自带的诊断工具,或者直接用 NCCL 测试,这一步别省。

2.3 NCCL 连通性测试别跳过

软件层面,集群的分布式计算要靠 NCCL 库来完成 AllReduce 这类集合通信。在部署推理引擎之前,我强烈建议先跑一遍 NCCL 全规约测试,这一步能提前暴露 80% 的网络隐患。

测试命令很简单:

# 每个节点上执行,获取 NCCL 测试工具 # 四台机器的 GPU 都要能被识别 ./build/all_reduce_perf -b 8 -e 1024M -f 2 -g 1

实际测试中,重点关注两个指标:带宽和稳定性。四台 DGX Spark 在 400Gb/s RoCE 环境下,AllReduce 跑到 300Gbps 以上算正常;如果只有几十 Gbps,基本可以断定网络配置出了问题——最常见就是 MTU 没统一、PFC 没生效,或者 NCCL 选错了网卡。

NCCL 选网卡这个坑很阴间。机器上有管理网和数据网两块网卡,NCCL 默认可能挑错。我通过环境变量强制指定:

export NCCL_IB_HCA=mlx5_0 export NCCL_SOCKET_IFNAME=eth1 export NCCL_IB_GID_INDEX=3

具体接口名以本机为准,可以用ibstat或者ibstatus查一下哪个是 RDMA 网卡,然后写死进去。不写死的话,有时候能通、有时候异常慢,非常费解。

通过信号:NCCL 测试输出里的带宽数字稳定、没有大幅波动,同时 four nodes 的耗时和 two nodes 的耗时比例接近理论预期,这就说明集群网络链路是健康的,可以继续往下走了。

3. 推理引擎与模型部署

3.1 先把 Ray 集群拉起来

多节点 vLLM 的资源协调依赖 Ray。我理解很多人觉得 Ray 重,但在生产环境里它做对了一件事:把跨机器的GPU资源、进程生命周期、失败检测统一管起来。vLLM 在多节点模式下会通过 Ray 找到集群里所有可用的 GPU,然后给每个 rank 分配任务。

启动 Ray 集群的流程:

先在 head 节点(node1)执行:

ray start --head --port=6379 --dashboard-host=0.0.0.0

然后在每个 worker 节点执行,把HEAD_NODE_IP替换成 node1 的业务 IP:

ray start --address=http://HEAD_NODE_IP:6379

所有节点启动完成后,在 head 节点上执行ray status,能看到 4 个节点的状态都是alive,每台机器各有一个 GPU 可用。这里要特别注意,DGX Spark 在软件层面对外暴露的是一个 GPU 设备,所以四台机器就是 4 个 GPU rank,张量并行最大就是 tp=4,不要幻想某台机器里能再拆出多个独立显卡。

如果打算长期运行,可以把 Ray head 配置成 systemd 服务,或者用容器编排工具统一管理 head/worker 的启停。过程中如果某个 worker 掉线,ray status会显示异常状态,排查起来非常直观。

3.2 vLLM 多节点启动与关键参数

Ray 集群正常后,在 head 节点上用 vLLM 启动推理服务。我用的是 vLLM 官方镜像,启动命令长这样:

vllm serve /models/某70B开源模型 \ --tensor-parallel-size 4 \ --pipeline-parallel-size 1 \ --max-model-len 32768 \ --gpu-memory-utilization 0.9 \ --kv-cache-dtype fp8 \ --enable-prefix-caching \ --port 8000

逐个解释关键参数:

--tensor-parallel-size 4是核心,表示把模型的每一层权重横向切成 4 份。vLLM 会把 4 个 rank 分布到 Ray 集群的 4 台机器上,每台 1 个 rank。这里不要超过 4——因为集群就 4 个 GPU 设备。

--pipeline-parallel-size 1是流水线并行维度。在 4 节点的规模下,张量并行优先于流水线并行。原因很简单,流水线并行虽然通信量小,但会引入流水线气泡,token 延迟反而升高。容我再多说一句:如果未来你扩到 8 台机器,再考虑 tp=4 + pp=2 的组合。

--max-model-len 32768限制了 KV cache 的最大长度。这个值和并发是互相挤兑的,不是设得越大越好,待会实测部分我会详细讲怎么找平衡。

--gpu-memory-utilization 0.9表示 vLLM 最多使用 90% 的内存做 KV cache。留 10% 余量给模型权重、激活值和系统开销。建议不要设到 0.98 之类的极端值,否则前端偶发显存峰值直接 OOM。

--kv-cache-dtype fp8是性能救星。KV cache 用 fp8 存储,内存占用几乎减半,同等空间下能支撑更长上下文或者更高并发。模型本身如果是 FP8 量化,整个集群的内存压力会小很多。

--enable-prefix-caching是 RAG 场景神器,它会把 prompt 公共前缀的 KV cache 缓存下来,多用户提问相似问题时直接复用,实测命中后首字延迟能降一大截。

关于分布式执行后端,我现在用的是 Ray。vLLM 新版本也有多进程执行后端(mp),不用 Ray 也能多节点运行,但对网络故障处理的鲁棒性不如 Ray,生产上我还是建议 Ray 优先。启动完成看到类似 “Application Started” 的日志,就可以用 OpenAI 兼容接口测试了:

curl http://192.168.50.11:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{"model": "/models/某70B开源模型", "prompt": "你好", "max_tokens": 64}'

3.3 模型文件放哪里:本地副本比 NFS 稳

模型加载这块,我一开始图省事用了 NFS 共享存储,把模型文件放在一个 NFS 服务器上,四台机器同时挂载读取。结果踩了不小的坑:首节点加载时四个 rank 同时读同一个大文件,NFS 服务端和网络都成了瓶颈,加载一个 70B 模型花了快四十分钟,而且中途偶发文件句柄超时导致 rank 掉线。

后来改成每台机器把模型文件复制到本地 NVMe 盘上,本地磁盘加载速度快了不止一个量级,四台机器各自加载本地副本,整体启动时间从四十分钟压缩到五分钟以内。DGX Spark 本地盘是 4TB NVMe,存一份 70B 模型完全没压力,没必要为了省磁盘去挑战 NFS 的性能。

如果模型会频繁更新,我的建议是“本地副本 + 分发流程”:模型文件先推到一台机器,再通过 rsync 并行分发到其他三台,最后重启服务。这个流程脚本化之后,更新一次模型大概几分钟,比 NFS 方案稳定得多。

4. 性能实测与调优记录

4.1 单机打四机:真实数据摆上来

先给个环境说明:模型是某 70B 开源对话模型,FP8 量化,权重约 70GB。客户端用脚本发请求,统计首 token 延迟(TTFT)、单 token 生成间隔(TPOT)和整体吞吐量。

配置最大并发TTFT(首 token)TPOT(单 token)吞吐(tokens/s)
单机 tp=121.2s98ms10.2
单机 tp=181.8s150ms5.3
四机 tp=480.45s28ms32.7
四机 tp=4160.6s35ms28.4
四机 tp=4321.1s52ms19.2

这里有两个有意思的现象值得拆解。

第一,四机 tp=4 的首 token 延迟反而比单机更低。张量并行虽然没有减少每层计算的总工作量,但每个 rank 算的矩阵尺寸变小了,单次计算的绝对耗时降低,网络 AllReduce 的延迟远小于矩阵计算节省下来的时间,所以 TTFT 整体下降。

第二,并发从 8 提到 16,吞吐反而轻微下跌。这说明集群在并发超过一定阈值后,内存带宽和网络带宽开始互相竞争。这也验证了我之前说的:DGX Spark 集群的性能上限更多由带宽决定,而非算力。后续调优的目标,就是在带宽允许的范围内最大化有效吞吐。

4.2 KV Cache、上下文长度和并发怎么平衡

我测出来的最优工作点是并发 8-16、上下文 32K。但这不代表你也这么设就好,因为 KV cache 占用是“上下文长度 × 并发数”的函数,两者互相打架。

举个例子,假设每 token 的 KV cache 占用约 1.6MB(随模型层数、头数浮动),32K 上下文 × 8 并发就需要约 40GB 的 KV cache。如果没开 fp8,这个数字翻倍到 80GB。所以量化 KV cache 几乎是必选项,不开的话四台机器的内存很快被吃光。

经验是先用下面这个顺序定参数:

  1. 模型权重量化:能上 FP8 就上 FP8,不但省内存,张量并行时网络通信的 payload 也变小;
  2. 确定最大上下文:根据真实业务需求定,不是越大越好,RAG 场景 8K-16K 往往就够;
  3. 用gpu-memory-utilization和 KV cache 统计值反推并发上限,让 vLLM 日志里的Pending队列不要持续堆积;
  4. 最后用并发压测微调,找到吞吐曲线的拐点。

还有个小技巧:上下文长了之后,prefix caching 的收益会变大,因为长 prompt 的公共前缀命中率更高。RAG 场景下,系统提示词 + 检索文档往往就有几千个 token,缓存一次能省掉一大半的重复计算。

4.3 网络瓶颈怎么识别和缓解

很多人在多节点推理集群上只盯着推理吞吐,不关心 NCCL 层面的带宽余量,这是个盲区。推理时的 AllReduce 通信量和训练不一样,它的数据量没那么大,所以网络瓶颈通常不会 100% 占满,但一旦并发上来,通信延迟会悄悄拉高。

我的排查套路是:

先在另一台机器上跑一个基准,看看当前网络还能吃多少余量。比如你这边推理服务跑着,那边再起一个 NCCL 带宽测试,看看能不能稳定跑满,如果本来就跑不满,说明网络层已经存在瓶颈。如果 NCCL 一跑,推理吞吐明显下降,说明通信和推理在抢带宽。

缓解手段分三招:

  • 第一招是减少不必要的通信量。KV cache 做成 fp8、模型权重做量化,本质都是在减小每次 AllReduce 的数据量,对延迟收益立竿见影。
  • 第二招是调度层面错峰。用 vLLM 的批处理调度天然把多个请求的计算合并,通信次数不会翻倍,这也是为什么连续批处理在多节点上特别重要。
  • 第三招是容量规划。四节点 tp=4 在 400G 网络下算一个甜点配置,如果继续加到 8 节点,建议研究 tp=4 + pp=2 或模型分区服务,把单次通信域控制在 4 台以内,避免 8 节点 AllReduce 的通信规模把延迟拖上去。

5. 踩坑实录与常见问题排查

5.1 网络层三个阴间坑

第一个坑是 MTU 不一致。我第一次组完网络,NCCL 测试结果是 40Gbps,找了一下午原因,最后发现是交换机某个口没开 Jumbo Frame,导致这个口上所有大包被分片。RDMA 对分片极其敏感,性能直接从四百分之一跌到十分之一不到。排查方式也简单,逐端口检查 MTU 配置,确保节点和交换机全部是 9000,任何一个口没改,都把那个口的流量单独测试。

第二个坑是 NCCL 选错网卡。前面提到的NCCL_SOCKET_IFNAME和NCCL_IB_HCA不设置的话,NCCL 有时候走慢速管理网,速度感人。我开过一次调试日志,发现它把两个节点的 IP 解析到了管理网段,立刻用环境变量强制指定 RDMA 网卡解决。

第三个坑是网卡驱动和固件版本不一致。集群里四台机器如果买了不同批次,固件版本可能有差异,某些组合下会出现 RDMA 偶发断开。这个排查起来很难,我最后是把所有节点的网卡固件统一刷到同一版本才消停。所以新机器到位后第一件事,就是比对驱动和固件版本,统一升级。

5.2 内存和共享内存导致的失败

DGX Spark 是统一内存模型,OOM 的表现和传统显卡不太一样。传统显卡 OOM 直接报显存不足,DGX Spark 则可能出现内存分配失败、进程被 OOM Killer 干掉的随机症状。我在调试时遇到最诡异的一次是:单独跑推理正常,多节点一起跑就偶发卡死,最后查出来是/dev/shm空间不够。多进程通信时每个 rank 要写共享内存,默认的/dev/shm太小,直接被灌爆,进程挂掉。如果你的运行环境是 Docker,务必加上:

docker run ... --shm-size=64g --gpus all ...

或者干脆--ipc=host用宿主机的共享内存。这个参数不加,多节点分布式推理迟早爆一次。

另外要注意一个隐性内存消耗:模型权重做张量并行切分后,每台机器除了本地权重,还要留一部分内存给 AllReduce 的临时缓冲区。如果gpu-memory-utilization设得太狠,比如 0.98,vLLM 在初始化阶段可能没事,但运行到某些 batch 特别大的请求时会触发内存分配失败。我建议按 0.88-0.92 设置,牺牲一点点 KV cache 空间,换取整体稳定性。

5.3 分布式行为了:心跳、超时和重启策略

多节点集群里有一种很难排查的故障:单机都正常,但分布式推理服务跑着跑着,某个 rank 自己退出。最常见原因是 NCCL 通信超时,尤其是网络暂时拥塞时,AllReduce 如果迟迟不完成,vLLM 的 timeout 触发就把整个进程判死。

这种问题的根治手段是让网络更稳定,前面说的 PFC/ECN/MTU 三件套必须全部到位。如果网络确实没问题,只是偶发拥塞,可以适当提高超时容忍度,比如设置:

export NCCL_TIMEOUT=300

也可以在 Ray 层面配置节点故障后的自动重启策略。我是把 head 节点的 vLLM 服务托管到一个进程守护工具里,异常退出后自动拉起;worker 节点的 Ray 进程则配置了健康检查,掉线后自动重新注册。集群大了以后,这些自动化手段比手工运维省心得多。

再提醒一个日常监控习惯:我每五分钟记录一次ray status、网卡 RDMA 带宽曲线和 vLLM 的吞吐日志。这套监控帮我在某次网络交换机固件异常时提前发现了问题,否则大概率又是半夜被报警吵醒的节奏。

写在最后的经验

这套多节点 DGX Spark 集群跑了快三个月,我个人最大的体会是:它不是一个传统意义上的“AI 服务器集群替代”,而是一个介于单机工作站和数据中心之间的甜点方案。它的性价比和部署便利性是实打实的优势,但它对网络调优的要求比拿着 NVLink 全互联的整机更苛刻——毕竟 RoCE 这套无损网络的学问,很多做训练的同学平时根本接触不到。

如果你打算照着这个方案折腾,我最后的建议是:不要一上来就想着把所有机器怼进一个集群做超大模型,先把两台机器、一个中小尺寸模型跑通,确认网络、Ray、vLLM 这套链路都稳定了,再加入第三台、第四台。这个递进过程会帮你把每一层问题隔离开,省掉大量“三台挂了不知道是网络还是代码”的痛苦排查时间。

等四台机器跑顺了,你还能顺着这个方向继续扩展:加一台共享存储做模型仓库、用网关把这套服务接入企业内部系统、甚至把它改造成多模型服务集群。DGX Spark 这些零散的桌面级算力,联网之后能发挥出来的价值,比想象中要大得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询