跳到主要内容
AI教程

使用 TensorFold 在两台 DGX Spark 上部署 DeepSeek-V4.1-Flash-1017

了解如何使用 TensorFold、ConnectX-7 网络、Engram 存储、推测解码和兼容 OpenAI 的 API,在两台 NVIDIA DGX Spark 上部署 2.9 位 EXL3 DeepSeek-V4.1-Flash-1017 检查点。

使用 TensorFold 在两台 DGX Spark 上部署 DeepSeek-V4.1-Flash-1017

此项目的功能

此部署方案在两台 NVIDIA DGX Spark 上提供 DeepSeek-V4.1-Flash-1017,每台设备配备 128 GB 统一内存。它使用 TensorFold 原生 Zig 引擎,在每台 Spark 上运行一个 rank 并通过张量并行协同工作,同时在端口 8888 上提供兼容 OpenAI 的 API。

该配置使用实验性的 2.9 位 EXL3 检查点 Mia-AiLab/DeepSeek-V4.1-Flash-1017-EXL3-EAQ-v1-2.9-bpw。它支持模型的大上下文窗口、图像输入、工具调用、可选思考,以及使用检查点草稿块进行的 DSpark 推测解码。

该仓库会自动完成准备、Docker 镜像构建、检查点下载、rank 缓存创建、工作节点配置、服务器启动、冒烟测试和关闭流程。第一台 Spark 充当头节点:运行 API、协调配置并启动 rank 0。第二台 Spark 运行 rank 1。

架构与重要限制

TensorFold 运行 BertholomusAI dsv41 系列,并将张量并行度设为 two。两个 rank 通过直接的 ConnectX-7 链路通信。头节点接收 API 流量,而两台 Spark 各自在内存中保留约 98 GiB 的模型权重。

该检查点约为 196 GiB,分为 39 个分片。部署还需要 Engram 的两个未量化表,占用约 203 GB。Engram 表应复制到两台 Spark 的本地磁盘。在 NFS 上读取这些表可能会显著降低预填充和解码性能,因为解码会执行大量随机 4 KiB 读取。

该模型在技术上可以使用 1,048,576 个 token 的窗口,但头节点的可用内存是实际限制。在运行其他桌面和开发服务的头节点上,README 建议将 CONTEXT 保持在 524288 或更低,除非释放更多内存。

硬件和软件要求

  • 两台 NVIDIA DGX Spark 或配备 GB10、每台拥有 128 GB 统一内存的同等系统。
  • ConnectX-7 端口之间的直接 QSFP 连接。
  • 直接链路上的 IPv4 地址、正常工作的网络连接以及 RoCE v2 GID。
  • 两台系统使用相同的 GPU 时钟上限。README 建议使用 nvidia-smi -q -d CLOCK 检查时钟,并在适用时使用 nvidia-smi -lgc 0,2200。
  • 头节点可通过基于密钥的 SSH 连接到工作节点。
  • 两台系统均安装带 NVIDIA 容器运行时的 Docker,并且当前用户属于 docker 组。
  • 头节点上安装 git、python3 和 Hugging Face CLI。
  • 为检查点、Engram 表、rank 权重文件、Docker 镜像和缓存准备足够的存储空间。按标准配置,头节点约需 505 GB,工作节点约需 310 GB。

在每台 Spark 上,直接链路可能显示为两个网络设备和两个 RoCE 设备。为这两条链路配置地址,并在两台系统上使用相同的 MTU。

准备网络和 SSH 连接

为 ConnectX-7 接口分配私有子网地址。例如,README 使用了 192.0.2.1/24 和 192.0.2.2/24 等地址。确认两台系统可以通过目标链路互相 ping 通。

在头节点上为工作节点安装 SSH 密钥,并验证非交互式访问:

ssh-copy-id user@<worker>
ssh -o BatchMode=yes user@<worker> true

在本地配置文件中设置工作节点 SSH 目标和网络接口地址。工作节点不需要仓库副本。

配置 NFS 或本地存储

默认情况下,工作节点通过 NFS 以只读方式挂载头节点的 Hugging Face 缓存。在头节点上安装 NFS 服务器并导出缓存:

sudo apt install nfs-kernel-server
echo "$HOME/.cache/huggingface <worker-CX7-address>(ro,no_subtree_check)" | sudo tee -a /etc/exports
sudo exportfs -ra

工作节点可能需要主机的 NFS 客户端辅助工具,例如 Ubuntu 上的 nfs-common。准备脚本会创建只读 Docker NFS 卷,并检查工作节点能否看到所需文件。

若需要更好的隔离,或 NFS 不适用,可在每台 Spark 上放置所需缓存的本地副本。将 HF_CACHE 设置为本地目录树,将 NFS_VOLUME 设置为对应的主机路径,将 HEAD_NFS_SERVER 留空,并设置 PREPARE=0。本地缓存必须包含检查点的小文件、视觉分片 model-00039-of-00039、提供服务的 model/ 文件夹、kit、token 映射以及相应的 rank 权重文件。

克隆并配置仓库

在头节点上克隆仓库并创建本地配置文件:

git clone https://github.com/MiaAI-Lab/DeepSeek-v4.1-Flash-1017-2x-DGX-Sparks.git
cd DeepSeek-v4.1-Flash-1017-2x-DGX-Sparks
cp scripts/local.sh.example scripts/local.sh

编辑 scripts/local.sh,至少将 WORKER 设置为工作节点的 SSH 目标。如果工作节点的 SSH 路由与直接网络接口路由不同,请将 FABRIC_PEER 设置为工作节点的 ConnectX-7 地址。

大多数设置定义在 scripts/config.sh 中。常用值包括:

  • MODEL_ID 和 MODEL_REVISION,用于指定固定版本的 EXL3 检查点。
  • CONTEXT,默认值为 1048576。
  • PARALLEL,默认允许四个并发请求。
  • 如果需要 Hugging Face 身份验证,则设置 HF_TOKEN。
  • ABLIT,用于选择原始模式或消融模式。

启动前运行干检查

使用干运行模式检查检测到的链路和 Docker 命令,但不执行任何更改:

DRY_RUN=1 ./start.sh

该仓库还会执行 Shell 语法检查,并在准备过程中验证预期的网络、Docker、GPU、SSH 和内存条件。只有当两台 Spark 都具备配置的最低可用内存 MIN_AVAIL_GIB 时,启动过程才会继续。

启动双 Rank 服务器

从主节点启动完整部署:

./start.sh

首次运行时,脚本会构建 TensorFold 镜像,下载检查点和 Engram 表,准备 RoPE 表及图像路由数据,创建令牌和 Rank 文件,配置工作节点的存储,并启动两个 Rank。在 Spark 上构建 Zig 镜像大约需要六分钟,生成的镜像大小约为 24.9 GB。

启动后,脚本会等待 API 就绪并运行冒烟测试。成功启动后会报告 DeepSeek-V4.1-Flash-1017 已在端口 8888 上运行。

常用的生命周期命令包括:

./start.sh restart
./stop.sh

修改服务设置后使用 restart。停止脚本会先保存压缩日志,并根据 LOG_KEEP 保留最新日志,然后移除容器。

调用兼容 OpenAI 的 API

客户端应使用主节点地址和 /v1 路径,并使用准确的模型标识符 DeepSeek-V4.1-Flash-1017。例如,可以按如下方式配置兼容 OpenAI 的 Python 客户端:

from openai import OpenAI

client = OpenAI(
    base_url="http://<head-address>:8888/v1",
    api_key="unused"
)

response = client.chat.completions.create(
    model="DeepSeek-V4.1-Flash-1017",
    messages=[
        {"role": "user", "content": "Explain tensor parallelism briefly."}
    ],
    max_tokens=512
)

print(response.choices[0].message.content)

除非请求禁用了思考功能,否则模型会在回答前进行思考。请为推理和最终回答分配足够的 max_tokens,或在环境中配置相应的思考和推理设置。

验证文本、工具、图像和长提示词

该仓库包含用于检查运行中端点的验证工具:

python3 tools/validate.py http://<head-address>:8888 --model DeepSeek-V4.1-Flash-1017
API_URL=http://<head-address>:8888 python3 tools/toolcheck.py

验证套件涵盖文本、思考、工具、图像输入和长提示词。README 指出,图像输入和验证工具尚未在所报告的硬件组合上完成全面检查,因此应将这些测试视为部署检查,而非保证。

如需进一步诊断,请检查 Rank 日志:

docker logs -f dsv41-1017-exl3-tf
ssh <worker> docker logs -f dsv41-1017-exl3-tf

使用消融模式

默认配置使用原始的 Mia EAQ 2.9-bit 检查点。设置 ABLIT=1 后会保留该检查点,并应用来自 drowzeys/keys-DeepSeek-V4.1-Flash-1017-Abliterated 的匹配 Keys 覆盖层。

这是一个受限的 Hugging Face 仓库。在准备之前,请接受仓库条款,并使用具有访问权限的账户进行身份验证:

hf auth login
ABLIT=1 ./scripts/prepare.sh
ABLIT=1 ./start.sh restart

或者,在不将令牌写入 Shell 历史记录的情况下提供令牌:

read -rsp 'Hugging Face read token: ' HF_TOKEN; echo
export HF_TOKEN
ABLIT=1 ./start.sh restart
unset HF_TOKEN

覆盖层由 ABLIT_REVISION 固定版本。准备过程会创建独立的缓存路径和 Rank 缓存,避免原始数据与消融数据意外混用。重写后的分片可能需要相当于另一个检查点的存储空间,此外还需要为覆盖层和 Rank 文件预留空间。使用以下命令切回原始模式:

ABLIT=0 ./start.sh restart

README 明确指出,原始模式的性能和正确性结果并不能验证该引擎上的消融模式。同时,请确保准备和启动使用相同的 ABLIT 设置。

性能与调优指南

使用真实散文和代码提示词进行的报告测量显示,单个散文流的速度约为每秒 74.9 个令牌,单个代码流的速度约为每秒 109.9 个令牌。使用四个流时,散文总吞吐量约为每秒 130.0 个令牌,代码总吞吐量约为每秒 155.5 个令牌。对于长度从 8K 到 256K 个令牌的提示词,预填充速度约为每秒 2,000 至 2,180 个令牌。

结果取决于提示词内容、GPU 时钟、并发负载、存储和内存压力。随机词基准测试的草拟效果不如正常散文或代码,因此不应将其较低的解码数据视为引擎的一般限制。

  • 将 Engram 表保存在两台 Spark 的本地磁盘上。
  • 使用匹配的 GPU 时钟上限,因为张量并行 Rank 会反复同步。
  • 确保 CONTEXT 不超过主节点的内存容量,尤其是在主节点还运行其他软件时。
  • 在服务长提示词或多个并发用户时,谨慎设置 PARALLEL。
  • 更改网络或部署设置前使用 DRY_RUN=1。

可选的引擎开关与补丁

该仓库在 zig/patches/ 下包含引擎补丁。这些补丁默认关闭,并通过 start.sh 传递给两个 Rank。README 报告称,默认镜像已针对一系列提示词和并发场景下的令牌哈希一致性进行了测试。

TF_DS_ENGRAM_LANES=2 会为 Engram 读取启用第二个 I/O 环,但测量结果显示,在测试存储设备上其速度更慢。TF_DS_IDX_SPLIT=1 会将预填充索引器行拆分到各个 rank 之间,但在测试的这对设备上未显示出可测量的收益。如果各 rank 对此设置不一致,这对设备可能会挂起,因此默认仍将其禁用。

补丁 0005 改进了提示词处理的交错机制,使现有流能够在另一个长提示词进行预取时接收解码轮次。可以通过 PREFILL_INTERLEAVE_MS 调整其行为。补丁 0006 会为图像输入保留提示词状态,除非使用 TF_DS_IMAGE_CACHE=0 禁用此行为。

监控内存并避免不安全的上下文大小

内存是主要的运行约束。README 报告称,在一台约有 6 GiB 内存被其他软件占用的设备上,512K 上下文是可行的;而当对话不断增长时,655K 配置可能会低于内存保护阈值。项目包含看门狗,因为 Spark 在高负载并发处理多个长提示词时,如果达到内存下限,可能会冻结。

请从默认值或较为保守的 CONTEXT 值开始,使用实际工作负载进行测试,并在处理长对话历史期间监控可用内存。即使模型已成功加载,随着缓存对话不断增长,可用内存也可能下降。

结论

该仓库提供了一种自动化方式,可将 DeepSeek-V4.1-Flash-1017 分布到两台直接连接的 DGX Spark 上。硬件、RoCE 网络、SSH、Docker、存储以及 Hugging Face 访问准备就绪后,start.sh 会处理多阶段配置,并提供熟悉的 OpenAI 兼容端点。

为了实现可靠部署,应优先使用本地 Engram 存储、匹配的 GPU 时钟、保守的上下文大小,并仔细验证图像、工具和长上下文工作负载。消融覆盖层和引擎开关可用于实验,但文档记录的性能与正确性测量主要适用于原始检查点和默认引擎配置。