📷 (此处预留位置:DGX Spark 真机实拍照片)

去年年底我们搞了两台 DGX Spark,本来只是当个好玩的桌面工作站。结果半年下来,它变成了公司内部 AI 服务的主力机房。

这篇不讲玄学,只讲三件事:怎么把它凑成双机、路上摔了哪些跤、以及十个人同时用会怎样。

最后一节是重点——压力测试的结论可能跟你想的不太一样。

硬件:为什么是两台

先说清楚我们手里有什么:

节点GPU内存存储
Spark 1GB10128GB 统一内存3.7TB NVMe
Spark 2GB10128GB 统一内存3.7TB NVMe

GB10 有个和普通显卡完全不同的地方:CPU 和 GPU 共用同一块 128GB 内存。 这意味着什么?模型权重、KV Cache、CUDA 中间结果全挤在一个池子里。显存大小不再是固定值,而是你挤出来的

两台机器用 ConnectX-7 200GbE RoCE 直连,MTU 9000。为什么要走 RDMA?因为双机跑一个大模型时,两台机器每算一层就要互相对话一次。走普通 TCP,光传输开销就能把计算时间吃掉一半。

我们的分工:Spark 1 当老大(head),Spark 2 当小弟(worker),模型切一半放一台,tensor-parallel-size 2

第一个大坑:官方镜像慢 3.65 倍

这是整件事最反直觉的部分。

按官方文档来,你该拉 NVCR 的 Docker 镜像,一行命令跑起来。我们当时也是这么干的,结果速度 13 tok/s——社区基准是 49 tok/s。差了 3.65 倍。

原因是个架构守卫 bug。

GB10 的架构代号是 sm_121a。vLLM 的 CMake 在判断「要不要为这个芯片编译高性能内核」时,用的是 12.0f 去匹配。12.1 匹配不上,于是官方镜像里根本没有为 GB10 编译的原生 kernel,全程走一条慢得多的回退路径。

解法很朴素:别用 Docker,用 pip 装。

pip 安装时工具链会自动检测出真实架构并现场编译原生 kernel。速度立刻从 13 跳到 49 tok/s。

记住这个原则:在边缘 AI 硬件上,别相信官方镜像的性能。先跑一版基准,确认 kernel 是不是真的跑在了你的芯片上。

顺带一提,这个理由也帮我省了个麻烦——国内网络拉 NVCR 极慢,pip + 镜像源反而更快。

部署 DeepSeek-V4-Flash:几个关键参数背后的道理

当前主力模型是 DeepSeek-V4-Flash-0731,参数规模看着吓人:

属性
总参数 / 活跃参数284B / 13B
量化FP8(官方权重)
权重体积~156 GB(48 个 shard)
上下文1,000,000 tokens

156GB 权重除以两台机器,每节点大约 81.5GB。加上 KV Cache 和系统开销,128GB 统一内存刚刚好——这就是「双机顶四机」的全部含义:不是算力翻倍,而是把内存拼够了。

单机模式是跑不起来的,物理上装不下。

这里有个特别容易踩的坑,值得单独拎出来:双机模式不要随便开 FP8 KV Cache。

FP8 KV Cache 的好处是省一半内存,看起来很香。但在 GB10 上,如果没有校准用的 scale factors,vLLM 会用 q_scale=1.0 这种没校准的值。而 GB10 的 FP8 attention 内核路径和数据中心级 Blackwell 不一样,结果是——短输出正常,超过 500 个 token 就开始重复循环。

MiniMax M2.7 的官方部署指南也明确避开了 FP8 KV Cache。所以我们的 DeepSeek 这台用的是 bf16 KV Cache。这直接决定了后面压力测试的结局。

推测解码是速度提升的关键。

DeepSeek-V4-Flash 内置了 DSpark 推测解码模块(权重就藏在模型分片里,不用额外下载)。开启后:

配置速度
不开推测解码26.9 tok/s
DSpark(7 tokens)39-42 tok/s(+47~56%)

原理是让小模型先猜 7 个 token,大模型一次性批量验证。接受率 55-72%。关键点:贪心采样模式下输出完全无损——每个 token 都经过目标模型校验,猜错了就丢弃重来。这是个免费的加速,不牺牲任何质量。

踩坑记录:五个真实事故

1. 残留进程偷吃内存

失败一次后,内存里躺着一个叫 VLLM::Worker_TP1 的进程。注意大写 VLLM——用 grep vllm 根本搜不到它。

症状是启动时报「显存不足」,明明什么也没跑。两台机器都得清一遍。

教训:分布式训练的进程名往往和你 grep 的关键字大小写不一致。清进程前先 ps aux | grep -i 看一遍真实名字。

2. venv 里的 nvcc 版本混乱(最坑)

报错:ptxas: Unsupported .version 9.3; current version is '9.0'

虚拟环境里的 CUDA 工具链版本对不齐——nvcc 是 13.3(生成 PTX 9.3),ptxas 却是 13.0(只认 9.0)。这是环境里最阴险的一类问题:每个组件单独看都正常,凑在一起就编译失败。

解决:强制指向系统 CUDA,绕开 venv 里那套。

3. mp 模式 follower 崩溃

分布式后端选 mp 时,worker 节点会报 collective_rpc should not be called on follower node。加一个 --headless 参数解决。

4. 端口被占

29501 被上一次残留进程占住,启动直接 EADDRINUSE。启动前清一下端口就行。

5. 两套环境不能共存

机器上同时挂着两套 vLLM 环境(一套跑 DeepSeek,一套跑 MiniMax)。它们共享同一块 GPU 内存,绝对不能同时启动,否则必然 OOM。 切换前必须把上一套的进程全部杀干净——包括那些大写名字的残留进程。

压力测试:十个人用,机器就顶不住

现在到最实在的部分了。

上面那些 tok/s 数字都是单人测的。我们把它开放给全公司用了,情况就变了。

📷 (此处预留位置:Workbuddy 使用体验截图 / 界面)

公司把 DeepSeek-V4-Flash 开放给员工做办公和开发——处理合同、写代码、跑内部数据分析。这类工作涉及公司敏感数据,所以本地化部署是刚需,这也正是我们当初买这两台 Spark 的初衷。

单人体验很好:35-42 tok/s,1M 上下文,响应流畅。

然后到了上班高峰期。大约 10 个人同时在线时,问题开始暴露:

  • 卡顿,明显能感知到
  • KV Cache 占满后,首次吐字的延迟严重滞后——要干等好几秒才出第一个字
  • 更糟的是 Workbuddy 出现「无模型响应」:一个任务长期停在等待状态,既不报错也不返回,用户只看到一个永远转着的进度条

排查下来原因很明确,而且比预想的更值得警惕:

根本瓶颈不是算力,是 KV Cache 容量

我们为了质量放弃了 FP8 KV Cache,用 bf16。代价是每份上下文缓存占的空间翻倍。配置 max-num-seqs=4、1M 上下文时,KV Cache 总共只有约 20GB

10 个人并发,每人一份多轮对话历史,缓存瞬间打满。之后新请求没有缓存可用,只能等待释放——这就是「卡顿」和「首次吐字严重滞后」的来源。

而「任务卡死」是另一个层面的问题:智能体类应用会主动占住缓存。 一个多步骤任务从开始到结束,整段上下文都挂在缓存里。它不主动退出,别人就得干等。

一个容易被忽略的洞察

这里有个反直觉的发现:智能体应用的缓存命中率其实非常高。 反复相同的系统提示、工具定义、历史消息前缀,prefix caching 能大幅减少重复计算。

所以算力和算力利用率不是问题,问题纯粹是缓存池太小。

一个只能同时容纳 4 份上下文的池子,面对 10 个并发的智能体任务,就像一条四车道的高速上开了十辆车——不是车不够快,是路不够宽。

结论

这台机器跑 DeepSeek-V4-Flash,只适合 1-3 个用户轻度使用。

超过 3 人并发,性能急剧下降;到 10 人时,已经不是「慢」的问题,而是会出现任务挂起、无响应的功能性故障。

如果你也在评估这类双机方案的容量,请记住这个教训:先算 KV Cache 池能装几份上下文,再决定开放给多少人用。tok/s 数字只能说明单机体验,说明不了并发上限。

下一步:换个小得多的模型试试

现在这个局面其实点明了优化方向——不是加机器,而是换模型。

我们计划部署 Qwen3.8-Flash-Next 做对比测试。同样是「Flash 级」定位的模型,如果能在相近质量下把权重和缓存占用压下来,那么同样的硬件能服务的用户数可能会翻好几倍。

对比维度会包括:

  • 同等并发下的吞吐和延迟
  • KV Cache 占用与最大并发数
  • 智能体任务的缓存命中效率
  • 实际办公场景的任务完成率

结果出来后我单独写一篇。如果你也在自己折腾双机方案,或者已经在跑同类模型,评论区聊,我特别想听听实际并发跑到多少才开始崩。


硬件配置速查

  • 2 × DGX Spark(GB10,128GB 统一内存 / 3.7TB NVMe)
  • ConnectX-7 200GbE RoCE 直连,MTU 9000
  • vLLM 0.26.0(jasl fork)+ DeepSeek-V4-Flash-0731
  • bf16 KV Cache(约 20GB)+ DSpark 推测解码
  • 单人 39-42 tok/s | 推荐并发 1-3 人