DeepSeek-V4-Flash-0731 双 B300 + SGLang 部署实战
写在前面:本文记录在一台双卡机器上完成 DeepSeek-V4-Flash-0731 部署、工具调用修复和性能验收的全过程。目标是让后续维护者能够复现当前服务,并快速判断常见故障发生在哪一层。
1. 最终状态
| 项目 | 当前配置 |
|---|---|
| 模型 | DeepSeek-V4-Flash-0731(本地权重目录:/data/USER/models/DeepSeek-V4-Flash-0731) |
| 权重规模 | 48 个 safetensors 分片,155.43 GiB |
| GPU | 2 × NVIDIA B300 SXM6 AC |
| 单卡显存 | 275040 MiB,约 288 GB 标称容量 |
| 推理框架 | SGLang 0.5.16 |
| Python / PyTorch | Python 3.12.13 / PyTorch 2.11.0+cu130 |
| NVIDIA 驱动 | 590.48.01 |
| CUDA 编译器 | CUDA 13.3 |
| 并行策略 | TP=2 |
| MoE 后端 | flashinfer_mxfp4 |
| 推测解码 | DSPARK |
| API | OpenAI compatible,http://127.0.0.1:30000/v1 |
| 工具解析器 | deepseekv4 |
| 推理解析器 | deepseek-v4 |
| 最大模型上下文 | 1,048,576 tokens |
服务启动脚本为 serve.sh。经验证的核心命令如下:
CUDA_VISIBLE_DEVICES=5,7 \
/usr/local/deploy/deepseek-v4-flash/serve.sh
当前完整参数:
sglang serve \
--trust-remote-code \
--model-path /data/models/DeepSeek-V4-Flash-0731 \
--tp 2 \
--reasoning-parser deepseek-v4 \
--tool-call-parser deepseekv4 \
--moe-runner-backend flashinfer_mxfp4 \
--speculative-algorithm DSPARK \
--mem-fraction-static 0.90 \
--chunked-prefill-size 4096 \
--swa-full-tokens-ratio 0.1 \
--disable-custom-all-reduce \
--host 0.0.0.0 \
--port 30000
workbuddy使用部署的deepseekv4flash:
2. “满血”与精度说明
当前部署加载的是完整官方 DeepSeek-V4-Flash-0731 checkpoint,不是蒸馏模型,也没有在本地做二次量化。因此从模型身份和官方发布形态看,这是完整的官方 Flash 部署。
不过,官方 Flash checkpoint 本身并不是全 BF16 权重。模型 config.json 明确记录:
- MoE routed expert 权重为 FP4:
expert_dtype: fp4; - 其他量化矩阵采用 FP8 E4M3,动态 activation scheme;
torch_dtype: bfloat16表示未量化部分和默认计算路径,并不表示所有权重以 BF16 存储;- SGLang 对 DeepSeek V4 自动选择
fp8_e4m3KV cache。
本地权重约对应 304B 参数。若全部换成 BF16,仅权重理论占用就约为 608 GB,已经超过两张 B300 合计约 576 GB 的标称显存,还没有计入 KV cache、CUDA Graph、DSPARK draft、激活与通信缓冲。因此两张 B300 不适合全 BF16 常规部署。
结论:当前是“官方完整 Flash 精度”,不是“全 BF16 权重”。这不是部署过程中额外牺牲的精度。
3. 部署前检查
3.1 确认权重完整
du -sh /data/models/DeepSeek-V4-Flash-0731
find /data/models/DeepSeek-V4-Flash-0731 \
-maxdepth 1 -name '*.safetensors' | wc -l
本次结果为约 156G、48 个权重分片。
3.2 找到真正空闲的物理卡
nvidia-smi --query-gpu=index,name,memory.total,memory.used,utilization.gpu \
--format=csv,noheader
本次选择物理 GPU 5 和 7,并通过 CUDA_VISIBLE_DEVICES=5,7 映射为进程内逻辑 GPU 0 和 1。排查显存问题时要注意区分物理编号与进程内编号。
3.3 核对软件版本
/data/miniconda3/envs/sglang/bin/python -c \
'import sglang, torch; print(sglang.__version__, torch.__version__)'
本次使用已安装好的 /data/miniconda3/envs/sglang 环境,没有重新安装或升级依赖。
4. 环境修复
4.1 DeepGEMM 找不到 CUDA_HOME
现象:启动或执行 SGLang benchmark 时,导入 deep_gemm 报错:
AssertionError
... deep_gemm/cuda_helpers.py ... find_cuda_home()
根因:当前 Conda 环境包含 CUDA 组件,但 CUDA_HOME 未指向它。
修复:
SGLANG_ENV=/data/miniconda3/envs/sglang
CUDA_ROOT="$SGLANG_ENV/lib/python3.12/site-packages/nvidia/cu13"
export CUDA_HOME="$CUDA_ROOT"
export PATH="$CUDA_HOME/bin:$PATH"
这也是为什么单独运行 python -m sglang.benchmark.serving 时,必须带上与服务一致的 CUDA 环境变量。
4.2 CUDA 13.3 编译器与 CUDA 13.0 runtime headers 混用
当前环境的 nvcc 为 CUDA 13.3,而 PyTorch runtime 是 cu130。CCCL 会检查 toolkit compatibility,首次 JIT 编译时需要:
export NVCC_PREPEND_FLAGS=-DCCCL_DISABLE_CTK_COMPATIBILITY_CHECK
这是针对当前环境组合的兼容开关,不应无条件复制到版本完全一致的其他机器。
4.3 FlashInfer 固定寻找 lib64
现象:FlashInfer 编译阶段找不到 CUDA lib64,而 NVIDIA Python CUDA 包实际提供的是 lib。
修复:
ln -s \
/data/miniconda3/envs/sglang/lib/python3.12/site-packages/nvidia/cu13/lib \
/data/miniconda3/envs/sglang/lib/python3.12/site-packages/nvidia/cu13/lib64
当前软链接已经存在。重复创建前应先用 ls -ld 检查,避免覆盖真实目录。
5. 首次启动与缓存
第一次启动会经历以下阶段:
- 加载 48 个 target 权重分片;
- 加载 checkpoint 内附带的 DSPARK draft head;
- 重排 FP4 expert 权重;
- DeepGEMM JIT 预编译;
- FlashInfer MoE autotune;
- target 和 draft CUDA Graph 捕获;
- 服务 warmup 后才开放 ready 状态。
本机一次完整冷启动约 21 分钟,其中 DSPARK draft 对应的 FlashInfer autotune 和 CUDA Graph 捕获耗时最长。过程中长时间没有 HTTP ready 不代表卡死,应观察日志中的 autotune 进度、GPU 利用率和显存变化。
生成的缓存位于用户 cache 目录,例如:
/home/USER/.cache/sglang/flashinfer/autotune/
不要随意删除 DeepGEMM、FlashInfer 和 CUDA Graph 相关缓存,否则下次可能重新承担十几分钟的预热成本。缓存是否可复用取决于 SGLang、CUDA、GPU 架构和启动参数是否一致。
6. 工具调用故障与修复
6.1 原始故障
客户端按照 OpenAI 协议发送 tools,模型也生成了原生工具标记,但响应表现为:
message.tool_calls为null;- 原生
<invoke>或 DSML 标记泄漏到message.content; finish_reason是stop,不是tool_calls;- 客户端在工具标记附近停止正常渲染,看起来像回答被截断。
这说明模型生成了调用意图,但 SGLang 没有把模型原生格式翻译成 OpenAI tool_calls。
6.2 正确修复
SGLang 0.5.16 内置 DeepSeek V4 专用工具解析器和 Python chat encoder。启动时加入:
--tool-call-parser deepseekv4 \
--reasoning-parser deepseek-v4
当 tool_call_parser=deepseekv4 或架构为 DeepseekV4ForCausalLM 时,SGLang 会自动选择内置 dsv4 encoder,不需要手写或下载 Jinja chat template。
日志中的:
No HuggingFace chat template found
对这个 checkpoint 是预期现象。官方模型本身提供 Python encoding,而非 Hugging Face Jinja template。
6.3 DSPARK 与 tool_choice=required
tool_choice: "required" 会触发 grammar-constrained decoding,而当前 DSPARK speculative backend 返回:
DFLASH speculative decoding does not support grammar-constrained decoding yet.
因此客户端应使用:
{
"tool_choice": "auto"
}
若业务必须强制 required,需要另行评估关闭 DSPARK 后的性能和兼容性,不能只改客户端参数。
6.4 工具调用验收结果
已验证:
- 非流式响应返回标准
message.tool_calls; - 流式 SSE 返回标准
delta.tool_calls; - 最终
finish_reason=tool_calls; - 工具执行结果以
role=tool回传后,模型能够完成最终回答; - 10 个不同城市的强指令工具调用测试全部通过,成功率 10/10;
- 这 10 个短工具调用请求的非流式平均端到端延迟为 370.66 ms,P95(nearest-rank)为 435.28 ms。
7. 性能基准
7.1 测试方法
测试时间:2026-08-04。服务已完成 warmup,在本机 loopback 地址测试,不包含公网、反向代理或客户端网络开销。
使用 SGLang 自带 serving benchmark:
python -m sglang.benchmark.serving \
--backend sglang-oai \
--base-url http://127.0.0.1:30000 \
--model DeepSeek-V4-Flash-0731 \
--tokenizer DeepSeek-V4-Flash-0731 \
--dataset-name random \
--random-input-len 512 \
--random-output-len 128 \
--random-range-ratio 1 \
--request-rate inf
短上下文测试分别使用并发 1、4、8;长上下文测试使用 8192 输入、128 输出、并发 1。每组包含 1~2 个 warmup 请求,主测试固定生成 token 数,避免 EOS 和回答差异影响结果。
指标含义:
- TTFT:Time To First Token,从请求发出到收到第一个 token;
- TPOT:除首 token 外,每个输出 token 的平均耗时;
- ITL:相邻流式 token 的间隔;
- E2E:完整请求端到端耗时;
- output throughput:整个服务在测试窗口内每秒输出 token 数;
- accept length:DSPARK 每轮平均接受的草稿长度,越高通常表示推测解码命中更好。
7.2 测试结果
| 输入/输出 | 并发 | 请求数 | 平均 TTFT | P95 TTFT | 平均 E2E | 平均 TPOT | P95 ITL | 输出吞吐 | 请求吞吐 | DSPARK accept |
|---|---|---|---|---|---|---|---|---|---|---|
| 512 / 128 | 1 | 8 | 344.77 ms | 351.86 ms | 609.68 ms | 2.09 ms | 4.77 ms | 209.27 tok/s | 1.63 req/s | 3.29 |
| 512 / 128 | 4 | 16 | 506.09 ms | 870.36 ms | 1430.77 ms | 7.28 ms | 56.97 ms | 346.98 tok/s | 2.71 req/s | 3.59 |
| 512 / 128 | 8 | 24 | 910.54 ms | 1462.16 ms | 2113.15 ms | 9.47 ms | 57.16 ms | 478.80 tok/s | 3.74 req/s | 3.81 |
| 8192 / 128 | 1 | 4 | 455.39 ms | 484.64 ms | 673.14 ms | 1.71 ms | 2.12 ms | 189.08 tok/s | 1.48 req/s | 3.88 |
8K 输入场景报告的整体 input throughput 为 12101.42 tok/s。该数值按完整 benchmark 时长计算,不是隔离 decode 后的纯 prefill kernel 吞吐,因此只适合同配置横向比较。
7.3 结果解读
- 交互型单请求表现较好:512-token prompt 平均 TTFT 约 345 ms,128-token 响应平均约 610 ms 完成。
- 并发 8 时输出吞吐提升到约 479 tok/s,是并发 1 的约 2.29 倍;代价是平均 TTFT 上升到约 911 ms。
- 如果目标是交互体验,建议前置调度层把常态并发控制在 1~4;如果目标是批量吞吐,可以使用更高并发。
- P95 ITL 明显高于中位数,说明 continuous batching 下偶发 token 间隔会被 prefill/调度拉长。对强实时流式体验,应持续观察 P95/P99,而不是只看平均 tokens/s。
- DSPARK accept length 随并发约为 3.29~3.88,推测解码在当前 workload 下确实产生了有效接受。
- 8K prompt 平均 TTFT 约 455 ms,说明当前 DSV4 attention 和 chunked prefill 路径工作正常。
7.4 测试边界
本轮属于部署验收 benchmark,不等于模型质量评测或生产容量规划:
- 使用 synthetic random tokens,而非 ShareGPT、代码仓库或真实 agent trace;
- 样本量较小,适合发现明显退化,不适合承诺严格 SLA;
- 服务已经 warmup,冷启动时间不计入请求延迟;
- loopback 测试不包含 TLS、网关和跨机网络;
- throughput 测试走 OpenAI completions 路径,工具调用正确性另用 chat completions 验证;
- 未测试 64K、128K、384K 和 1M 上下文,也未测试多轮 radix cache 命中收益;
- 未运行 HumanEval、SWE-bench、Toolathlon 等模型能力基准。
原始 benchmark JSONL 建议单独保存(如 benchmarks/ 目录),便于后续与升级后的 SGLang、驱动或参数配置比较。
8. 常用检查与运维
检查服务:
curl http://127.0.0.1:30000/v1/models
检查实际启动参数:
ps -eo pid,etime,args | \
rg '[s]glang serve.*DeepSeek-V4-Flash-0731'
检查两张卡:
nvidia-smi --query-gpu=index,memory.used,memory.free,utilization.gpu,power.draw \
--format=csv,noheader | sed -n '6p;8p'
当前 --mem-fraction-static 0.90 会主动为权重、CUDA Graph 和大容量 KV pool 占用大部分显存。空闲时每张卡占约 261 GB 是正常现象,不代表显存泄漏。
停止服务时应先通过 ps 定位唯一 PID,再发送 SIGTERM:
kill -TERM <sglang-pid>
不要在机器上广泛 pkill python,避免影响同机其他训练或推理任务。
9. 后续建议
- 将脚本接入 systemd、Supervisor 或现有集群编排,补充日志轮转与异常拉起。
- 若需要生产 SLA,按真实 prompt 长度、输出长度和到达率至少持续压测 30 分钟,采集 P95/P98 TTFT、ITL、错误率、GPU 功耗和显存。
- 为 agent 场景补充真实多轮工具 trace 测试,包括并行 tool calls、工具报错、超时和长 tool result。
- 若升级 SGLang、PyTorch、CUDA 或驱动,先保留当前结果作为基线,再查找 parser、DSPARK accept length 和 CUDA Graph 是否退化。
- 启动日志中的 “FP8 KV cache 未提供 scaling factors,使用 1.0” 警告需要在未来官方 checkpoint 或 SGLang 更新后复核;当前功能与性能均通过,但它是值得持续跟踪的精度风险提示。
如果本文对你有帮助,欢迎点赞收藏。也欢迎在评论区交流你的部署经验。
更多推荐


所有评论(0)