三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

保姆级教程 | 两台 DGX Spark 双机部署 DeepSeek V4 Flash(0731),从零到跑通 OpenAI 兼容 API

保姆级教程 | 两台 DGX Spark 双机部署 DeepSeek V4 Flash(0731),从零到跑通 OpenAI 兼容 API

本教程基于开源项目 spark-vllm-docker(B12X 内核分支)在双机 DGX Spark 集群上实测跑通。
覆盖:物理连接 → 网络配置 → 免密 SSH → 构建镜像 → ModelScope 下载模型 → 启动 vLLM → 验证推理,以及一路踩过的坑。


一、写在前面:这套方案能给你什么

1.1 硬件主角:DGX Spark

NVIDIA DGX Spark(代号 GB10)是一台「桌面级 AI 超算」:

  • 单颗 GB10 SoC,128GB 统一内存(LPDDR5x,CPU/GPU 共享);
  • 单卡 GPU,算力主打 FP4/FP8 推理场景;
  • 自带 ConnectX-7 网络控制器,单根 QSFP 线缆可提供最高200GRDMA(RoCE)互连;
  • 出厂 Ubuntu + Docker,开箱即用。

单机跑大模型往往显存不够,于是「双机/多机张量并行」成了把大模型搬到本地跑的关键玩法。DeepSeek V4 Flash 正是那种「单机装不下、双机刚好」的模型。

1.2 模型主角:DeepSeek V4 Flash 0731

deepseek-ai/DeepSeek-V4-Flash-0731是 DeepSeek 在 2026-07-31 发布的正式版推理模型,MIT 开源

指标数值
架构DeepSeekMoE(Mixture-of-Experts)
总参数量284B(含 DSpark 投机解码模块后约 304B)
单 token 激活参数13B
上下文窗口1M tokens(最大输出约 38 万 token)
权重精度路由专家FP4,非专家层 FP8
模型体积167GB
注意力混合注意力:CSA(压缩稀疏注意力)+ HCA(高度压缩注意力),KV 缓存省约 90%

这个量级 + 1M 上下文,单台 DGX Spark(128GB 统一内存)装不下,正是需要2 台做张量并行(TP=2)的典型场景。

1.3 部署方案全貌

┌────────────────────────────┐ QSFP 直连 / ConnectX 200G ┌────────────────────────────┐ │ DGX Spark 节点 A │ ════════════════════════════ │ DGX Spark 节点 B │ │ (head / 主控) │ rocep1s0f0,roceP2p1s0f0 │ (worker / 从节点) │ │ GB10 × 1 · 128GB 统一内存 │ ◄──── NCCL RDMA ────► │ GB10 × 1 · 128GB 统一内存 │ │ vLLM · TP rank 0 · :8000 │ │ vLLM · TP rank 1 │ └────────────────────────────┘ └────────────────────────────┘
  • 用开源项目spark-vllm-dockerB12X 镜像(基于 SM121 架构做了大量手写 kernel 优化);
  • 模型通过ModelScope(魔搭)下载,国内网络友好;
  • --no-ray多节点后端(PyTorch 分布式)+--tp 2让两台机器各出一块 GPU 张量并行。

1.4 前置清单

项目说明
硬件2 × DGX Spark(Ubuntu + Docker)
网络1 根 QSFP 线缆直连(可选再加 10G 管理网)
软件git、python3.10+、Docker(系统自带)、uv/uvx
时间网络/SSH 约 30 分钟;镜像构建约 2–40 分钟(取决于网络);模型下载约 1–2 小时

本文使用节点 A =192.168.100.10,节点 B =192.168.100.11(同一网段内即可,请按你实际规划替换)。


二、物理连接与网络配置(最容易出错的环节)

2.1 QSFP 直连

把两台 Spark 用一根 QSFP 线缆连起来,插在最外侧的 QSFP 口(从背面看是右边那个)。

实测:连一根线就能跑满带宽,双口都插没有额外收益,不必多插。更多台机器才需要 RoCE 交换机或 mesh 组网。

2.2 理解 ConnectX 的「孪生口」

DGX Spark 的 ConnectX 很特别:单根线缆背后其实有2 组 PCIe 5.0 x4 链路,每组链路由一对「Ethernet + RoCE」接口组成:

$ ibdev2netdev rocep1s0f0 port1==>enp1s0f0np0(Down)rocep1s0f1 port1==>enp1s0f1np1(Up)roceP2p1s0f0 port1==>enP2p1s0f0np0(Down)roceP2p1s0f1 port1==>enP2p1s0f1np1(Up)

也就是说,一个物理口对应两组「Ethernet + RoCE」:

  • Ethernet:enp1s0f1np1enP2p1s0f1np1
  • RoCE/IB:rocep1s0f1roceP2p1s0f1

vLLM 走的是RoCE RDMA,Ethernet 口只要配个 IP 用于带外控制即可。为了榨满带宽,NCCL 需要同时用两个 RoCE 口:NCCL_IB_HCA=rocep1s0f1,roceP2p1s0f1

上面的口名是文档示例(插的是「右一」口)。具体叫什么取决于你插的物理口:本文实测机器插的口对应enp1s0f0np0(Ethernet)+rocep1s0f0/roceP2p1s0f0(RoCE)。launch-cluster.sh会自动探测并设好NCCL_IB_HCA,你只要按 2.3 把对应的 Ethernet 口配上 IP 即可。

好消息launch-cluster.sh会自动探测这些接口并设置好环境变量,你只需要把 Ethernet 口配好静态 IP。

2.3 配置静态 IP

给两台机器的 ConnectX Ethernet 口配上同一网段的静态 IP。注意:接口名取决于你插的物理 QSFP 口,本文实测机器为enp1s0f0np0,用ip linkibdev2netdev确认你实际的口名(插另一个口可能是enp1s0f1np1)。

一条命令立即生效(临时,重启会丢)—— 本文实测用法:

节点 A(主节点):

sudoipaddradd192.168.100.10/24 dev enp1s0f0np0sudoiplinksetenp1s0f0np0 up

节点 B(工作节点):

sudoipaddradd192.168.100.11/24 dev enp1s0f0np0sudoiplinksetenp1s0f0np0 up

⚠️ 两个节点配同一个网段即可互通。想榨满 200G 带宽可以把每个口的两组孪生口(enp1s0f0np0enP2p1s0f0np0)都配 IP,但两个孪生口千万不要配在同一网段,会干扰自动发现并搞乱路由。NCCL 走 RoCE 不走 Ethernet,本文实测只配一个 Ethernet 口就足够。launch-cluster.sh会自动探测 RoCE 接口并设置NCCL_IB_HCA

2.4 验证网络

ipaddr show enp1s0f0np0# 确认节点 A 拿到 192.168.100.10ping-c3192.168.100.11# 节点 A 上 ping 节点 B

2.5 配置免密 SSH

主节点上生成密钥并分发到所有从节点(后续launch-cluster.sh/build-and-copy.sh都要靠免密 SSH 跨机操作):

ssh-keygen-trsa-b4096-f~/.ssh/id_rsa-N""ssh-copy-id root@192.168.100.11sshroot@192.168.100.11# 验证免密登录成功

建议顺手把PermitRootLogin等 sshd 配置检查一遍,确保 root 能免密登录。没有 root 权限,后面容器/系统级操作会很痛苦。


三、克隆项目与环境准备

主节点(节点 A)上执行。

3.1 克隆 spark-vllm-docker

gitclone https://github.com/eugr/spark-vllm-docker.gitcdspark-vllm-docker

3.2 安装 uv / uvx

项目脚本依赖uvx(用来下载模型等):

curl-LsSfhttps://astral.sh/uv/install.sh|sh

国内网络慢的话可以换镜像:

curl-LsSfhttps://astral.org.cn/uv/install.sh|sh

装完把$HOME/.local/bin加进PATH,然后确认:

source$HOME/.local/bin/env uvx--version

3.3 生成 .env(自动发现节点)

网络 + 免密 SSH 就绪后,让项目自动探测集群并写入.env

./run-recipe.sh--discover

它会把CLUSTER_NODESCOPY_HOSTS等探测结果写进.env。也可以手动写,格式见.env.example

CLUSTER_NODES="192.168.100.10,192.168.100.11"COPY_HOSTS="192.168.100.11"

CLUSTER_NODES第一个 IP 是主节点(head)。COPY_HOSTS是镜像/模型分发目标,通常就是所有从节点。


四、构建并分发 B12X 镜像

4.1 为什么是 B12X

DeepSeek V4 Flash 用到的 B12X(SM120/121)手写 kernel(MLA 稀疏注意力、FP8 GEMM、MoE、MHC 超连接等)目前主要在B12X 分支的 vLLM 里有。所以不能用默认镜像,要用--exp-b12x

  • --exp-b12x默认直接拉取预编译好的eugr/spark-vllm-b12x:latest(快);
  • 想从源码编译就加--rebuild-vllm(慢,20–40 分钟);
  • 注意:B12X没有发布 vLLM wheels,所以--use-wheels与它不兼容。

4.2 一条命令构建 + 分发

./build-and-copy.sh --exp-b12x-c
  • --exp-b12x:选择 B12X 镜像预设,镜像 tag 为vllm-node-b12x
  • -c--copy-to):把镜像分发到COPY_HOSTS(来自.env或自动发现)里的所有节点。

网络慢的话,初次拉取 base 镜像 + B12X 镜像可能耗时较长,请耐心等待。之后重复构建会走缓存,快很多。隔一段时间可以用docker system dfdocker builder prune --filter until=72h清理构建缓存。

验证一下两台机器上都有镜像:

dockerimages|grepb12xsshroot@192.168.100.11"docker images | grep b12x"

五、让模型从 ModelScope 下载(国内网络友好)

5.1 思路

vLLM 默认从 HuggingFace 拉模型,国内经常拉不动。好在 vLLM 原生支持环境变量VLLM_USE_MODELSCOPE=TRUE,启动时会改从ModelScope(魔搭)下载。模型 ID 不变:deepseek-ai/DeepSeek-V4-Flash-0731

但有一个前提:镜像里要装了modelscope这个 Python 包。官方 vLLM 镜像一般没装,需要在容器里pip install modelscope

5.2install-modelscope这个 mod

项目支持「mod」机制:在容器启动前注入一段初始化脚本。仓库里的mods/install-modelscope/run.sh就是干这个的,完整内容如下:

#!/bin/bashset-euopipefailPREFIX="[install-modelscope]"# Tsinghua PyPI mirror (fast for CN networks)INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"# vLLM's modelscope_list_repo_files() expects the pre-1.38 get_model_files()# response format (files carry a "Type" key). modelscope>=1.38.0 broke that and# raises KeyError('Type') / unexpected 'revision' kwarg. vLLM's supported range# is >=1.18.1,<1.38; this pin forces the newest compatible build (1.37.x).MODELSCOPE_SPEC="modelscope>=1.18.1,<1.38"echo"=== Installing modelscope into the vLLM runtime environment ==="echo"$PREFIXusing PyPI mirror:$INDEX_URL"echo"$PREFIXinstalling:$MODELSCOPE_SPEC(pinned for vLLM compat)"if!command-vuv>/dev/null2>&1;thenecho"$PREFIX'uv' not found in container; falling back to pip">&2python3-mpipinstall-i"$INDEX_URL""$MODELSCOPE_SPEC"elseuv pipinstall--index-url"$INDEX_URL""$MODELSCOPE_SPEC"fipython3 -<<'EOF' try: import modelscope print(f"OK: modelscope {modelscope.__version__} is importable") except Exception as exc: raise SystemExit(f"modelscope import failed: {exc}") EOFecho"=== OK: modelscope installed, VLLM_USE_MODELSCOPE will work inside this container ==="

要点:优先用容器里的uv pip installuv不存在就退回pip);走清华 PyPI 镜像加速国内下载;装完会导入一次modelscope自检。

deepseek-v4-flash-0731这个 recipe 已经把 mod 和 env 都配好了(见下一节的 YAML):

mods:-mods/instanttensor-hybrid-draft-loader-mods/install-modelscopeenv:VLLM_USE_MODELSCOPE:"TRUE"

所以你什么都不用改,直接跑 recipe 即可:容器启动后先装 modelscope,vLLM 再从 ModelScope 下载模型。

5.3 版本 pin 的来龙去脉(重要)

为什么把 modelscope 钉在>=1.18.1,<1.38

因为modelscope>=1.38.0(2026-07 发布)改了HubApi.get_model_files()的响应格式,而 vLLM 的modelscope_list_repo_files()还在用旧格式,会直接报:

KeyError: 'Type'

所以强制装 1.37.x 这个最新兼容版本。等 vLLM 修了这个问题(见 vllm-project/vllm#47358)就可以放松上限。

5.4 宿主机预下载(可选,为了省时间)

vLLM 启动时才在容器内下载模型,容器重建后会重新下载。想省时间可以先在宿主机用 modelscope CLI 预下载:

pipinstallmodelscope modelscope download--modeldeepseek-ai/DeepSeek-V4-Flash-0731\--local_dir./models/deepseek-ai/DeepSeek-V4-Flash-0731

但注意:ModelScope 缓存默认在~/.cache/modelscope/hub它不在 launch-cluster.sh 的默认挂载目录里(默认只挂 vllm/flashinfer/triton/tilelang 和 HuggingFace 缓存)。要让容器看到宿主机缓存,需要手动挂载:

./run-recipe.sh deepseek-v4-flash-0731 --no-ray--tp2--namevllm_ds4\-v~/.cache/modelscope:/root/.cache/modelscope

本教程默认走「容器内自动从 ModelScope 下载」,不需要上面这步。


六、启动集群

./launch-cluster.sh-dstart

-d是 daemon 模式:把两台机器上的vllm_node容器以sleep infinity方式后台拉起,供后续exec使用。这一步做完可以确认:

dockerps# 本机容器sshroot@192.168.100.11"docker ps"# 对端容器

七、一行命令启动 vLLM

核心命令:

cd~/spark-vllm-docker ./run-recipe.sh deepseek-v4-flash-0731 --no-ray--tp2--namevllm_ds4

--served-model-name "deepseek-v4-flash"--api-key {api_key}已经写进 recipe 的 YAML(见 7.1),启动时自动带上,不需要再在命令行传。要换 API 密钥,直接改recipes/deepseek-v4-flash-0731.yamldefaults.api_key的值即可。

参数拆解:

参数含义
deepseek-v4-flash-0731recipe 名(recipes/deepseek-v4-flash-0731.yaml
--no-ray多节点用 PyTorch 分布式后端(不依赖 Ray),双机 B12X 的默认推荐
--tp 2张量并行度 2:两台机器各出一块 GPU,模型权重一分为二加载
--name vllm_ds4容器别名,方便docker ps/docker logs识别
--served-model-name "deepseek-v4-flash"给 API 起个短名字,调用时model字段就用它(在 recipe 的command里配好,见 7.1)
--api-key {api_key}为 API 加鉴权,所有请求都要带Authorization: Bearer头(密钥填在 recipe 的defaults.api_key

想指定上下文长度 / 显存占用:

./run-recipe.sh deepseek-v4-flash-0731 --no-ray--tp2--namevllm_ds4\--max-model-len262144--gpu-mem0.85

recipe 里的--max-model-len默认是auto,vLLM 会根据显存自动计算;固定长度就显式传。--served-model-name--api-key已写在 recipe YAML 里(见 7.1),无需命令行传;其他自定义 vLLM 参数在--之后追加即可。

7.1 这个 recipe 长什么样

recipes/deepseek-v4-flash-0731.yaml的内容大致如下(已含 ModelScope 相关改动):

model:deepseek-ai/DeepSeek-V4-Flash-0731container:vllm-node-b12xbuild_args:---exp-b12xcluster_only:truemods:-mods/instanttensor-hybrid-draft-loader# 主模型 InstantTensor,投机草稿懒加载-mods/install-modelscope# 容器内安装 modelscopedefaults:port:8000host:0.0.0.0tensor_parallel:2gpu_memory_utilization:0.85max_model_len:autoblock_size:256max_num_seqs:8max_num_batched_tokens:8192max_cudagraph_capture_size:64num_speculative_tokens:5api_key:"你的API密钥"# 填你自己的 API 密钥env:VLLM_USE_MODELSCOPE:"TRUE"# 从 ModelScope 下载模型CUTE_DSL_ARCH:"sm_121a"VLLM_USE_AOT_COMPILE:"1"# AOT 编译VLLM_USE_B12X_WO_PROJECTION:"1"# B12X 系列 kernel 开关VLLM_USE_B12X_MHC:"1"VLLM_USE_B12X_FP8_GEMM:"1"VLLM_USE_B12X_MOE:"1"VLLM_USE_B12X_SPARSE_INDEXER:"1"VLLM_USE_V2_MODEL_RUNNER:"1"...command:|vllm serve deepseek-ai/DeepSeek-V4-Flash-0731 \ --host {host} \ --port {port} \ --trust-remote-code \ --tensor-parallel-size {tensor_parallel} \ --kv-cache-dtype fp8 \ --block-size {block_size} \ --max-model-len {max_model_len} \ --max-num-seqs {max_num_seqs} \ --max-num-batched-tokens {max_num_batched_tokens} \ --gpu-memory-utilization {gpu_memory_utilization} \ --enable-prefix-caching \ --tokenizer-mode deepseek_v4 \ --tool-call-parser deepseek_v4 \ --enable-auto-tool-choice \ --reasoning-parser deepseek_v4 \ --reasoning-config '{{"reasoning_parser":"deepseek_v4","reasoning_start_str":"","reasoning_end_str":""}}' \ --default-chat-template-kwargs.thinking=true \ --default-chat-template-kwargs.reasoning_effort=high \ --load-format instanttensor \ --moe-backend b12x \ --linear-backend b12x \ --attention-backend B12X_MLA_SPARSE \ --served-model-name "deepseek-v4-flash" \ --api-key {api_key} \ --max-cudagraph-capture-size {max_cudagraph_capture_size} \ --compilation-config '{{"cudagraph_mode":"FULL_AND_PIECEWISE","custom_ops":["all"]}}' \ --speculative-config '{{"method":"dspark","num_speculative_tokens":{num_speculative_tokens},"draft_sample_method":"probabilistic","attention_backend":"B12X_MLA_SPARSE"}}'

注意 YAML 里的{{...}}是转义后的模板变量:run-recipe会用defaults里的值替换{host}{port}{api_key}等(对应run-recipe.py里的command.format(**params))。--served-model-name--api-key {api_key}就配置在这里。

启动命令里的关键 vLLM 参数:

  • --kv-cache-dtype fp8:KV 缓存用 FP8,大幅省显存;
  • --load-format instanttensor:流式加载,避免把 167GB 权重一次性塞进内存;
  • --attention-backend B12X_MLA_SPARSE:B12X 稀疏 MLA 注意力;
  • --speculative-config '{"method":"dspark","num_speculative_tokens":5,...}'DSpark 投机解码,草稿模型每步猜 5 个 token,显著提速;
  • --tokenizer-mode deepseek_v4--reasoning-parser deepseek_v4--tool-call-parser deepseek_v4:模型自带的推理/工具调用格式支持;
  • --default-chat-template-kwargs.thinking=true/reasoning_effort=high:默认开启思考模式、高推理强度;
  • --served-model-name "deepseek-v4-flash":给 API 起短名,调用时model字段用它即可;
  • --api-key {api_key}:API 鉴权,密钥填在defaults.api_keyrun-recipe会自动替换{api_key})。

7.2 启动日志里看什么

启动时会出现几段关键日志(正常现象,耐心等待):

  1. 容器内安装modelscopeinstall-modelscopemod 的输出);
  2. vLLM 从 ModelScope 下载模型(约 167GB,取决于带宽);
  3. AOT 编译VLLM_USE_AOT_COMPILE):首次会花一段时间生成编译产物,之后走缓存;
  4. InstantTensor 流式加载权重;
  5. NCCL/RDMA 初始化,两个 rank 握手;
  6. 最后出现Application startup complete或监听0.0.0.0:8000的日志。

建议用 tmux 跑,别关终端:

tmux new-svllm ./run-recipe.sh deepseek-v4-flash-0731 --no-ray--tp2--namevllm_ds4# Ctrl-b d 退出 tmux,随时 tmux a -t vllm 回来

八、验证与调用

服务监听在主节点:8000,即http://<主节点IP>:8000。本文主节点为192.168.100.10;如需从外部访问,用主节点的对外路由 IP(例如10.0.0.28,请换成你自己的)即可。

8.1 检查模型列表

curlhttp://192.168.100.10:8000/v1/models\-H"Authorization: Bearer 你的API密钥"

能列出deepseek-v4-flash(就是--served-model-name指定的名字)就说明加载成功。开启--api-key后,所有请求都要带上这个鉴权头,否则返回 401。

8.2 发起一次对话(含推理过程)

curlhttp://192.168.100.10:8000/v1/chat/completions\-H"Content-Type: application/json"\-H"Authorization: Bearer 你的API密钥"\-d'{ "model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "用三句话介绍 DGX Spark"}], "max_tokens": 512, "reasoning_effort": "high" }'

响应会带 DeepSeek 风格的reasoning_content(思考过程)和content(最终回答)。

8.3 用 Python OpenAI SDK 调用

fromopenaiimportOpenAI client=OpenAI(api_key="你的API密钥",# 与 --api-key 保持一致base_url="http://192.168.100.10:8000/v1",)resp=client.chat.completions.create(model="deepseek-v4-flash",# --served-model-name 指定的名字messages=[{"role":"user","content":"用三句话介绍 DGX Spark"}],max_tokens=512,extra_body={"reasoning_effort":"high"},)print(resp.choices[0].message.content)

8.4 在 GPU 上确认模型已加载

在任意节点执行nvidia-smi,能直接看到本节点的 vLLM 张量并行 worker 进程:

+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.142 Driver Version: 580.142 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA GB10 On | 0000000F:01:00.0 Off | N/A | | N/A 49C P0 12W / N/A | Not Supported | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 3300 G /usr/lib/xorg/Xorg 56MiB | | 0 N/A N/A 3445 G /usr/bin/gnome-shell 49MiB | | 0 N/A N/A 764903 C VLLM::Worker_TP0 10121... | +-----------------------------------------------------------------------------------------+

几个关键点:

  • VLLM::Worker_TP0表示本节点是张量并行 rank 0(主节点);对端节点(节点 B)会显示VLLM::Worker_TP1,用ssh root@192.168.100.11 "nvidia-smi"确认,两台机器都应看到各自的 worker 进程;
  • 有这个进程在,就说明模型权重已在本节点加载、vLLM worker 正常运行;空载时GPU-Util 0%、功耗只有十几瓦是正常的,有请求进来利用率会立刻拉高;
  • 注意Memory-Usage显示Not Supported:因为 GB10 是CPU/GPU 统一内存架构(128GB 共用),nvidia-smi不单独报告显存占用,这是正常现象,不代表没吃显存。

这样你就有了一套本地自托管的、OpenAI 兼容的 DeepSeek V4 Flash 推理服务,可以接进各类 Agent/工作流。


九、踩坑记录(FAQ)

9.1modelscopeKeyError: 'Type'

vLLM 从 ModelScope 拉模型时崩,报错KeyError('Type')/ unexpectedrevisionkwarg。

原因modelscope>=1.38.0改了 API 响应格式,和当前 vLLM 不兼容。

解决:本项目install-modelscopemod 已把版本钉在modelscope>=1.18.1,<1.38,直接用即可。手动的等价做法:在容器里执行
uv pip install "modelscope>=1.18.1,<1.38"

9.2 重启容器后模型又从头下载

ModelScope 缓存默认在容器内~/.cache/modelscope/hub不在 launch-cluster.sh 的默认挂载列表里,容器重建即消失。

解决(任选其一):

  • 接受每次重建重新下载;
  • 宿主机预下载后挂载:-v ~/.cache/modelscope:/root/.cache/modelscope
  • launch-cluster.shCACHE_DIRS_TO_CREATE增加~/.cache/modelscope

9.3:8000端口连不通

排查顺序:

dockerps# 容器是否在跑、名字是否为 vllm_ds4ss-lntp|grep8000# 端口是否监听curlhttp://127.0.0.1:8000/v1/models\-H"Authorization: Bearer 你的API密钥"# 本机先试

宿主机防火墙挡了的话(很多 DGX Spark 默认 iptables 策略较严):

sudoiptables-L-n# 看看是不是被 DROP 了sudoiptables-F# 临时清空(生产环境请用白名单规则)

9.4 改了配置/参数,重跑总是起不来

先用docker ps -a找到旧容器,停掉再重跑:

dockerps-adockerstop<容器ID>./run-recipe.sh deepseek-v4-flash-0731 --no-ray--tp2--namevllm_ds4

launch-cluster.sh对已存在的容器一般是复用,顽固的陈旧容器需要手动清理。

9.5 大模型用--load-format fastsafetensors内存爆炸

项目 README 明确警告:模型加载后占用超过可用 RAM 的 85% 时,别用fastsafetensors,可能直接 OOM。DeepSeek V4 Flash 这种 167GB 的模型请用 recipe 默认的--load-format instanttensor(流式加载到显存)。

9.6--tp到底该设几

DGX Spark 每台1 块 GPU,所以双机--tp 2正好用满两台。--tp会被 launch-cluster 换算成需要的节点数:双机集群--tp 2用两台,--tp 4会自动用满 4 台(如果你有更多 Spark)。别把--tp设成单机核数,那是误解。

9.7 国内拉 base 镜像太慢

  • 给 Docker 配置国内镜像加速器(registry mirror);
  • build-and-copy.sh默认拉eugr/spark-vllm-b12x:latest,如果已存在于本机就不会重复拉。

9.8 首次启动很久没反应

大概率在 AOT 编译或从 ModelScope 下载权重,用docker logs -f vllm_ds4(对端则ssh ... "docker logs -f vllm_ds4")看进度,别急着杀进程。


十、调参建议与性能

  • 投机解码:recipe 已开启 DSpark(num_speculative_tokens: 5),草稿模型随主权重一起加载。想省显存可降到 3,想更快可尝试 6–8(观察--speculative-config里的接受率日志)。
  • KV 缓存--kv-cache-dtype fp8+--block-size 256,配合模型自带的 CSA/HCA 注意力,1M 上下文才能塞进显存。不要关 FP8 KV
  • 推理强度:通过请求参数reasoning_effortlow/high/max)在速度与深度间取舍;不需要思考的简单任务设lowthinking=false提速明显。
  • 显存余量--gpu-memory-utilization 0.85是较稳的默认;跑满 1M 上下文长任务时,可以把并发压小(--max-num-seqs)或适当降长度。
  • 做一次吞吐测试:用 2–4 并发请求打满,观察 TTFT(首 token 延迟)与 TPOT(每 token 生成时间),再微调投机 token 数。每个人的带宽/任务不同,没有一个万能数字。

十一、参考链接

  • 开源项目:spark-vllm-docker(含 Networking 指南、Recipes 文档)
  • 模型介绍:Together AI 模型卡、The Batch 报道、Open Source For You
  • modelscope 版本兼容问题:vllm-project/vllm#47358
← 返回列表