两台DGX Spark互联:NVIDIA Sync实现70B模型张量并行实战

两台DGX Spark互联:NVIDIA Sync实现70B模型张量并行实战 如果你只有一台 DGX Spark本地跑 200B 模型这件事已经足够让人兴奋。但只要真正把模型加载进去、开始连续对话很多人会发现问题并没有想象中那么轻松单机的统一内存再大也经不住长上下文、大并发和持续推理的消耗算力再强一次只能干一条流水线的话吞吐依然会被卡住。于是“能不能再加一台 DGX Spark把两台机器连成一个集群”就成了很自然的下一步。这个问题在社区里讨论度很高尤其是想用两台 DGX Spark 做张量并行、跑 70B 模型的人几乎都会问到底怎么连需要什么配置单并发下每秒能输出多少 token这篇文章就是围绕“用 NVIDIA Sync 连接两台 DGX Spark”展开。先说结论连接两台机器不是插一根网线、跑一个脚本就能完事它需要你同时处理好网络链路、NCCL 集合通信、容器环境和推理引擎四个层面的配置。文章不会依赖某个虚构的“一键同步命令”而是把从物理连接、IP 规划、通信验证到 70B 模型张量并行推理、性能基准测试的完整路径拆开讲清楚。读完你不仅能搭起来还能判断“两台机器到底值不值得连”。1. 为什么要连接两台 DGX Spark而不是只买一台更大的机器先理解单机的边界。DGX Spark 的定位是个人 AI 超级计算机内置 Grace Blackwell 架构芯片和较大容量的统一内存出厂目标是让开发者在桌面上直接跑数百亿甚至千亿级参数的模型。单机确实能“放进去”一个 200B 模型但“能放进去”和“能跑好”之间有一条明显的性能鸿沟。当你做推理时内存不仅要放模型权重还要放激活值、KV Cache 和临时计算张量。模型越大上下文越长KV Cache 增长越快。单机推理场景下一旦上下文序列变长内存就会被迅速占满吞吐也随之下降。更麻烦的是如果你还想同时服务多个请求单机的算力和内存带宽会成为双重瓶颈。这时两台 DGX Spark 的价值就出来了把 70B 甚至更大模型的权重分散到两台机器的显存/统一内存中降低单机内存压力。让两个 Grace Blackwell 芯片同时参与同一层计算理论上提升推理吞吐。为后续扩展到更多节点提供基础能力形成一个小型本地算力池。但也必须清醒多机互联不是免费的。两机之间的通信延迟和带宽永远比单机内部芯片间通信高一个量级。如果模型较小、单机已经跑得很快强行做张量并行反而可能因为通信开销而得不偿失。所以“两台 DGX Spark 连接”最适合的场景是模型超过单机理想工作负载或者对并发/吞吐有明确要求。2. 核心概念NVIDIA Sync、DGX Spark 与张量并行2.1 DGX Spark 是什么DGX Spark 是 NVIDIA 推出的小型个人 AI 工作站产品核心是一颗高度集成的超级芯片配合高带宽统一内存。它的意义在于把过去需要一台服务器才能完成的 AI 推理/微调工作压缩到桌面级设备里。正因为单机能力已经很强用户才会进一步想通过多机组合来突破单机瓶颈。2.2 NVIDIA Sync 是什么NVIDIA Sync 是面向多台 DGX 设备协同计算的通信与同步方案。它解决的核心问题不是“把两台机器用网线连上”而是“让两台机器在分布式计算时保持步调一致”。分布式训练和推理中多个节点必须频繁交换梯度、张量、中间状态。如果节点的时钟不同步、通信协议不一致、集合通信配置错误轻则性能大幅下降重则训练直接卡死或启动失败。NVIDIA Sync 的本质就是一套面向这类场景的同步和通信机制底层依赖高速网卡驱动和 NCCLNVIDIA Collective Communications Library集合通信库。需要特别注意不同 DGX 系统版本、不同驱动版本对应的同步工具命令和配置方式可能有差异。本文会避开那些可能因版本而变的私有命令重点讲通用配置流程。只要网络、NCCL、容器环境正确不管当前 NVIDIA Sync 的具体实现是什么都能顺利跑通。2.3 张量并行、流水线并行、数据并行怎么选多机部署大模型时有三种典型并行策略并行策略切分方式通信压力适用于数据并行每台机器复制完整模型切分数据每轮同步梯度压力中等训练场景流水线并行按模型层切分每台机器负责若干层机器间传输中间激活压力较小模型层数很多的场景张量并行把单层计算切分到多台机器每层前向/反向都要通信压力最高模型单层很大单机放不下两台 DGX Spark 组合时最常见的诉求是跑 70B 级模型推理。70B 模型如果使用 4-bit 量化权重大约 40GB单台 DGX Spark 的内存通常能放下但推理速度和并发能力受限如果使用 FP16/BF16权重就接近 140GB单机压力极大这时候张量并行几乎成为必选项。张量并行的核心逻辑是一个 Transformer 层的矩阵乘法可以被拆成多个 GPU 各自计算一部分最后通过 AllReduce 汇总结果。这个过程每一次矩阵计算都伴随至少一次多机通信。所以张量并行对网络要求很苛刻这也就是为什么连接两台 DGX Spark 时网络配置和 NCCL 参数不能随便填。3. 连接前的硬件与软件检查清单在接任何线缆或输入任何命令之前先做一轮检查。多机环境排错最痛苦的地方是“不知道问题是出在硬件、驱动、网络还是软件配置”而前置检查能把问题范围快速缩小。3.1 检查硬件状态和驱动在两台机器上分别执行nvidia-smi这个命令会输出 GPU 名称、驱动版本、CUDA 版本、显存使用情况。DGX Spark 的 GPU 应该正常显示并且驱动版本尽量保持一致。如果两台机器的驱动版本不一致分布式环境偶尔会出现奇怪的行为。再检查高速网卡是否被系统识别lspci | grep -i mellanox lspci | grep -i ethernet如果这台 DGX Spark 使用 ConnectX 系列网卡Mellanox 关键字会出现在输出中。这一步是为了确认网卡驱动已经加载而不是只有一块普通的板载网卡。3.2 检查现有网络接口ip link show ip addr show输出中通常会看到多个网络接口。其中至少有一个接口用于管理网络你可能用它 SSH 登录设备还有一个接口是专门用于高速互连的。建议把“管理网络”和“高速互连网络”分离开避免大数据通信时把管理流量也挤占掉。如果你的环境支持 InfiniBand还可以用ibstat 2/dev/null || echo no ibstat or no IBibstat会显示 InfiniBand 设备状态和端口速率。如果命令不存在说明系统没有安装 InfiniBand 工具包但不代表网卡不可用因为同一块 ConnectX 网卡也可以工作在以太网RoCE模式下。3.3 检查容器运行时和 NVIDIA 组件推荐在两台机器上使用完全相同的容器镜像和软件栈。先确认 Docker 和 NVIDIA Container Toolkit 是否正常docker --version nvidia-container-runtime --version 2/dev/null || nvidia-container-toolkit --version 2/dev/null || echo container runtime not found从实际经验看DGX 类设备出厂通常已经预装好驱动的容器运行时。如果你拿到的是底层的 Server 版本系统可能需要手动安装nvidia-container-toolkit。这一步务必先确认否则后面启动容器时会报 GPU 不可用。3.4 同步系统时间分布式集群对时间同步非常敏感。即使 NCCL 不要求绝对严格的时间同步节点间时钟偏差过大也会影响日志排查、证书校验和应用层逻辑。timedatectl status sudo timedatectl set-ntp true两台机器最好使用同一个 NTP 服务器。4. 物理连接与基础网络配置4.1 选择直连还是交换机连接两台 DGX Spark 的高速互连可以有两种拓扑直连用一根足够高速的网线/光纤直接连接两台机器的高速网卡。交换机连接两台机器分别接到同一台交换机。直连的优势是延迟更低、少一跳缺点是只能连接两台后续扩展要重新改线。交换机的优势是便于扩展到 3 台、4 台甚至更多节点且链路管理更规范。如果你明确只组两机集群优先直连如果打算以后继续加机器优先交换机。4.2 静态 IP 规划高速互连网段不要使用 DHCP建议规划一个固定子网。例如节点高速网卡 IP管理网络 IP示例node-a192.168.10.1/24192.168.1.10/24node-b192.168.10.2/24192.168.1.11/24这里把 192.168.10.0/24 专门留给高速互连避免它与管理网络冲突。4.3 使用 netplan 配置静态 IPUbuntu 或 DGX OS 通常使用 netplan。创建配置文件/etc/netplan/10-dgx-sync.yamlnetwork: version: 2 ethernets: eth1: dhcp4: no addresses: - 192.168.10.1/24 routes: - to: 192.168.10.0/24 scope: link mtu: 9000这里假设高速互连接口名是eth1。实际操作时请用第 3 章ip link show看到的实际接口名替换。MTU 设置到 9000Jumbo Frame可以降低大数据包传输时的 CPU 开销但需要交换机或对端网口同样支持并且两端 MTU 一致否则会出现分片或丢包。应用配置sudo netplan apply在 node-b 上做类似配置IP 改为 192.168.10.2。4.4 验证网络连通性先确认基本联通ping -c 4 192.168.10.2如果 ping 不通先查网线、接口名、IP 配置、防火墙。两机的防火墙如果开着需要放行内部互连网段的通信sudo ufw status sudo ufw allow from 192.168.10.0/24然后检查端口速率和 MTUip link show dev eth1如果看到mtu 9000并且状态是UP说明链路层正常。4.5 高速网络带宽测试分布式训练和推理对带宽非常敏感。建议在配置完成后做一次裸带宽测试。如果环境里有iperf3在 node-b 启动服务端iperf3 -s在 node-a 启动客户端并打满 60 秒iperf3 -c 192.168.10.2 -t 60 -P 8如果支持 InfiniBand/RoCE还可以使用ib_write_bw -d mlx5_0命令会显示双向带宽。这一步的关键不只是看数值而是确认链路能达到预期速率。如果吞吐异常低大概率是 MTU 不一致、网卡驱动没有启用 RDMA 或线缆、模块有问题。不要带着一个低带宽链路继续往下配置否则张量并行性能会很差。5. 容器环境与 NCCL 通信配置5.1 拉取统一的 PyTorch NGC 容器推荐在两台机器上使用相同标签的 NGC PyTorch 容器。NGC 容器的好处是预装了 CUDA、NCCL、PyTorch 和常见分布式工具能省去大量手动编译的环节。docker pull nvcr.io/nvidia/pytorch:latest如果你更看重稳定复现可以指定一个固定标签。具体标签请以 NGC 目录当前列表为准不要在文档里把一个不确定的版本写死。5.2 启动容器并传递 NCCL 环境变量在 node-a 和 node-b 上分别启动容器。启动命令要保持一致除了网络参数外尽量做到环境一致docker run -it --rm \ --gpus all \ --ipchost \ --ulimit memlock-1 \ --ulimit stack67108864 \ --network host \ -e NCCL_SOCKET_IFNAMEeth1 \ -e NCCL_IB_DISABLE0 \ -e NCCL_DEBUGINFO \ -v /mnt/models:/models \ nvcr.io/nvidia/pytorch:latest \ bash解释关键参数参数/环境变量作用--ipchost共享主机 IPC 命名空间避免分布式通信时共享内存不足--ulimit memlock-1不限制内存锁定量NCCL 在注册内存时需要锁定内存页--ulimit stack67108864提高栈空间防止某些 CUDA 操作栈溢出--network host容器直接使用主机网络对 InfiniBand/RDMA 支持更友好NCCL_SOCKET_IFNAMEeth1告诉 NCCL 使用 eth1 这个接口做 socket 通信NCCL_IB_DISABLE0允许 NCCL 使用 InfiniBand/RoCE如果链路支持NCCL_DEBUGINFO打印 NCCL 初始化日志排查通信问题时非常有用需要注意NCCL_IB_DISABLE这一项取决于你的实际链路模式。如果你的两台机器通过普通以太网连接且没有启用 RoCE可以显式设置为NCCL_IB_DISABLE1让 NCCL 走 TCP socket 通信避免它反复探测 IB 设备超时。6. 用 torchrun 验证分布式通信是否正常在正式跑 70B 模型之前先用一个最小分布式程序验证两机通信。6.1 编写测试代码创建文件test_dist.pyimport os import torch import torch.distributed as dist def main(): dist.init_process_group(backendnccl) rank dist.get_rank() world_size dist.get_world_size() print(f[Rank {rank}/{world_size}] CUDA available: {torch.cuda.is_available()}, device: {torch.cuda.get_device_name(rank)}) # 构造一个大张量测试多机 AllReduce x torch.ones(4096, 4096, dtypetorch.float32).cuda() dist.barrier() dist.all_reduce(x, opdist.ReduceOp.SUM) print(f[Rank {rank}/{world_size}] all_reduce sum {x[0, 0].item():.0f}) dist.barrier() dist.destroy_process_group() if __name__ __main__: main()这段代码做了三件事初始化 NCCL 分布式环境。打印每个 rank 的编号和总节点数。在两个节点上各建一个 4096x4096 的 float32 张量执行 AllReduce 求和。如果两机通信正常两个位置的结果都应该是 2.0。6.2 在 node-a 上启动分布式任务容器内执行torchrun \ --nproc_per_node1 \ --nnodes2 \ --node_rank0 \ --master_addr192.168.10.1 \ --master_port29500 \ test_dist.py在 node-b 上执行相同的命令但把--node_rank改为 1:torchrun \ --nproc_per_node1 \ --nnodes2 \ --node_rank1 \ --master_addr192.168.10.1 \ --master_port29500 \ test_dist.py这里--master_addr指向 node-a 的高速互连 IP--master_port是两机通信控制端口。推荐nproc_per_node1因为每台 DGX Spark 在一个容器里只需要暴露一个 rank真正的大并行度通过多机实现。6.3 预期输出与验证标准如果配置正确node-a 和 node-b 会交替输出类似日志[Rank 0/2] CUDA available: True, device: NVIDIA ... [Rank 1/2] CUDA available: True, device: NVIDIA ... [Rank 0/2] all_reduce sum 2.0 [Rank 1/2] all_reduce sum 2.0验证标准有两条两边的 rank 都能打印出来说明 master 地址、端口、通信链路都正常。AllReduce 结果等于 2.0说明张量数据真的在节点间做了汇总而不是各自跑各自的。如果卡在初始化阶段重点检查--master_addr是否能从 node-b 访问、NCCL_SOCKET_IFNAME是否指向了正确网卡、防火墙是否放行端口。7. 在两台 DGX Spark 上部署 70B 模型张量并行推理7.1 准备模型权重先把 70B 模型权重放到两台机器都能访问的位置。最简单的做法是模型同时放在 node-a 和 node-b 的相同路径下例如/mnt/models/Qwen2.5-70B-Instruct-GPTQ-Int4。如果有多台机器的扩展计划推荐使用 NFS 或 Ceph 这类共享存储让所有节点共享同一份权重文件避免反复同步。7.2 使用 vLLM 启动多机张量并行服务vLLM 是当前比较主流的高性能推理框架对多机张量并行支持也比较成熟。它需要借助 Ray 或者自身的分布式执行后端来做跨节点通信。下面是一个双节点部署示例假设节点 A 的 IP 是 192.168.10.1节点 B 的 IP 是 192.168.10.2。先启动 Ray head 节点在 node-a 上ray start --head --port6379 --dashboard-host0.0.0.0然后在 node-b 上加入该 Ray 集群ray start --address192.168.10.1:6379最后在 node-a 上启动 vLLM API Serverpython -m vllm.entrypoints.openai.api_server \ --model /mnt/models/Qwen2.5-70B-Instruct-GPTQ-Int4 \ --tensor-parallel-size 2 \ --distributed-executor-backend ray \ --ray-address 127.0.0.1:6379 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --host 0.0.0.0 \ --port 8000参数说明参数含义--tensor-parallel-size 2张量并行度设为 2也就是把模型切分到两个 rank 上--distributed-executor-backend ray使用 Ray 管理跨节点分布式状态--max-model-len 8192最大上下文长度影响 KV Cache 预留空间--gpu-memory-utilization 0.9每个 GPU 允许使用的显存/统一内存比例这里假设两台机器上的 vLLM 、Torch、CUDA 版本完全一致。如果 vLLM 版本较老可能不支持--distributed-executor-backend ray需要参考当前版本说明替换为 TP 多机启动方式。7.3 发一个推理请求验证服务启动后打开另一个终端向 node-a 发请求curl -s http://192.168.10.1:8000/v1/completions \ -H Content-Type: application/json \ -d { model: /mnt/models/Qwen2.5-70B-Instruct-GPTQ-Int4, prompt: 用一句话解释分布式系统, max_tokens: 128, temperature: 0.7 }如果返回 JSON 中包含choices和生成文本说明双机张量并行服务已经可以工作。7.4 单并发输出多少 token 的真相很多人关心“两台 DGX Spark 张量并行70B 模型单并发输出多少 token”。这个问题没有一个固定答案因为它取决于至少五个因素模型精度FP16、BF16、INT8、INT4 对应的计算量和显存占用完全不同。输入输出长度输出越长KV Cache 越大计算量越大。量化方案GPTQ、AWQ、FP8 的 kernel 效率不一样。互联带宽张量并行每次矩阵乘法都要 AllReduce网络越慢性能掉得越厉害。vLLM 版本和调度策略不同版本的 continuous batching 和 fusing kernel 差异很大。更稳妥的做法是部署后自己测。可以使用 vLLM 自带的 benchmark 脚本python benchmarks/benchmark_serving.py \ --backend vllm \ --model /mnt/models/Qwen2.5-70B-Instruct-GPTQ-Int4 \ --tokenizer /mnt/models/Qwen2.5-70B-Instruct-GPTQ-Int4 \ --num-prompts 1 \ --output-len 256把--num-prompts设为 1就可以测到单并发下的输出吞吐。单位通常是tokens/s。真正上线前建议分别测一次单机、一次双机对比张量并行带来的收益。如果双机结果反而比单机低不要惊讶通信开销可能超过了计算收益这时需要重新评估模型量化和网络优化策略。8. 常见问题与排查思路多机分布式环境的问题往往不是单点故障而是多个环节叠加。常见的排查顺序是链路层 → 网络层 → NCCL → 应用层。问题现象可能原因排查方式解决方案torchrun启动后卡住master 地址不通或防火墙未放行在 node-b 执行ping 192.168.10.1检查nc -vz 192.168.10.1 29500确认 IP、放行端口、关闭 firewalld/ufwNCCL 初始化报Ring或者Channel失败NCCL_SOCKET_IFNAME指向了错误的网卡或 IB/RoCE 探测失败打开NCCL_DEBUGINFO看日志中使用的网卡名改成正确接口名或设置NCCL_IB_DISABLE1容器内看到不到 GPUNVIDIA Container Toolkit 未装或驱动版本不匹配容器内执行nvidia-smi宿主机安装/更新nvidia-container-toolkit重启 dockerAllReduce 结果不等于 2.0两机张量没有真正做集合通信或存在多个进程串扰查看输出日志中的 rank 数量确认--nnodes、--node_rank参数干净关闭旧进程张量并行后生成速度反而下降互联带宽不足或模型较小导致通信开销占比高用iperf3/ib_write_bw测裸带宽看NCCL_DEBUGINFO是否大量重传优化 MTU、更换线缆/交换机或尝试降低并行度两台机器模型路径不一致权重只存在于一台机器另一台找不到在 node-b 执行ls /mnt/models/使用 NFS 共享或同步权重到相同路径vLLM 启动时 ray 连接失败Ray 集群没有先启动或版本不一致检查ray status统一 vLLM/Ray 版本先启动 head 节点再启动 worker--network host下端口冲突多个容器同时监听 8000 端口用 ss -lntpgrep 8000 查看占用对于第一次接触分布式推理的开发者建议在运行 70B 模型之前先用前面第 6 章的 AllReduce 测试验证通信再跑一次小模型的单机 vLLM最后才切到 70B 模型。这样每一步失败都能快速定位而不是面对一长串错误日志无从下手。9. 最佳实践与工程建议9.1 网络规划要早做两台机器互联很简单但不要忽略后续扩展。建议从一开始就把高速互连网段、管理网段、存储网段分开并写入网络规划文档。IP 地址固定不要依赖 DHCP。所有节点的主机名和 IP 映射写入/etc/hosts避免分布式框架解析主机名时出错。192.168.10.1 node-a 192.168.10.2 node-b9.2 环境一致性是稳定性的前提两台的驱动版本、CUDA 版本、NGC 容器标签、Python 包版本、vLLM 版本尽量完全一致。最省心的方式是维护一份requirements.txt或直接使用同一个容器镜像。环境不一致带来的问题往往很隐蔽比如张量并行在某些层上计算正常在某些层上出现NaN或崩溃。9.3 模型权重与数据的安全管理模型权重文件往往很大建议集中放在共享存储中并做好只读挂载。不要在每次启动时往节点里拷贝大文件。推理服务如果需要对外暴露不要直接监听公网 IP最好放在内网并通过 API 网关或 SSH 隧道访问。对模型文件设置严格权限避免未授权用户覆盖或删除权重。9.4 监控与日志不可少分布式推理比单机复杂得多必须有监控。推荐部署 NVIDIA DCGM。DCGM 是 NVIDIA 官方的数据中心 GPU 管理工具能采集 GPU 利用率、显存使用、温度、带宽等信息。配合 Prometheus 和 Grafana可以在一个面板上同时查看两台 DGX Spark 的状态。启动 nvidia-smi 的实时监控模式也可以临时观察nvidia-smi dmon -s pum这个命令会周期性刷新 GPU 利用率、显存读写和功耗。如果张量并行推理时某个节点利用率明显低于另一个优先检查网络通信是否成为瓶颈。9.5 上线前先做基准测试和回滚方案不要一上来就切换生产流量。先用小并发、短上下文跑通全链路记录单机性能和双机性能确认双机收益符合预期后再扩大。配置变更前备份当前正常的 Docker 启动命令、环境变量清单和权重文件列表。由于多机环境依赖项多一旦改挂快速恢复的最好方式不是现场排查而是回滚到上一份验证过的配置快照。9.6 明确适合场景避免过度设计最后一条建议可能最重要如果不是模型真的超过单机承受能力或者并发需求明确两台 DGX Spark 互联的收益未必显著。70B 模型在量化后的单机推理很多时候已经能跑。真正需要双机张量并行的是那些单机内存放不下、或者需要高吞吐/低首 token 延迟的正式业务场景。先基准测试再决定是否要加节点比盲目堆硬件更省钱、更省时间。10. 总结与后续学习方向本文的关键在于把两台 DGX Spark 通过 NVIDIA Sync 互联这件事拆成了三层物理网络层、NCCL 通信层、推理引擎层。物理网络层解决“两台机器能不能高速通信”NCCL 层解决“分布式进程能不能步调一致地交换张量”推理引擎层解决“70B 模型到底该怎么切到两个节点上”。只有每一层都验证通过多机张量并行才能真正跑起来。很多初学者会把精力集中在最后的 vLLM 命令上却忽略了前面的网络验证和环境一致性。真正决定双机性能上限的往往是那根高速网线的链路质量、MTU 是否对齐、NCCL 是否选择了正确的网络接口。如果你的集群搭完之后速度不理想不要急着换推理框架先回头检查通信链路。下一步值得研究的方向有三个一是更多节点的扩展从两台到四台时网络拓扑会复杂得多二是训练场景下的多机并行数据并行与张量并行的组合调度三是结合 NVIDIA DCGM 和 Prometheus 建立完整监控把集群变成一个可运维的长期服务。建议先把本文第 6 章的 AllReduce 测试和三组 vLLM 基准数据跑出来再决定要不要继续投入。