DeepSeek V4 Flash NVFP4 在 2×Jetson Thor 上的调试记录 1:SGLang 走到 DeepGEMM 前
这篇是调试记录,不是成功战报。
目标很直接:用两台 Jetson Thor,通过 QSFP28 互联,尝试启动 nvidia/DeepSeek-V4-Flash-NVFP4。这轮先验证 SGLang 路线,后面会继续试 vLLM / DSpark 路线。
结论先写在前面:
| 项目 | 当前结果 |
|---|---|
| 模型 | nvidia/DeepSeek-V4-Flash-NVFP4 |
| 运行框架 | SGLang nightly lmsysorg/sglang:nightly-dev-cu13-20260812-c7c03ec5 |
| 硬件 | 2× Jetson Thor |
| 网络 | QSFP28,4×10GbE;单次聚合 iperf 约 35.6 Gbit/s |
| 并行方式 | TP=1 + PP=2 |
| 当前状态 | 没有完成推理服务启动 |
| 进展 | 已完成分布式初始化、权重加载、DSV4 memory pool、FlashInfer autotune |
| 最终阻塞 | deepgemm/csrc/apis/hyperconnection.hpp:59: Unsupported architecture |
一句话:Thor 的系统、网络、容器和权重加载都已经越过了;真正卡点落在 DeepSeek V4 的 DeepGEMM HyperConnection/MHC kernel 对 Thor sm110 支持不足。
机器和网络
两台机器:
| 名称 | Tailscale | QSFP28 角色 |
|---|---|---|
thor | 100.98.202.31 | .1 侧 |
thor-jd | 100.98.98.105 | .2 侧 |
QSFP28 四个 mgbe 网段:
| 接口 | thor | thor-jd |
|---|---|---|
mgbe0_0 | 192.168.100.1/24 | 192.168.100.2/24 |
mgbe1_0 | 192.168.101.1/24 | 192.168.101.2/24 |
mgbe2_0 | 192.168.102.1/24 | 192.168.102.2/24 |
mgbe3_0 | 192.168.103.1/24 | 192.168.103.2/24 |
最终用于本轮 SGLang 分布式初始化的是 mgbe1_0:
NCCL_SOCKET_IFNAME=mgbe1_0
GLOO_SOCKET_IFNAME=mgbe1_0
NCCL_IB_DISABLE=1
NCCL_NET=Socket
QSFP28 聚合测速结果:
| 链路 | iperf3 结果 |
|---|---|
mgbe0_0 | 8.87 Gbit/s |
mgbe1_0 | 8.87 Gbit/s |
mgbe2_0 | 8.95 Gbit/s |
mgbe3_0 | 8.91 Gbit/s |
| 合计 | 35.61 Gbit/s |
配置过程已经单独整理在 docs/thor-qsfp28-40g-setup.md。
权重和镜像
模型权重先下载到一台 Ubuntu PC / 中转机 chip 的外接盘,再同步到两台 Thor:
/media/chip/f2c346e1-7a07-47bc-9af0-84c67f898fbe/models/nvidia/DeepSeek-V4-Flash-NVFP4
同步后的路径:
thor: /home/nvidia/models/DeepSeek-V4-Flash-NVFP4
thor-jd: /home/nvidia/models/DeepSeek-V4-Flash-NVFP4
权重大小约 157GB,包含 46 个 safetensors shard。
SGLang 使用的是:
lmsysorg/sglang:nightly-dev-cu13-20260812-c7c03ec5
容器内关键版本:
torch: 2.13.0+cu130
CUDA: 13.0
transformers: 5.12.1
sglang: 0.0.0.dev1+gc7c03ec53
GPU: NVIDIA Thor, capability (11, 0)
这版 SGLang 已经能识别 deepseek_v4,旧的 NGC sglang:26.04-py3 和 vllm:26.04-py3 不行,主要问题是 Transformers / model registry 太旧。
Docker runtime 先踩了一坑
thor-jd 重启后,Docker 的 NVIDIA runtime 一度被 CDI 配置卡住:
failed to inject CDI devices:
unresolvable CDI devices runtime.nvidia.com/gpu=all
Jetson / L4T 环境下,nvidia-ctk cdi generate 默认走 NVML 会失败:
Unable to determine the device handle for GPU0: 0000:01:00.0: Unknown Error
最后可用的修法是让 NVIDIA container runtime 强制走 CSV:
sudo cp /etc/nvidia-container-runtime/config.toml /etc/nvidia-container-runtime/config.toml.bak
sudo sed -i 's/mode = "auto"/mode = "csv"/' /etc/nvidia-container-runtime/config.toml
sudo systemctl restart docker
验证:
docker run --rm --runtime=nvidia lmsysorg/sglang:nightly-dev-cu13-20260812-c7c03ec5 bash -lc 'python3 - <<PY
import torch
print(torch.cuda.is_available())
print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else None)
print(torch.cuda.get_device_capability(0) if torch.cuda.is_available() else None)
PY'
恢复后的输出:
True
NVIDIA Thor
(11, 0)
为什么不用 TP=2
一开始试过跨节点 TP=2,但在 Ethernet QSFP28 上它不是一个好形态。
SGLang 日志里出现过:
CustomAllreduce is disabled because this process group spans across nodes
对于 DeepSeek V4 这种 MoE + MLA + FP4/NVFP4 路线,跨节点 tensor parallel 会放大通信压力。两台 Thor 没有 NVLink/NVSwitch,QSFP28 也不是 IB/RoCE,所以本轮改用:
TP=1 + PP=2
即两台机器做 pipeline parallel,各自持有一段层。
启动命令
worker 在 thor-jd:
docker run -d --name deepseek-v4-worker \
--runtime=nvidia \
--net=host \
--ipc=host \
--ulimit memlock=-1 \
--ulimit stack=67108864 \
-v /home/nvidia/models:/models \
-e CUDA_VISIBLE_DEVICES=0 \
-e NCCL_SOCKET_IFNAME=mgbe1_0 \
-e GLOO_SOCKET_IFNAME=mgbe1_0 \
-e NCCL_IB_DISABLE=1 \
-e NCCL_NET=Socket \
-e SGLANG_OPT_USE_TILELANG_MHC_PRE=0 \
-e SGLANG_OPT_USE_TILELANG_MHC_POST=0 \
-e SGLANG_DSV4_MHC_PREWARM=0 \
lmsysorg/sglang:nightly-dev-cu13-20260812-c7c03ec5 \
bash -lc 'python3 -m sglang.launch_server \
--model-path /models/DeepSeek-V4-Flash-NVFP4 \
--host 0.0.0.0 \
--port 30000 \
--dist-init-addr 192.168.101.1:20000 \
--nnodes 2 \
--node-rank 1 \
--tensor-parallel-size 1 \
--pipeline-parallel-size 2 \
--trust-remote-code \
--kv-cache-dtype fp8_e4m3 \
--mem-fraction-static 0.70 \
--max-running-requests 8 \
--chunked-prefill-size 2048 \
--disable-cuda-graph \
--bf16-gemm-backend torch \
--dsa-paged-mqa-logits-backend cutedsl'
master 在 thor,只改 --node-rank 0:
--node-rank 0
本轮还在容器内临时补了一个 KV scale fallback。原因是 NVIDIA 这个 NVFP4 checkpoint 在 SGLang 的 FP8 KV cache 路径里没有提供完整 scaling factors,原始代码会断言:
assert layer.k_scale > 0.0
临时补丁逻辑是:如果没有正数 scale,就默认用 1.0。日志也明确提示这可能影响精度:
Using FP8 KV cache but no scaling factors provided.
Defaulting to scaling factors of 1.0.
这不是生产补丁,只是为了推进启动链路,确认后面的阻塞点。
实测推进到了哪里
这轮成功越过了几个关键阶段。
分布式初始化:
[PP0] Init torch distributed ends. elapsed=14.17 s
[PP1] Init torch distributed ends. elapsed=28.51 s
权重加载:
[PP0] Load weight end. elapsed=110.23 s
[PP1] Load weight end. elapsed=86.11 s
模型被识别为:
DeepseekV4ForCausalLM
hybrid FP8+NVFP4 checkpoint
NVFP4 MoE group_size=16
DSV4 memory pool:
[PP0] DSV4 pool PP slice: rank=0 layers=[0,21) local=21/44
[PP1] DSV4 pool PP slice: rank=1 layers=[21,43) local=22/44
内存池初始化也完成:
[PP0] Memory pool end. avail mem=18.13 GB
[PP1] Memory pool end. avail mem=15.60 GB
然后进入 FlashInfer autotune:
Running FlashInfer autotune with cache:
/root/.cache/sglang/flashinfer/autotune/0.6.15.post1/sm110/...
到这里为止,系统层面已经相当接近“服务启动前最后一步”。
最终失败点
两边最终都在 warmup forward 阶段失败:
Scheduler hit an exception
self.warmup()
File ".../base_runner.py", line 247, in warmup
RuntimeError: Assertion error (/deepgemm/csrc/apis/hyperconnection.hpp:59):
Unsupported architecture
这说明我们关掉了 TileLang MHC pre/post 和 prewarm 后,SGLang 在实际 forward warmup 里仍然会走到 DeepGEMM HyperConnection / MHC 路径,而这条路径当前不支持 Thor 的 sm110。
换句话说,瓶颈已经不是磁盘、网络、Docker、模型识别、权重读取或 distributed init,而是 DeepGEMM kernel architecture coverage。
这轮得到的判断
nvidia/DeepSeek-V4-Flash-NVFP4权重可以在两台 Thor 上完整读取。- SGLang nightly 已经支持
deepseek_v4和 hybrid FP8+NVFP4 checkpoint。 - QSFP28 单链路可以承担 torch distributed rendezvous,分布式初始化能过。
TP=1 + PP=2是当前比跨节点TP=2更合理的形态。- KV cache scaling factor 需要 SGLang 侧更稳的 fallback 或 checkpoint 侧提供完整 scale。
- 最终启动失败的主因是 DeepGEMM HyperConnection 不支持
sm110。
所以这条 SGLang 路线继续往下走,需要源码级处理:
| 方向 | 代价 | 备注 |
|---|---|---|
| 在 SGLang 里彻底禁用 DeepSeek V4 MHC runtime 路径 | 中 | 可能牺牲性能,但最适合先跑通 |
为 DeepGEMM HyperConnection 增加 sm110 支持 | 高 | 需要编译和 kernel 级验证 |
| 换 vLLM / DSpark 路线 | 中 | 已经拉到可在 Thor 上启动的 DSpark 镜像 |
下一步:vLLM / DSpark
参考双 DGX Spark 路线的文章使用的是:
ghcr.io/anemll/dspark-vllm-gx10:0.1.1
vLLM 0.25.2
DeepSeek-V4-Flash-0731
TP=2
nvfp4_ds_mla KV cache
我已经把这个 DSpark 镜像拉到 thor,并做了单机探针:
Linux-6.8.12-tegra-aarch64
torch 2.11.0+cu130
CUDA 13.0
cuda available: True
GPU: NVIDIA Thor
capability: (11, 0)
vLLM: 0.25.2.dev0
transformers: 5.13.1
这并不等于它能跑 DeepSeek V4,因为该镜像明显面向 DGX Spark / GB10 / sm_121a 做过优化,而 Thor 是 sm110。但至少它能在 Thor 上启动并识别 GPU,值得作为下一篇继续测试。
参考链接:
- SGLang releases: https://github.com/sgl-project/sglang/releases
- DeepSeek V4 on dual DGX Spark reference: https://github.com/maliubiao/dgx-spark-2-deepseek-flash-0731
- NVIDIA model page: https://huggingface.co/nvidia/DeepSeek-V4-Flash-NVFP4
测试时间:2026 年 8 月 13 日。本文是调试记录 1,不声称已经完成 DeepSeek V4 Flash NVFP4 在 2×Jetson Thor 上的成功推理。