跳到主要内容
AI教程

使用 vLLM 和 Pi 在两台 DGX Spark 上部署 DeepSeek-V4.1-Flash

本教程介绍如何在两台 NVIDIA DGX Spark 节点上部署经过 EXL3 量化的 DeepSeek-V4.1-Flash 检查点,配置 RoCE 张量并行,验证兼容 OpenAI 的 API,并将模型连接到 Pi 编程代理。

使用 vLLM 和 Pi 在两台 DGX Spark 上部署 DeepSeek-V4.1-Flash

你将构建的内容

本项目提供了使用 vLLM 在两个 NVIDIA DGX Spark 节点上运行 DeepSeek-V4.1-Flash 的脚本。张量并行通过 QSFP/RoCE 链路跨节点运行,而头节点在 8000 端口提供兼容 OpenAI 的 API。

该部署使用 0xSero/DeepSeek-V4.1-Flash-Spark 检查点。路由骨干专家以 EXL3 trellis 数据编码,报告的平均值为每个权重 2.77 bit。注意力模块、共享专家、路由器、Engram 表、草稿层、视觉组件、嵌入和输出头均保留自上游检查点。

部署完成后,你可以直接通过其 API 使用模型,也可以将其连接到 Pi 编码代理,用于编码和工具辅助工作流。

性能与能力

README 报告了两个 DGX Spark GB10 节点的测试结果,测试使用通过 RoCE 的张量并行、FP8 KV 缓存、七 token 的 DSpark 推测解码、磁盘支持的 Engram 表以及两个并发序列。

  • 8k 提示词预填充:约每秒 2,050 个 token。
  • 32k 提示词预填充:约每秒 2,061 个 token。
  • 代码解码:单流约每秒 39–41 个 token。
  • 双流代码解码:聚合每秒 60 个 token。
  • prose 解码:单流约每秒 29 个 token。
  • 每个请求的最大上下文:262,144 个 token。
  • KV 缓存池:2,023,717 个 token。
  • 视觉输入、工具调用和推理:冒烟测试成功。
  • 175k token 上下文召回:通过报告中的全部六项实验室检查。

首次启动约需 11–13 分钟,因为需要加载权重和 EXL3 bank、编译内核并捕获 CUDA 图。

前置条件

你需要两个运行 DGX OS 的 DGX Spark 节点。选择其中一个作为头节点,负责提供 API;另一个作为工作节点。

  • 使用 QSFP 线缆连接两个节点,并启用 RoCE。
  • 每个节点至少有一个 RDMA 端口处于 ACTIVE 状态,可使用 rdma link 验证。
  • 每个节点在对应 fabric 网络上都有 IPv4 地址,例如 10.10.10.13 和 10.10.10.11。
  • 头节点可以使用工作节点的 fabric 地址进行免密码 SSH。
  • 两个节点都安装了带 NVIDIA runtime 的 Docker。
  • 你的用户必须属于 docker 组。
  • 头节点约需 700 GB 可用 NVMe 空间,工作节点约需 470 GB。
  • 两个节点都安装了 python3、rsync 和 curl。
  • 运行 Pi 的机器上安装了 Node.js 和 npm。

克隆仓库并定义工作节点

在头节点上运行以下命令。将 SSH 目标替换为工作节点的 fabric 地址。

git clone https://github.com/0xSero/DeepSeek-V4.1-Flash-Two-Sparks
cd DeepSeek-V4.1-Flash-Two-Sparks
export WORKER=user@10.10.10.11

脚本使用 WORKER 连接第二个 Spark。继续之前,请确保 SSH 密钥认证正常工作。

下载并分发检查点

将约 462 GB 的检查点下载到头节点的默认模型目录:

scripts/download.sh

下载脚本还会重新组装 Engram 分片。由于 Hugging Face 将单个文件限制为 50 GB,其中两个原生分片以 .partNN 文件存储。脚本会重新组装这些文件,根据 sha256-manifest.txt 验证六个原生分片,然后删除分片文件。如果希望保留这些分片,请设置 KEEP_PARTS=1。

通过 fabric 将完整模型复制到工作节点:

scripts/copy-to-peer.sh

或者,也可以直接在工作节点上运行 scripts/download.sh。默认模型路径为 ~/models/DeepSeek-V4.1-Flash-Spark。如果工作节点使用其他路径,请在启动前配置 WORKER_MODEL_DIR。

拉取服务镜像

该项目使用包含 EXL3 混合专家路径和 B12X Spark 内核的 vLLM 镜像。在两个节点上拉取固定版本的镜像:

docker pull ghcr.io/0xsero/deepseek-v4.1-flash-spark@sha256:5668e35e5ee021da4b9ce88a1964caf0e082e8ca01d81d1d64b6213a55c6add5

如果镜像尚未存在,启动脚本会自动拉取,因此也可以在启动过程中完成此步骤。

启动两个张量并行 rank

从头节点启动双节点服务器:

scripts/launch.sh

启动器会检测处于活动状态的 fabric 接口,在 ~/.dsv41-two-sparks/api_key 创建 API 密钥,在两个节点上启动内存保护程序,在工作节点上启动 rank 1,并在头节点上启动 rank 0。它会等待 API 可用,启动时间最长允许 45 分钟。

使用同一脚本检查或管理部署:

scripts/launch.sh status
scripts/launch.sh logs r0
scripts/launch.sh logs r1
scripts/launch.sh stop

服务器在头节点的 http://127.0.0.1:8000 上提供本地服务。客户端可以使用头节点可访问的地址,而 rank 之间的流量必须使用 QSFP/RoCE fabric。

运行冒烟测试

使用以下命令验证文本生成、工具调用和视觉输入:

python3 scripts/smoke.py http://127.0.0.1:8000

每项检查都会报告 PASS 或 FAIL。你还可以运行可选的基准测试:

python3 scripts/bench.py --out bench.json --conc 1 2

基准测试涵盖预填充、解码和长上下文速度,不设置输出上限。

使用 OpenAI 兼容端点

服务器提供以下 API 详细信息:

  • 基础 URL:http://<head-ip>:8000/v1
  • 模型名称:deepseek-v4.1-flash
  • 身份验证:来自 ~/.dsv41-two-sparks/api_key 的 bearer 令牌

例如,使用以下命令从头节点获取密钥:

ssh <head> cat ~/.dsv41-two-sparks/api_key

然后,只需配置基础 URL、模型名称和 bearer 密钥,即可使用任何兼容 OpenAI 的客户端调用该端点。

将 Pi 连接到模型

在安装了 Node.js 和 npm 的计算机上,安装并注册 Pi 提供程序。该命令接受不带末尾模型路径的 API 基础 URL:

pi/install.sh http://<head-ip>:8000/v1

在将要启动 Pi 的 shell 中设置 API 密钥:

export DSV41_API_KEY=$(ssh <head> cat ~/.dsv41-two-sparks/api_key)
pi --model dsv41-sparks/deepseek-v4.1-flash

如果 Pi 尚未位于你的 PATH 中,安装程序会先安装 Pi,然后仅在 Pi 的模型配置中添加或替换 dsv41-sparks 提供程序。安装程序会先创建带时间戳的备份,并保留其他提供程序不变。

如果使用 enabledModels 列表,安装程序会将所提供的模型添加到该列表中。设置 SET_DEFAULT=1 可将此模型设为 Pi 的启动模型。

已安装的扩展会移除此提供程序的 Pi 输出令牌限制,使响应能够自然结束。它会在请求时读取 DSV41_API_KEY,不会将密钥写入 Pi 的配置。

了解默认配置

scripts/launch.sh 会复现经过测量的服务配置。重要设置包括:

  • 使用 KV_BYTES=2700000000 的 FP8 KV 缓存。
  • 最大上下文长度为 262144 个令牌。
  • 最多两个并发序列。
  • 最大批处理令牌数设置为 2048。
  • 使用七个草稿令牌和自适应验证的 DSpark 推测解码。
  • 由磁盘支持的 Engram 表。
  • B12X 注意力、线性和 MoE 内核。
  • 使用 ST_EXL3_PREFILL=st 的 EXL3 路由专家。
  • FULL_DECODE_ONLY CUDA 图。
  • B12X RoCE 单次全归约,以及用于其余分布式操作的 NCCL over RoCE。
  • 每个多模态提示使用一张图像。
  • deepseek_v41 推理和工具调用解析器。

大多数设置都可以通过环境变量覆盖。模型目录由 MODEL_DIR 控制,工作进程的模型目录由 WORKER_MODEL_DIR 控制,持久化运行时数据由 STATE_DIR 控制。默认状态目录为 ~/.dsv41-two-sparks。

启动器会将模型以只读方式挂载到 /model。它会将 EXL3 分配计划复制到状态目录,并将其中的 bank 路径改写为已挂载的 EXL3 目录。

确保流量使用正确的网络

vLLM、NCCL 和 Gloo 进程必须绑定到 QSFP/RoCE 地址,而不是 Wi-Fi、以太网或 Tailscale 接口。启动器通常会检测活动的 RoCE 端口,并设置以下变量:

  • VLLM_HOST_IP
  • NCCL_SOCKET_IFNAME
  • GLOO_SOCKET_IFNAME
  • NCCL_IB_HCA

如果自动检测选择了错误的接口,请显式设置 HEAD_IP、WORKER_IP、HEAD_IFNAME、WORKER_IFNAME、HEAD_HCAS 或 WORKER_HCAS。使用 ip -br a 和 rdma link 识别正确的地址和 RDMA 设备。

安全管理内存

DGX Spark 在 CPU 和 GPU 之间共享 128 GB 内存池。如果可用内存降至零,主机可能会变得无响应,而不是正常终止容器。启动器会在两个节点上启动 scripts/memguard.sh,当可用内存低于配置的下限时停止 dsv41-r* 容器。

在以下位置查看内存保护程序日志:

~/.dsv41-two-sparks/memguard.log

在默认配置下,稳态可用内存约为 2–3 GiB。如果保护程序触发,请先降低 KV_BYTES 或 GPU_UTIL,再增大 MEMGUARD_GIB。

排查常见问题

启动速度缓慢

首次启动可能需要约 12 分钟,因为系统需要加载权重、准备 EXL3 bank、编译 B12X 内核并捕获 CUDA 图。内核缓存存储在 STATE_DIR/cache 下,因此后续启动可能更快。

缺少 Engram 文件

如果启动时报告缺少类似 model-00005-of-00006.safetensors 的文件,Engram 分片可能尚未重新组装。再次运行 scripts/download.sh。该命令会继续未完成的工作,并跳过已完成的步骤。

Fabric 检测选择了错误的接口

使用 ip -br a 检查地址,并使用 rdma link 检查 RDMA 状态。然后提供上文所述的头节点和工作节点接口、IP 及 HCA 变量。

下载速度缓慢

如果某个 Spark 只能通过 Wi-Fi 连接互联网,请在上行链路最佳的节点上下载检查点,然后使用 scripts/copy-to-peer.sh 通过 Fabric 传输。

Pi 看不到模型

确保在启动 Pi 的同一个 shell 中导出了 DSV41_API_KEY。在 Pi 中运行 /model 以重新加载模型列表。

Pi 打印模式无限等待

当标准输入不是终端时,pi -p 也会从 stdin 读取内容。在脚本中,请将 stdin 重定向到 /dev/null:

pi -p < /dev/null

结论

此仓库包含在两台 DGX Spark 上运行 DeepSeek-V4.1-Flash 所需的模型、服务镜像、分布式启动脚本、内存保护机制、验证工具和 Pi 集成。请准备 RoCE 网络,下载检查点并在两台节点上完成校验,启动两个 rank,运行冒烟测试,然后将兼容的客户端或 Pi 指向头节点的 OpenAI 兼容端点。