DGX Spark 大模型部署工具 spark-vllm-docker

针对 DGX Spark 优化的 vLLM Docker(支持单节点或多节点)

本仓库包含在 DGX Spark 上运行 vLLM 所需的 Docker 配置和启动脚本,覆盖从单节点到使用 Ray 或 vLLM 原生 PyTorch 分布式模式的多节点集群。它支持 InfiniBand/RDMA(NCCL)、自定义环境配置,以及通过 fastsafetensors 和 InstantTensor 实现的高性能模型加载。
集群搭建支持双 Spark 直连、QSFP/RoCE 交换机配置以及 3 节点 mesh(网状)配置。

虽然它主要是为支持多节点推理而开发的,但在单节点配置上同样运行良好。

目录

DISCLAIMER

本仓库与 NVIDIA 及其子公司无关。这是一项社区努力,旨在帮助 DGX Spark 用户在 Spark 集群或单节点上搭建并运行最新版本的 vLLM。

默认情况下,build-and-copy.sh 会从 DockerHub 拉取经过测试的 nightly runner 镜像:eugr/spark-vllm:latest。Nightly 镜像在推进 latest 标签之前,会在集群和单机两种配置下针对多个模型进行构建和测试。
我们会不断扩大流水线中测试模型的范围,但由于 vLLM 是一个快速发展的平台,某些东西可能会出问题。

在不带本地构建标志或自定义参数的情况下选择 --exp-b12x,会拉取单独测试过的
eugr/spark-vllm-b12x:latest 镜像,并将其标记为 vllm-node-b12x

如果你只想从预编译的 vLLM 和 FlashInfer wheel 构建 runner,请指定 --use-wheels。该选项永远不会回退到编译缺失的 wheel:如果某个 wheel 无法下载或在本地找不到,命令会直接报错退出。要从 main 分支构建最新的 vLLM,请使用 --rebuild-vllm;要指定特定的仓库、release 或 commit,请设置 --vllm-repo 和/或 --vllm-ref

类似地,--rebuild-flashinfer--flashinfer-ref--apply-flashinfer-pr 用于控制 FlashInfer 构建,并强制走本地构建路径。

QUICK START

构建

在本地检出仓库。如果使用 DGX Spark 集群,请在头节点上操作。

git clone https://github.com/eugr/spark-vllm-docker.git
cd spark-vllm-docker

准备容器镜像。

如果你只有一台 DGX Spark:

./build-and-copy.sh

在 DGX Spark 集群上:

请确保你已按照我们的网络指南将 Spark 互连并启用免密码 SSH。你也可以参考 NVIDIA 的 Connect Two Sparks Playbook,但使用我们的指南是最佳的入门方式。该指南还包含 3 节点 Spark mesh 集群的配置说明。

然后运行以下命令来拉取、打标签并将镜像分发到整个集群。

./build-and-copy.sh -c

默认镜像准备速度主要取决于你的网络连接,以及 eugr/spark-vllm:latest 是否已存在于本地。

对于网速较慢的情况,使用 --use-wheels 参数从预编译 wheel 构建可能会更快。首次构建速度取决于你的网速以及基础镜像是否已在本机。拉取基础镜像后,构建通常只需 2-3 分钟。

如果使用了 --use-wheels--rebuild-vllm--rebuild-flashinfer 或其他构建定制选项,脚本会保持本地 wheel 构建 runner 的路径。--use-wheels 本身只是下载或复用预编译的 wheel;源码编译只针对通过源码构建标志显式选择的依赖项。完整的源码重新构建可能需要 20-40 分钟,但后续构建会更快。

运行

单节点

launch-cluster.sh 支持 solo 模式,这也是目前在单台 Spark 上运行容器的推荐方式:

./launch-cluster.sh --solo exec \
  vllm serve \
    QuantTrio/Qwen3-VL-30B-A3B-Instruct-AWQ \
    --port 8000 --host 0.0.0.0 \
    --gpu-memory-utilization 0.8 \
    --load-format fastsafetensors

如果要发布服务器端口而不是使用 host 网络,请在 exec 之前传入 Docker 端口映射:

./launch-cluster.sh --solo -p 8000:8000 exec \
  vllm serve \
    QuantTrio/Qwen3-VL-30B-A3B-Instruct-AWQ \
    --port 8000 --host 0.0.0.0

在集群上

建议在启动之前先在一个节点上下载模型,并通过 ConnectX 互联分发到整个集群。这样可以避免集群中每个节点都从互联网重新下载模型。

本仓库提供了一个便捷脚本 hf-download.sh。以下命令会下载模型,并通过自动发现功能将其分发到整个集群。

./hf-download.sh QuantTrio/MiniMax-M2-AWQ -c --copy-parallel

启动模型:

./launch-cluster.sh exec vllm serve \
  QuantTrio/MiniMax-M2-AWQ \
  --port 8000 --host 0.0.0.0 \
  --gpu-memory-utilization 0.8 \
  -tp 2 \
  --distributed-executor-backend ray \
  --max-model-len 128000 \
  --load-format fastsafetensors \
  --enable-auto-tool-choice --tool-call-parser minimax_m2 \
  --reasoning-parser minimax_m2

启动器会使用并行标志所需数量的节点。在 2 节点集群中,该命令会使用两个节点;在更大的已配置集群中,多余的节点不会被使用。

注意: 如果你加载的模型会占用超过可用内存的 0.85(不含 KV 缓存),请勿使用 --load-format fastsafetensors,否则可能导致内存不足。

另外: 只要其他 vLLM 容器中有 bash,你就可以将它们与启动脚本配合使用。启动器默认会清除镜像的 entrypoint,以防止 vllm-openai 之类的容器在所有必要的初始化完成之前就启动 vLLM。不过,为获得最佳兼容性和最新功能,建议使用本仓库构建容器。

重要提示

你可能需要时不时清理一下构建缓存,特别是如果你从一开始就在使用这些容器构建。

可以通过运行以下命令检查构建缓存大小:

docker system df

首次清理缓存或发现缓存异常庞大时,请使用:

docker builder prune

不要每次重新构建都这么做,因为那会拖慢编译速度。

对于定期维护,我建议使用过滤器:docker builder prune --filter until=72h

CHANGELOG

2026-08-06

GLM-5.2 NVFP4 8 节点 Spark 集群配方

新增了仅限集群使用的 recipes/8x-spark-cluster/glm-5.2-nvfp4.yaml 配方,用于部署 nvidia/GLM-5.2-NVFP4。需要 8 个节点。该配方使用 vllm-node-b12x 镜像。

./run-recipe.sh recipes/8x-spark-cluster/glm-5.2-nvfp4.yaml

2026-08-03

新的 B12X 镜像

新增了 --exp-b12x(别名:--experimental-b12x)作为替代版本,基于 Luke Alonso 的 fork 构建。该 fork 支持一组针对 sm12x 架构的实验性高性能 B12X kernel。

由于它是从 fork 的 vLLM 分支构建的,因此(至少目前)将与主("常规")构建并行维护。

不带参数指定 --exp-b12x 会从 Dockerhub 拉取 eugr/spark-vllm-b12x:latest,该镜像目前由 CI 流水线与主镜像一起按 nightly 节奏构建和测试(前提是源分支或 B12X 有更新)。

添加 --rebuild-vllm 可从源码编译。

该预设默认镜像标签为 vllm-node-b12x;显式的 -t 仍然优先。可以通过一个或多个 --apply-vllm-pr 标志在该预设之上叠加额外的 vLLM 修改。PR 是从上游 vLLM 仓库应用的,而不是从 Luke 的 fork!如果指定了任何 PR,脚本将从源码构建,而不是使用预构建镜像。

该构建不会发布 vLLM wheel,但如果你从源码构建,它会复用已发布的 Flashinfer wheel(除非指定了 --rebuild-flashinfer)。

目前我们只有一个使用该构建的配方,后续会有更多。

DeepSeek V4 Flash 0731 B12X 集群配方

新增了仅限集群的 deepseek-v4-flash-0731 配方,用于在双 DGX Spark 集群上部署 deepseek-ai/DeepSeek-V4-Flash-0731。该配方需要 B12X 容器(vllm-node-b12x),可通过 ./build-and-copy.sh --exp-b12x -c 拉取(或者直接让配方系统替你拉取)。关于 b12x 构建的详情请参见上文。

./run-recipe.sh deepseek-v4-flash-0731

2026-07-30

Inkling Small NVFP4 支持

新增了对
thinkingmachines/Inkling-Small-NVFP4 的支持。至少需要双 DGX Spark 配置。

./run-recipe.sh inkling-small-nvfp4

首次运行时添加 --setup,以准备容器并下载、分发模型。

官方 vLLM 镜像支持:earlyoom、InstantTensor 和 SciPy

mods/use-official-vllm 现在除了安装其他 mod 所需的兼容性包之外,还会安装 earlyoom、InstantTensor 和 SciPy。这使得在启动 vllm-openai 等官方 vLLM 镜像时,launch-cluster.sh --earlyoom--load-format instanttensor 以及基于 SciPy 的功能均可使用。Python 包安装时会锁定镜像中现有的 Torch 包,以免在依赖解析过程中替换掉支持 CUDA 的构建。

可重复的 Docker 卷映射

launch-cluster.shrun-recipe.sh 现在支持可重复的 -v / --volume 映射,使用 Docker 的 local_path:container_path 语法。在集群模式下,每个映射都会应用到每个启动的节点。

./launch-cluster.sh --solo \
  -v "$PWD/models:/models" \
  exec vllm serve /models/qwen3.6-35b-a4b-nvfp4 ...

2026-07-14

自定义 vLLM 仓库和 PyTorch 版本

build-and-copy.sh 现在可以通过 --vllm-repo 从 fork 构建 vLLM。自定义仓库会绕过共享的上游 Git 检出缓存,强制进行 vLLM 源码构建,并抑制 Dockerfile 中的上游预设 PR(除非显式请求 --apply-preset-vllm-prs)。

--torch-version--torchvision-version--torchaudio-version 用于选择在源码构建环境和最终 runner 镜像中安装的包。省略 torchvision 和 torchaudio 的标志时,其版本仍由解析器选择;当没有匹配的 wheel 时,--torchaudio-version none 会省略 torchaudio。

local-inference-lab/vllm 任意 ref 构建时,也会自动克隆并构建 lukealonso/b12xmaster ref。该仓库产出 b12x 发行版。源层在每次适用的 runner 构建时都会刷新,因此之前缓存的克隆不会隐藏更新的上游提交。只安装本地构建的 B12X wheel:它的共享依赖来自 vLLM,因此像 CUTLASS DSL 这类与 API 相关的版本锁定不会在所选 vLLM 修订版本之下被升级。检出的 commit 会记录在镜像内的 /workspace/b12x-source-commit。B12X kernel 仍然在运行时 JIT 编译;构建其 Python wheel 不会为镜像构建增加额外的 CUDA 编译阶段。

2026-07-10

可选的 earlyoom 监控器

Runner 镜像现在包含 earlyoomlaunch-cluster.sh --earlyoom 可以将其作为容器前台进程运行,替代 sleep infinity。这保留了现有的启动器流程(Ray 和 vLLM 通过 docker exec 启动),同时让容器能够持续监控主机低内存状态。run-recipe.pyrun-recipe.sh 会将相同的 --earlyoom--earlyoom-args 选项透传给启动器。

默认策略是保守的,基于绝对内存值:-M 524288,102400 -s 100 -r 60。当可用内存低于 512 MiB 时发送 SIGTERM,低于 100 MiB 时升级为 SIGKILL,不会等 swap 写满才采取行动,并每分钟打印一次内存报告。你可以通过 --earlyoom-args 在每次启动时覆盖默认值,或设置 VLLM_SPARK_EARLYOOM_ARGS

构建和运行时兼容性更新

--gpu-arch 现在还会驱动 NCCL 的 NVCC_GENCODE 构建参数,使非默认的本地构建为与 Torch 和 FlashInfer 相同的目标架构编译 NCCL。

源码构建的 KV 缓存清理现在直接嵌入到 Dockerfile 中,而 mods/kv-cache-prealloc-cleanup 只保留运行时策略调整。

mods/gpu-mem-util-gb 已针对当前的 vLLM 内存分析代码进行了刷新,使固定 GiB 的 GPU 显存预留功能继续适配新的启动路径。

2026-07-02

默认使用预构建 runner 镜像

build-and-copy.sh 现在默认拉取预构建的 eugr/spark-vllm:latest,并在本地标记为 vllm-node 或通过 -t 请求的标签。latest 标签指向最新经过测试的 nightly 镜像。预构建镜像由 CI 流水线与预构建 wheel 同步更新,因此它们始终保持一致。

使用 --use-wheels 可保持之前基于 wheel 的 runner 构建路径。--exp-mxfp4 等构建定制标志、非默认的 --gpu-arch--vllm-ref--flashinfer-ref、重建/下载标志以及 PR 应用标志也会保持本地构建路径。--tf5 仍然是标签兼容性别名,会将预构建镜像拉取为 vllm-node-tf5

复制操作现在会在保存镜像之前检查本地和每个远程主机上的镜像 ID。已具有相同镜像 ID 的主机会被跳过,当所有目标都已是最新时,docker save 会被完全跳过。--no-build 仍然跳过镜像准备,只在需要时复制已存在于本地的标签。

2026-07-01

No-Ray 成为默认的多节点后端

launch-cluster.shrun-recipe.sh 现在默认使用 no-Ray 多节点启动。使用 --ray 可启用 Ray;在 Ray 模式下,如果 vLLM 命令省略了 --distributed-executor-backend ray,会自动补上。多节点启动仍接受 --no-ray 以保持兼容。

构建和依赖更新

我们现在使用 NCCL 的 main 分支,并在构建中包含新的实验性 vLLM Rust 前端。DeepGEMM 现在跟踪 nv_dev 分支。

Transformers 5 标志弃用

--tf5--pre-tf--pre-transformers 现在是已弃用的兼容性别名。它们不再覆盖依赖解析;只保留传统的默认镜像标签。之前使用 vllm-node-tf5 的配方现在使用标准的 vllm-node 镜像。

配方更新

新增了 gemma4-26b-a4b-nvfp4 配方,将 Qwen3.6-35B-A3B-NVFP4 配方还原为 --kv-cache-dtype fp8,并清理了受影响配方中过时的 TF5 构建参数。

2026-06-22

Deepseek V4 Flash 支持

基于新合并的 vLLM PR,新增了对 Deepseek V4 Flash 的支持及配方。请注意,该 PR 需要 DeepGEMM 的 nv_dev 分支,默认 vLLM 构建中不包含该分支,但本社区构建已包含。

运行 DSV4F 需要一个 Spark 集群(2 个或更多节点)。

运行方式:

git pull
./build-and-copy.sh -c
./hf-download.sh deepseek-ai/DeepSeek-V4-Flash -c
./run-recipe.sh deepseek-v4-flash --no-ray

新增 DeepGEMM 支持

vLLM 现在使用 NVIDIA 分支的 DeepGEMM,其中包含对 sm12x GPU 系列(包括 DGX Spark)的支持。
请注意,它目前与 NVRTC 编译器不兼容,因此新构建中已关闭 DG_JIT_USE_NVRTC

MiniMax AWQ Weight-Shape 加载器临时修复

在 Dockerfile 层面添加了一个临时修复,解决 vLLM nightly 的一个回归问题:加载时将 compressed-tensors MoE 的 weight_shape 元数据当作标量处理,导致受影响的 MoE 量化模型报错 shape '[]' is invalid for input of size 2

2026-06-18

KV 缓存预分配清理 Mod 和双 Spark 更新版 Qwen3.5-397B 配方

为源码构建的 vLLM wheel 添加了 KV 缓存预分配清理功能,在 vLLM 确定大小并分配 KV 缓存块之前清除已缓存的 CUDA 分配器内存。双节点 Qwen3.5-397B INT4 AutoRound 配方也在 mods/gpu-mem-util-gb 之后应用了 mods/kv-cache-prealloc-cleanup,以进行针对该模型的内存策略调整。

同一配方现在保留 108 GiB 的启动预留,设置 VLLM_MEMORY_PROFILER_ESTIMATE_CUDAGRAPHS=0,并使用手动 2.25 GiB 的 KV 缓存分配来绕过 vLLM 保守的基于 profiler 的 KV 预算。源码构建会在 KV 缓存确定大小之前处理仅用于 profiling 的 graph-pool 清理,而配方 mod 使环境变量完全跳过 CUDA graph 内存 profiling,并允许固定 GiB 预留参数与 --kv-cache-memory-bytes 共存,从而加载该模型。这可能会导致使用少量 swap 来卸载未使用的资源,因此请确保已启用 swap。

新增 nvidia/Qwen3.6-35B-A3B-NVFP4 配方

新增了 NVIDIA 针对 Qwen3.6-35B 模型的混合精度量化配方。与早期的 NVFP4 量化相比,它具有更高的精度和改进的性能。

使用方式:

  • qwen3.6-35b-a3b-nvfp4:启用 MTP 运行
  • qwen3.6-35b-a3b-nvfp4-no-mtp:禁用 MTP 运行

2026-06-10

DiffusionGemma 配方和 Mod

通过 mods/diffusiongemma 添加了对 Google DeepMind 的 DiffusionGemma 模型的 day0 支持。详情请查看 NVIDIA 博客

新增了四个仅限 solo 的 DiffusionGemma 配方:

  • diffusion-gemma-bf16-thinking:针对启用思考模式的 google/diffusiongemma-26B-A4B-it
  • diffusion-gemma-bf16:针对禁用思考模式的 google/diffusiongemma-26B-A4B-it
  • diffusion-gemma-nvfp4-thinking:针对启用思考模式的 nvidia/diffusiongemma-26B-A4B-it-NVFP4
  • diffusion-gemma-nvfp4:针对禁用思考模式的 nvidia/diffusiongemma-26B-A4B-it-NVFP4

非思考变体仍然保留 --reasoning-parser gemma4,因为即使禁用思考模式,这些模型也可能输出 Gemma4 通道标记。

示例:

./hf-download.sh google/diffusiongemma-26B-A4B-it
./run-recipe.sh diffusion-gemma-bf16-thinking --solo

run-recipe.sh 启动标志透传

run-recipe.sh 现在在运行配方时会透传额外的 launch-cluster.sh 标志:
--apply-mod-p / --publish--keep-entrypoint

端口发布仍然仅限 solo 模式,与 launch-cluster.sh 的行为一致。

2026-06-09

配方内存默认值

为了匹配当前的 vLLM 内存分配行为,将主要单节点和双节点配方中的默认 gpu_memory_utilization0.7 提高到 0.8

2026-06-07

Docker 基础镜像兼容性

默认 CUDA 基础镜像更改为 nvidia/cuda:13.0.2-devel-ubuntu24.04,以获得更广泛的主机兼容性。

Dockerfile 现在在安装自定义 NCCL Debian 包时还会传入 --allow-change-held-packages,避免镜像构建过程中替换被锁定的 CUDA/NCCL 包时出现 apt 失败。

2026-06-06

MiniMax 多节点回归问题临时修复

新增了一个有针对性的 Dockerfile 补丁,禁用 vLLM PR #43410 引入的 MiniMax QK RMSNorm CUDA IPC 融合路径。当张量并行跨越 DGX Spark 节点时,该融合路径可能会失败;该临时方案保留了 MiniMax 多节点 TP 功能,同时避免完全回退上游代码。

2026-06-03

Solo 端口发布

launch-cluster.sh 现在在 solo 模式下支持 Docker 风格的 -p / --publish 端口映射。使用端口发布时,启动器会将该 solo 容器从 host 网络切换为 Docker bridge 网络。

示例:

./launch-cluster.sh --solo -p 8000:8000 exec vllm serve ...

2026-05-29

Wheel 新鲜度检测

改进了 build-and-copy.sh 的 wheel 新鲜度检查,使更新的本地构建 wheel 不会仅仅因为文件名与最新 release 资产不同而被覆盖。脚本现在会在决定下载之前,将本地 wheel 的 mtime 与远程 release 资产的时间戳进行比较。此外,还从使用 GitHub API 切换为常规 HTTP 检查,以避免限流。

gpu-mem-util-gb 补丁刷新

刷新了 mods/gpu-mem-util-gb,使其能够适配上游行号/上下文漂移后较新的 vLLM CacheConfig 代码。

2026-05-28

StepFun Step 3.7 Flash 支持

新增了对 StepFun Step 3.7 Flash 多模态模型的支持。

至少需要集群中有 2 台 Spark。FP8 和 NVFP4 检查点均受支持。FP8 需要更多内存,因此建议使用 NVFP4。

请先更新仓库并构建新容器:

git pull
./build-and-copy.sh --cleanup -c

运行 NVFP4 版本:

下载模型:

./hf-download.sh stepfun-ai/Step-3.7-Flash-NVFP4 -c

运行:

./run-recipe.sh step-3.7-flash-nvfp4 --no-ray

运行 FP8 版本:

下载模型:

./hf-download.sh stepfun-ai/Step-3.7-Flash-FP8 -c

运行:

./run-recipe.sh step-3.7-flash-fp8 --no-ray

请注意,FP8 需要 --no-ray 才能装下完整上下文!

use-official-vllm NCCL 临时修复

更新了 mods/use-official-vllm,使其也能处理 vllm-project/vllm#42354 中跟踪的 NCCL 加载顺序 bug。当 pip 安装的 nvidia/nccl/lib/libnccl.so.2 和系统 libnccl2 同时存在时,该 mod 会将 pip 安装的 NCCL 路径重定向到系统 /usr/lib 的 soname,与修复多节点 DGX Spark 挂起问题的手动解决方案一致。

在启动模型之前将其与官方 vLLM 镜像配合使用:

./launch-cluster.sh -t vllm/vllm-openai:latest \
  --apply-mod mods/use-official-vllm \
  exec vllm serve ...

Wheel 安装期间的 Torch 版本锁定

在两个 Dockerfile 中,安装本地构建的 wheel 和最终运行时依赖时,通过 uv --override 锁定已安装的 CUDA torch 构建。这可以防止传递依赖在镜像构建期间将 torch 重新解析为 CPU wheel。

2026-05-22

新 Mod:use-official-vllm

新增了 mods/use-official-vllm,这是一个前置 mod,用于在官方 vLLM Docker 容器(例如 vllm-openai)中应用补丁。官方容器不附带 git,而多个 mod 需要它。如果 git 尚不存在,该 mod 会通过 apt-get 安装它。

请在其他需要 git 的 mod 之前应用它:

./launch-cluster.sh -t vllm/vllm-openai:latest \
  --apply-mod mods/use-official-vllm \
  --apply-mod mods/gpu-mem-util-gb \
  exec vllm serve ...

gpu-mem-util-gb 适配最新 vLLM Main

更新了 mods/gpu-mem-util-gb 补丁,使其能够干净地应用到当前的 vLLM main 分支。该 mod 现在会在启动时检查 git,如果缺少 git 则打印提示先应用 mods/use-official-vllm(在使用官方 vLLM 容器时相关)。

2026-05-18

NCCL 更新到 NVIDIA v2.30u1

Dockerfile 现在从 NVIDIA 的 v2.30u1 分支构建 NCCL,而不是自定义 NCCL fork。该分支融合了自定义 fork 的所有功能,并基于最新的 NCCL 版本。网络指南中的 NCCL 测试命令已更新为对 3 节点 mesh 集群使用相同的分支。

2026-05-14

默认清除 Entrypoint

launch-cluster.sh 现在在启动空闲集群容器时默认清除 Docker 镜像的 entrypoint。这使得具有服务器风格 entrypoint 的镜像(例如 vllm-openai)也能走相同的集群启动器流程。使用 --keep-entrypoint 可保留镜像的 entrypoint。

2026-05-10

Qwen3.5-397B 配方内存更新

更新了 Qwen3.5-397B AutoRound 配方以降低 OOM 风险。双节点配方现在使用标准分数形式的 --gpu-memory-utilization,3 节点流水线并行配方使用 InstantTensor 加载以降低内存压力。

2026-05-06

Qwen3.6-35B-A3B-FP8 配方

新增了 qwen3.6-35b-a3b-fp8qwen3.6-35b-a3b-fp8-dflash 配方,以及专门的 Qwen3.6 chat-template mod。DFlash 配方禁用了前缀缓存,因为它会导致精度问题。

2026-04-29

Gemma4 配方修复和实验性 b12x Mod

Gemma4-26B-A4B 配方现在使用 safetensors 加载,并且默认不再应用过时的工具解析器 mod。

2026-04-25

MiniMax-M2.7-AWQ 配方

新增了 minimax-m2.7-awq,一个仅限集群的 MiniMax M2.7 AWQ 配方,使用 cyankiwi/MiniMax-M2.7-AWQ-4bit

2026-04-14

为 vLLM 添加了 --load-format instanttensor 支持 - 感谢 @SeraphimSerapis。
目前还是一个实验性选项,但它比当前的 fastsafetensors 默认值加载更快。你需要重新构建容器才能开始使用该选项,但不需要触发源码构建。

2026-04-12

针对 Qwen3.5-397B 的 Drop-caches mod

更新了 Qwen3.5-397B 配方(双节点配置),使用新的 mod mods/drop-caches,在容器运行期间每分钟清除文件系统缓存,解决了 fastsafetensors 加载卡住以及在接近最大内存限制运行时的其他一些 bug。

2026-04-11

固定 PyTorch 版本

将 PyTorch 固定为 2.11.0 版本(之前使用 nightly 构建),以修复与 transformers 5.x 的不兼容问题,并避免构建中的 torch 版本不匹配。

2026-04-02

针对 Gemma4-26B-A4B 的"即时" FP8 量化新配方:

单台 Spark:

./run-recipe.sh gemma4-26b-a4b --solo

双台 Spark:

./run-recipe.sh gemma4-26b-a4b --no-ray

2026-03-31

指定 Flashinfer ref 和应用 PR 的标志

build-and-copy.sh 新增了两个标志,与现有的 vLLM 对应标志一致:

  • --flashinfer-ref <ref> — 从特定的 commit SHA、分支或标签构建 FlashInfer,而不是 main。强制本地构建 FlashInfer(跳过预构建 wheel 下载)。
  • --apply-flashinfer-pr <pr-num> — 在构建之前获取并应用 FlashInfer GitHub PR 补丁。可以指定多次。强制本地构建 FlashInfer。

这两个标志都与 --exp-mxfp4 不兼容。

build-and-copy.sh 中的默认镜像标签

未指定 -t 时,build-and-copy.sh 现在会自动设置合理的默认镜像标签:

  • --tf5 / --pre-tf - 已弃用的兼容性标志;常规构建,标签默认为 vllm-node-tf5
  • --exp-mxfp4 - 标签默认为 vllm-node-mxfp4
  • 其他所有情况 - 标签默认为 vllm-node(无变化)

显式的 -t <tag> 始终优先。

支持 3 节点 mesh 配置

新增了对 3 台 Spark 以环形 mesh 方式互连(无需额外交换机)的初步支持。
有关如何连接和配置此类集群网络的说明,请参阅网络指南

launch-cluster.shrun-recipe.sh 中的自动发现功能现在可以检测 mesh 配置并相应地配置参数。

你可以尝试使用以下配方以流水线并行配置在全部 3 个节点上运行模型:

./run-recipe.sh --discover # 强制进行 mesh 发现
./run-recipe.sh recipes/3x-spark-cluster/qwen3.5-397b-int4-autoround.yaml --setup --no-ray --force-build # 后续调用可以去掉 --setup 和 --force-build

请注意,任何常用模型都不支持 --tensor-parallel-size 3-tp 3,因此要利用全部三个节点运行单个模型,只有两种可行选择:

  • --pipeline-parallel 3 可以运行无法装入双 Spark 的模型,但没有额外的速度提升(不过总吞吐量可能会提高)。
  • --data-parallel 3(可能配合 --enable-expert-parallel)可以运行能装入单台 Spark 的模型,但能获得更好的并发性。

你也可以在 3 节点配置下以 --tensor-parallel 2 运行模型 - 在这种情况下,只会使用前两个节点(来自自动发现/.env 或 CLI 参数)。

节点发现期间的 GB10 验证

节点发现现在会在将每个 SSH 可达的对等节点加入集群之前,确认其为 GB10 系统:
只有报告 NVIDIA GB10 的主机才会被包含进来。这可以防止意外地将恰好位于同一子网的非 Spark 机器加入集群。

独立的 COPY_HOSTS 发现

自动发现现在会独立于 CLUSTER_NODES 确定用于镜像和模型分发的主机列表:

  • 非 meshCOPY_HOSTSCLUSTER_NODES 相同(行为不变)。
  • Mesh:扫描直连 IB 的 enp1s0f0np0enp1s0f1np1 接口(而非 OOB ETH 接口),使大文件传输使用更快的直连 InfiniBand 路径。

COPY_HOSTS 会保存到 .env,并被 build-and-copy.shhf-download.shrun-recipe.py 使用。

autodiscover.sh 中的交互式配置保存

autodiscover.sh 现在通过引导式交互流程处理 .env 的创建,取代了 run-recipe.py 中之前的逻辑:

  • .env 不存在时自动运行。
  • CLUSTER_NODESCOPY_HOSTS 都要求逐节点确认。
  • 如果 .env 已存在则跳过(使用 --setup 强制运行)。

run-recipe.py 不再包含自己的 .env 保存提示 — 它完全委托给 autodiscover.sh

launch-cluster.shbuild-and-copy.sh 中的 --setup 标志

这两个脚本现在都接受 --setup,以强制执行完整的自动发现并覆盖现有的 .env

./launch-cluster.sh --setup exec vllm serve ...
./build-and-copy.sh --setup -c

这等同于 run-recipe.sh 中现有的 --setup

--config 标志

hf-download.shbuild-and-copy.shlaunch-cluster.sh 现在都接受 --config <file> 来加载自定义的 .env 配置文件。配置中的 COPY_HOSTS 用于模型分发:

./hf-download.sh QuantTrio/MiniMax-M2-AWQ --config /path/to/cluster.env -c --copy-parallel

感知并行度的节点裁剪

launch-cluster.sh 现在会从 exec 命令或启动脚本中解析 -tp / --tensor-parallel-size-pp / --pipeline-parallel-size-dp / --data-parallel-size,并相应地调整活动节点数量 — 适用于 Ray 和 no-Ray 两种模式。

  • 如果需要的节点少于已配置的节点,只有所需节点会启动容器(多余的节点保持空闲)。
  • 如果需要的节点多于可用节点,会在启动任何内容之前报错。
Note: Command requires 2 node(s) (tp=2 * pp=1 * dp=1); using 2 of 3 configured node(s).
Error: Command requires 4 nodes (tp=4 * pp=1 * dp=1) but only 3 node(s) are configured.

无需任何标志 — 只要命令中存在并行参数,该检查就会自动进行。

2026-03-18

--master-port / --head-port 参数

launch-cluster.shrun-recipe.sh 中都新增了 --master-port(同义词:--head-port),用于配置集群协调所用的端口:

  • Ray 模式下:设置 Ray 头节点端口(之前硬编码为 6379)
  • No-Ray 模式下:设置传递给 vLLM 的 PyTorch 分布式 --master-port

默认值为 29501

./launch-cluster.sh --master-port 29501 --no-ray exec vllm serve ...
./run-recipe.sh qwen3.5-122b-fp8 --no-ray --master-port 29501

构建参数中的 --network 参数

build-and-copy.sh 新增了 --network <name>,允许在构建期间使用 host 网络。
感谢 @apairmont 提交的 PR。

2026-03-17

实验性 Intel/Qwen3.5-397B-A17B-int4-AutoRound 配方

你可以在仅两台 Spark 上运行完整的 397B Qwen3.5 模型,并支持视觉和完整上下文,但需要确保你的 Spark 没有运行任何会占用大量内存的其他程序。也就是说,你不应该登录图形界面或使用远程桌面。请通过 ssh 连接到头节点。

或者,你可以使用 sudo systemctl isolate multi-user.target 切换到非图形模式(runlevel 3)运行(可以使用 sudo systemctl set-default graphical.target 切换回图形模式),但已知这会略微降低性能。

你可以在头节点上使用以下命令运行模型:

./run-recipe.sh qwen3.5-397b-int4-autoround.yaml --no-ray

请注意,--no-ray 是装下完整上下文所必需的。它还能将推理速度提高约 1 t/s。
默认情况下,它会尝试在每个节点上为 vLLM 分配 108 GiB。你可以通过修改配方中的 gpu_memory_utilization 或传入 --gpu-mem 来更改;该配方将该值映射到 --gpu-memory-utilization-gb,因此单位是 GiB 而不是百分比。

已知问题

  1. 当前固件可能导致一台或两台 Spark 在高负载推理期间突然关机。如果你遇到此问题,需要在受影响的机器上降低 GPU 频率,例如 sudo nvidia-smi -lgc 200,2150。此命令会将 GPU 最大频率降至 2150 MHz。你可以尝试更高的值,看看多少适合你(默认为 2411 MHz,但最高可 boost 到 3000 MHz)。请注意,该设置只能保留到下次重启,但可以随时重新应用。
  2. 你需要使用新的 --no-ray 参数才能装下完整上下文。
  3. 如果模型在加载权重时卡住,在两个节点上清除缓存可以使其"解除卡顿"。使用 sudo sh -c 'sync; echo 3 > /proc/sys/vm/drop_caches' 清除缓存。

集群编排的重大重构

launch-cluster.sh 中的内部集群启动逻辑进行了重大重构:

  • 移除了独立的 run-cluster-node.sh 脚本;其逻辑现已完全集成到 launch-cluster.sh 中。
  • Ray head/worker 启动、环境变量注入和启动脚本分发现在由 launch-cluster.sh 直接处理。
  • Worker 容器启动时通过 docker run/docker exec 注入正确的逐节点环境变量(VLLM_HOST_IPNCCL_SOCKET_IFNAME 等),而不再依赖 .bashrc
  • 现在你可以运行其他 vLLM 容器而无需应用 use-ngc-vllm mod(当前版本只是一个空桩)。

No-Ray 多节点模式

launch-cluster.sh 中新增了 --no-ray 标志,用于在不使用 Ray 的情况下运行多节点 vLLM 集群,改用 PyTorch 原生分布式后端。它可以略微提升大多数模型的推理性能,并降低内存需求。

./launch-cluster.sh --no-ray exec vllm serve ...

--no-ray--solo 不兼容(后者本来就不使用 Ray)。

run-recipe.sh 的 No-Ray 模式和扩展标志透传

run-recipe.sh 现在支持 --no-ray 标志,用于在不使用 Ray 的情况下运行多节点推理(改用 PyTorch 分布式后端):

./run-recipe.sh qwen3.5-122b-fp8 --no-ray

以下 launch-cluster.sh 标志现在也会从 run-recipe.sh 透传:
--master-port--name--eth-if--ib-if-j--no-cache-dirs--non-privileged--mem-limit-gb--mem-swap-limit-gb--pids-limit--shm-size-gb

Nemotron-3-Nano-NVFP4 切换到 Marlin 后端

nemotron-3-nano-nvfp4 配方已更新为使用 Marlin 后端,以获得更好的性能和可靠性(直到 Flashinfer 在 sm121 上完全支持 NVFP4)。

2026-03-12

实验性 --gpu-memory-utilization-gb Mod

新增了新的 mod mods/gpu-mem-util-gb,为 vLLM 添加了 --gpu-memory-utilization-gb 标志,允许你以 GiB 而不是分数来指定 GPU 显存预留。这在 DGX Spark 的统一内存架构上特别有用,因为可用内存会动态变化。

./launch-cluster.sh --apply-mod mods/gpu-mem-util-gb exec vllm serve ... \
  --gpu-memory-utilization-gb 110

不能与 --kv-cache-memory-bytes 同时使用。

Qwen3.5-397B INT4-AutoRound TP=4 配方(4 台 Spark 集群)

新增了 recipes/4x-spark-cluster/qwen3.5-397b-int4-autoround.yaml,用于在 4 个 DGX Spark 节点上以张量并行(TP=4)运行 Intel/Qwen3.5-397B-A17B-int4-AutoRound。

基准测试:单用户约 37 tok/s,4 个并发用户聚合约 103 tok/s。

包含一个新的 mod mods/fix-qwen35-tp4-marlin,解决了 Marlin kernel 的限制(MIN_THREAD_N=64),该限制会在 TP=4 时导致某些投影层出错。

注意: 需要 NVIDIA 驱动 580.x。驱动 590.x 在 GB10 统一内存上存在 CUDAGraph 捕获死锁问题。

./run-recipe.sh 4x-spark-cluster/qwen3.5-397b-int4-autoround

感谢 @sonusflow 的贡献。

Nemotron-3-Super-120B NVFP4 配方

新增了配方 nemotron-3-super-nvfp4,用于使用 Marlin kernel 运行 nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4。支持 solo 和集群两种模式。包含从模型仓库获取的自定义推理解析器(super_v3_reasoning_parser.py)。支持双机和单机 Spark 配置。

./run-recipe.sh nemotron-3-super-nvfp4

2026-03-11

Qwen3-Coder-Next INT4-AutoRound 配方

新增了配方 qwen3-coder-next-int4-autoround,用于运行 Intel/Qwen3-Coder-Next-int4-AutoRound。仅支持单台 Spark(配合 --solo 开关使用),因为切分后的权重对于 Marlin kernel 来说太小。

./run-recipe.sh qwen3-coder-next-int4-autoround --solo

2026-03-06

run-recipe.py 中的 -e/--env 透传

run-recipe.sh 现在接受一个或多个 -e VAR=VALUE 标志,将环境变量直接传递给容器,与 launch-cluster.sh 的现有行为一致。

./run-recipe.sh qwen3.5-122b-int4-autoround --solo -e HF_TOKEN=$HF_TOKEN

Qwen3.5 的 Unsloth Chat Template

新增了新的 mod mods/fix-qwen3.5-chat-template,为 Qwen3.5 模型应用 Unsloth chat template,以更好地兼容现代客户端。该模板现已包含在 qwen3.5-122b-fp8qwen3.5-122b-int4-autoroundqwen3.5-35b-a3b-fp8 配方中。

修复 Exec 命令参数的 Shell 引号问题

修复了 launch-cluster.shrun-recipe.py 中 exec 命令参数的 shell 引号处理,以正确处理包含空格或特殊字符的参数。

2026-03-05

Qwen3.5-35B-A3B-FP8 配方

新增了配方 qwen3.5-35b-a3b-fp8,用于以 FP8 格式运行 Qwen3.5-35B-A3B。

./run-recipe.sh qwen3.5-35b-a3b-fp8

4 台 Spark 集群配方

新增了 recipes/4x-spark-cluster/ 子目录,包含针对 4 节点 Spark 集群优化的配方:

  • minimax-m2.5 — 在 4 台 Spark 上运行 MiniMax M2.5
  • qwen3.5-397b-a17B-fp8 — 在 4 台 Spark 上以 FP8 运行 Qwen3.5-397B-A17B

下载前更可靠的 Wheels 检查

改进了 build-and-copy.sh 中的 wheel 可用性检查,在决定是否下载远程 wheel 时更加可靠。

2026-03-04

通过 GitHub Releases 提供预构建 vLLM Wheels

build-and-copy.sh 会自动从 GitHub releases 下载预构建的 vLLM wheel,用于基于 wheel 的 runner 构建。它不会隐式回退到源码构建。

下载逻辑与 FlashInfer 的行为一致:

  • 如果预构建 wheel 可用且比任何本地缓存版本更新,则自动下载。
  • 如果下载失败(例如无网络、找不到 release、GPU 架构不受支持),脚本会在可用时复用现有的本地 wheel;否则退出并指明所需的显式源码构建标志。
  • --rebuild-vllm--vllm-ref--apply-vllm-pr 会完全跳过下载并强制本地构建。

无需新标志 — 下载会透明地进行。

所有预构建 wheel 现在都会作为自动化部署流水线的一部分,在 solo 和集群配置下针对多个模型进行测试,该流水线现在每晚运行。只有当 wheel 通过所有测试且未检测到重大性能回归时才会发布。

Qwen3.5-122B-FP8 配方

新增了配方 qwen3.5-122b-fp8,用于以 FP8 格式运行 Qwen3.5-122B。

./run-recipe.sh qwen3.5-122b-fp8

2026-03-02

Qwen3.5-122B-INT4-Autoround 支持

新增了对 Intel/Qwen3.5-122B-A10B-int4-AutoRound 模型的支持,并新增了 mod mods/fix-qwen3.5-autoround,修复了 ROPE 语法错误。

配方可在 recipes/qwen3.5-122b-int4-autoround.yaml 找到。

2026-02-26

Daemon 模式改进

  • 现在在指定 exec 操作时也可以使用 daemon 模式(solo 和集群均可)。
  • 在 daemon 模式下运行时,将 exec 命令的输出通过管道传入 docker logs。

2026-02-25

HF_HOME 支持

新增了对使用 $HF_HOME 环境变量作为 huggingface 缓存目录的支持。

Intel/Qwen3-Coder-Next-INT4-Autoround Mod

新增了针对 Intel/Qwen3-Coder-Next-INT4-Autoround 模型支持的 mod:mods/fix-qwen3-next-autoround

2026-02-21

Minimax 推理解析器更新

更改了 Minimax 的推理解析器,以更好地兼容现代客户端(例如编码工具)。

2026-02-18

构建流程彻底重新设计

build-and-copy.sh 会自动从 GitHub releases 下载预构建的 FlashInfer wheel,用于基于 wheel 的 runner 构建。它不会隐式回退到源码构建。

下载逻辑:

  • 如果预构建 wheel 可用且比任何本地缓存版本更新,则自动下载。
  • 如果下载失败(例如无网络、找不到 release、GPU 架构不兼容),脚本会在可用时复用现有的本地 wheel;否则退出并建议使用 --rebuild-flashinfer
  • --rebuild-flashinfer 会完全跳过下载并强制进行全新的本地构建。

无需新标志 - 除非指定了 --rebuild-flashinfer,否则下载会透明地进行。

Wheel 会按组件和配置文件缓存在 ./.wheel-cache 下,以便后续复用。

  • --rebuild-flashinfer 会强制从 flashinfer main 分支重新构建 FlashInfer。
  • --rebuild-vllm 会强制从 vLLM main 分支或 --vllm-ref 指定的特定 commit 重新构建 vLLM。

请注意,指定 --vllm-ref--apply-vllm-pr 每次都会强制重新构建 vLLM。

2026-02-17

非特权模式支持

launch-cluster.sh 中新增了 --non-privileged 标志,用于在不使用完全特权访问的情况下运行容器,同时保持 RDMA/InfiniBand 功能:

  • --cap-add=IPC_LOCK 替代 --privileged
  • --shm-size=64g 替代 --ipc=host(可通过 --shm-size-gb 配置)
  • 通过 --device=/dev/infiniband 暴露 RDMA 设备
  • 添加资源限制:内存(110GB)、内存+swap(120GB)、pids(4096)

用法示例:

./launch-cluster.sh --non-privileged exec vllm serve ...
./launch-cluster.sh --non-privileged --mem-limit-gb 120 --shm-size-gb 64 exec vllm serve ...

可能会带来轻微的性能下降(2% 以内),以换取更好的可靠性和稳定性。

Qwen3-Coder-Next 配方更新

更新了 qwen3-coder-next-fp8 配方:KV 缓存类型改为 fp8,最大上下文长度降至 131072 个 token,以可靠地装入单台 Spark 的内存。

2026-02-16

MiniMax M2.5 AWQ 配方

新增了配方 minimax-m2.5-awq,用于运行 MiniMax-Text-01-AWQ (M2.5)。用法:

./run-recipe.sh minimax-m2.5-awq

GLM-4.7-Flash-AWQ mod 扩展了 vLLM 崩溃修复

fix-glm-4.7-flash-AWQ mod 现在还会应用 PR #34695 中的修复,解决使用 AWQ 量化运行 GLM 模型时 mla_attention.py 中的崩溃问题。该补丁会与现有的速度修复一起自动应用,如果已合并到已安装的 vLLM 版本中则会跳过。

2026-02-13

FlashInfer cubin 缓存

FlashInfer cubins(预编译的 GPU kernel)现在通过 Docker bind mount 进行缓存,并在重新构建之间复用。之前,即使没有变化,每次重新构建 FlashInfer 时所有 cubin 都会从头重新编译。这显著减少了仅有少量源码改动时 FlashInfer 的重新构建时间。

2026-02-12

新增了一个针对 Qwen3-Coder-Next-FP8 的 mod,修复了以下问题:

该 mod 已包含在 qwen3-coder-next-fp8 配方中。

2026-02-11

可配置的 GPU 架构

build-and-copy.sh 中新增了 --gpu-arch <arch> 标志。这允许在构建过程中指定目标 GPU 架构(例如 12.0f),而不是硬编码为 12.1a。该参数同时控制 TORCH_CUDA_ARCH_LISTFLASHINFER_CUDA_ARCH_LIST 构建参数。

2026-02-10

缓存目录挂载

launch-cluster.sh 现在会自动将默认缓存目录挂载到容器中,以改善冷启动时间:

  • ~/.cache/vllm
  • ~/.cache/flashinfer
  • ~/.triton
  • ~/.tilelang

要禁用此行为(全新启动),请使用 --no-cache-dirs 标志。

2026-02-09

  • 迁移到了新的基础镜像,其中包含带 Spark 支持编译的 PyTorch 2.10。此更改后,wheel 构建不再是推荐方式 - 请改用源码构建。
  • Triton 3.6.0 现在为默认版本。
  • 移除了临时的 fastsafetensors 补丁,因为正确的修复已合并到 vLLM main 分支。

2026-02-04

配方支持

@raphaelamorim 的重大贡献 - 模型配方。
配方允许通过一条命令以预配置的设置启动模型。

示例:

# 列出可用配方
./run-recipe.sh --list

# 以 solo 模式运行配方(单节点)
./run-recipe.sh glm-4.7-flash-awq --solo

# 完整配置:构建容器 + 下载模型 + 运行
./run-recipe.sh glm-4.7-flash-awq --solo --setup

# 带覆盖参数运行
./run-recipe.sh glm-4.7-flash-awq --solo --port 9000 --gpu-mem 0.8

# 在配方 mod 之上应用额外的 launch-cluster mod
./run-recipe.sh glm-4.7-flash-awq --solo --apply-mod mods/use-official-vllm

# 在 solo 模式下发布端口
./run-recipe.sh glm-4.7-flash-awq --solo -p 8000:8000

# 集群部署
./run-recipe.sh glm-4.7-nvfp4 --setup

详情请参阅文档

启动脚本选项

你现在可以指定一个启动脚本在头节点上执行,而不是通过 exec 操作直接指定命令。
示例:

./launch-cluster.sh --launch-script examples/vllm-openai-gpt-oss-120b.sh

感谢 @raphaelamorim 的贡献!

构建期间应用 vLLM PR 的能力

./build-and-copy.sh 现在支持在构建时应用 vLLM PR。PR 补丁会应用到所选的 vLLM ref(--vllm-ref,默认为 main)上,且不携带 PR 分支的原始基础历史。这不适用于 MXFP4 特殊构建!

使用时只需在参数中指定 --apply-vllm-pr <pr_num>。对于普通的 main 源码构建,Dockerfile 预设的 vLLM PR 会自动应用。指定 --vllm-ref--apply-vllm-pr 中的任何一个都会抑制预设 PR,除非同时指定了 --apply-preset-vllm-prs;启用后,预设和请求的 PR 补丁都会应用到所选的 vLLM ref 之上。请注意,如果 PR 补丁无法干净地应用到所选 ref,可能会失败。请谨慎使用!

示例:

./build-and-copy.sh -t vllm-node-20260204-pr31740 --apply-vllm-pr 31740 -c

2026-02-02

Nemotron Nano mod

新增了支持 nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B 的 mod。它支持使用相同推理解析器的所有 Nemotron Nano 模型/量化版本。
使用时,在 ./launch-cluster.sh 参数中添加 --apply-mod mods/nemotron-nano

例如,在单节点上运行 nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4:

./launch-cluster.sh --solo --apply-mod mods/nemotron-nano \
  -e VLLM_USE_FLASHINFER_MOE_FP4=1 \
  -e VLLM_FLASHINFER_MOE_BACKEND=throughput \
  exec vllm serve nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4 \
    --max-num-seqs 8 \
    --tensor-parallel-size 1 \
    --max-model-len 262144 \
    --port 8888 --host 0.0.0.0 \
    --trust-remote-code \
    --enable-auto-tool-choice \
    --tool-call-parser qwen3_coder \
    --reasoning-parser-plugin nano_v3_reasoning_parser.py \
    --reasoning-parser nano_v3 \
    --kv-cache-dtype fp8 \
    --gpu-memory-utilization 0.7 \
    --load-format fastsafetensors 

请注意,Spark 上的 NVFP4 模型在 vLLM(任何构建)上尚未得到完全支持,因此性能不会是最优的。你很可能在加载期间看到 Flashinfer 错误。已知该模型有时会崩溃。

能够将 launch-cluster.sh 与 NVIDIA NGC 容器配合使用

新增了新的 mod,使集群启动脚本能够与 NVIDIA NGC vLLM 或任何包含 Infiniband 库和 Ray 支持的其他 vLLM 容器配合使用。

使用时,在 ./launch-cluster.sh 参数中添加 --apply-mod mods/use-ngc-vllm。它可以与其他 mod 组合使用。
例如,要使用 NGC 容器在集群中启动 Nemotron Nano,可以使用以下命令:

./launch-cluster.sh \
   -t nvcr.io/nvidia/vllm:26.01-py3 \
   --apply-mod mods/use-ngc-vllm \
   --apply-mod mods/nemotron-nano \
   -e VLLM_USE_FLASHINFER_MOE_FP4=1 \
   -e VLLM_FLASHINFER_MOE_BACKEND=throughput \
   exec vllm serve nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4 \
       --max-model-len 262144 \
       --port 8888 --host 0.0.0.0 \
       --trust-remote-code \
       --enable-auto-tool-choice \
       --tool-call-parser qwen3_coder \
       --reasoning-parser-plugin nano_v3_reasoning_parser.py \
       --reasoning-parser nano_v3 \
       --kv-cache-dtype fp8 \
       --gpu-memory-utilization 0.7 \
       --tensor-parallel-size 2 \
       --distributed-executor-backend ray

请确保你已在两个节点上拉取了该容器!

目前来看,NGC 容器在该模型上的表现似乎并不比自定义构建更好。

2026-01-29

launch-cluster.sh 的新参数

  • launch-cluster.sh 中新增了 solo 模式,用于在单节点上启动模型。只需使用 --solo 标志;如果你只有一台 Spark 且未发现其他节点,则默认使用 Solo 模式。
  • launch-cluster.sh 中新增了 -e / --env 参数,用于向容器传递环境变量。

针对 GLM-4.7-Flash-AWQ 的新 Mod

新增了 mod,防止使用 cyankiwi/GLM-4.7-Flash-AWQ-4bit(以及该模型的其他 AWQ 量化版本)时出现严重的推理速度下降。
实现细节请参见(NVIDIA 论坛上的这篇帖子)[https://forums.developer.nvidia.com/t/make-glm-4-7-flash-go-brrrrr/359111]。

首先构建标准镜像:

# 标准镜像标签默认为 vllm-node
./build-and-copy.sh -c

然后,在单节点上运行:

./launch-cluster.sh -t vllm-node --solo \
  --apply-mod mods/fix-glm-4.7-flash-AWQ \
  exec vllm serve cyankiwi/GLM-4.7-Flash-AWQ-4bit \
  --tool-call-parser glm47 \
  --reasoning-parser glm45 \
  --enable-auto-tool-choice \
  --served-model-name glm-4.7-flash \
  --max-model-len 202752 \
  --max-num-batched-tokens 4096 \
  --max-num-seqs 64 \
  --host 0.0.0.0 --port 8888 \
  --gpu-memory-utilization 0.7

在集群上运行:

./launch-cluster.sh -t vllm-node \
  --apply-mod mods/fix-glm-4.7-flash-AWQ \
  exec vllm serve cyankiwi/GLM-4.7-Flash-AWQ-4bit \
  --tool-call-parser glm47 \
  --reasoning-parser glm45 \
  --enable-auto-tool-choice \
  --served-model-name glm-4.7-flash \
  --max-model-len 202752 \
  --max-num-batched-tokens 4096 \
  --max-num-seqs 64 \
  --host 0.0.0.0 --port 8888 \
  --gpu-memory-utilization 0.7 \
  --distributed-executor-backend ray \
  --tensor-parallel-size 2

注意:即使打了补丁,vLLM 的实现仍然不是最优的。对于激活参数量这个级别的模型,其性能仍然明显偏慢。在集群中运行可以提高 prompt 处理性能,但不会提高 token 生成速度。在单节点和集群中,你都可以期待约 40 t/s 的生成速度。

实验性优化的 MXFP4 构建

新增了一个实验性构建选项,由 Christopher Owen 针对 DGX Spark 和 gpt-oss 模型进行了优化。

这目前是在 DGX Spark 上运行 GPT-OSS 的最快方式,在单台 Spark 上可达到 60 t/s。

要使用此构建,请先使用 --exp-mxfp4 标志构建容器。建议使用单独的标签,因为目前不建议将此构建用于 gpt-oss 以外的模型:

# 使用 --exp-mxfp4 时镜像标签默认为 vllm-node-mxfp4
./build-and-copy.sh --exp-mxfp4 -c

然后,在单台 Spark 上运行:

 docker run \
  --privileged \
  --gpus all \
  -it --rm \
  --network host --ipc=host \
  -v  ~/.cache/huggingface:/root/.cache/huggingface \
  vllm-node-mxfp4 \
  bash -c -i "vllm serve openai/gpt-oss-120b \
        --host 0.0.0.0 \
        --port 8888 \
        --enable-auto-tool-choice \
        --tool-call-parser openai \
        --reasoning-parser openai_gptoss \
        --gpu-memory-utilization 0.70 \
        --enable-prefix-caching \
        --load-format fastsafetensors \
        --quantization mxfp4 \
        --mxfp4-backend CUTLASS \
        --mxfp4-layers moe,qkv,o,lm_head \
        --attention-backend FLASHINFER \
        --kv-cache-dtype fp8 \
        --max-num-batched-tokens 8192"

在双 Spark 集群上:

./launch-cluster.sh -t vllm-node-mxfp4 exec vllm serve \
  openai/gpt-oss-120b \
        --host 0.0.0.0 \
        --port 8888 \
        --enable-auto-tool-choice \
        --tool-call-parser openai \
        --reasoning-parser openai_gptoss \
        --gpu-memory-utilization 0.70 \
        --enable-prefix-caching \
        --load-format fastsafetensors \
        --quantization mxfp4 \
        --mxfp4-backend CUTLASS \
        --mxfp4-layers moe,qkv,o,lm_head \
        --attention-backend FLASHINFER \
        --kv-cache-dtype fp8 \
        --max-num-batched-tokens 8192 \
        --distributed-executor-backend ray \
        --tensor-parallel-size 2

2025-12-24

  • 新增了 hf-download.sh 脚本,用于使用 uvx 从 HuggingFace 下载模型,并可选择将其复制到其他集群节点。

用法示例。以下命令会下载模型并并行分发到集群中的所有节点:

./hf-download.sh QuantTrio/GLM-4.7-AWQ -c --copy-parallel

2025-12-23

  • 新增了 mods/patches 功能,允许通过 launch-cluster.sh 中的 --apply-mod 标志应用自定义补丁,从而无需重建整个镜像即可进行特定模型的兼容性修复和实验性功能。

  • 新增了对 Salyut1/GLM-4.7-NVFP4 量化版本的支持。

运行时,请使用新的 --apply-mod 标志应用补丁,以修复因 glm4 解析器期望分离的 k 和 v scale、而该模型使用融合量化方案所导致的不兼容问题。详情参见 Huggingface 上的这个讨论

在两个节点上下载模型后(以避免启动期间过长的等待时间),使用此命令:

./launch-cluster.sh --apply-mod ./mods/fix-Salyut1-GLM-4.7-NVFP4 \
exec vllm serve Salyut1/GLM-4.7-NVFP4 \
        --attention-config.backend flashinfer \
        --tool-call-parser glm47 \
        --reasoning-parser glm45 \
        --enable-auto-tool-choice \
        -tp 2 \
        --gpu-memory-utilization 0.88 \
        --max-model-len 32000 \
        --distributed-executor-backend ray \
        --host 0.0.0.0 \
        --port 8000

2025-12-21

  • build-and-copy.sh 中新增了 --pre-tf / --pre-transformers 标志,用于早期 Transformers 5 测试。历史说明:该标志现已弃用;当前构建使用 vLLM 默认的 Transformers 依赖,该标志仅保留传统的输入/标签行为。
  • 预构建 wheel 现在支持 release 版本。与 --use-wheels release 配合使用。
  • 为了获得更好的性能,建议使用 nightly wheel 或从源码构建。

2025-12-20

  • 从源码构建时将 ccache 限制为 50G,以减少构建缓存大小。
  • build-and-copy.sh 中新增了 --pre-flashinfer 标志,用于使用 FlashInfer 的预发布版本。
  • build-and-copy.sh 中新增了 --use-wheels [mode] 标志。
    • 允许使用预构建的 vLLM wheel 而不是从源码编译来构建容器。
    • 减少了构建时间和容器体积。
    • mode 是可选的,默认为 nightly
    • 支持的模式:nightly(release wheel 目前在 CUDA 13 下有问题)。更新:release 现在也可以用了。

      2025-12-19

更新了 build-and-copy.sh 以支持复制到多个主机(感谢 @ericlewis 的贡献)。

  • 新增了 -c, --copy-to(接受以空格或逗号分隔的主机列表),并保留 --copy-to-host 作为向后兼容的别名。
  • 新增了 --copy-parallel,可并行复制到所有主机。
  • 新增了自动发现支持:如果未向 --copy-to 提供主机,脚本会自动检测其他集群节点。
  • 破坏性变更:短参数 -h 现在用于显示帮助。复制请使用 -c

2025-12-18

  • 新增了 launch-cluster.sh 便捷脚本,用于基本的集群管理 - 详情见下文。
  • build-and-copy.sh 中新增了 -j / --build-jobs 参数,用于控制构建并行度。
  • 新增了 --nccl-debug 选项,用于指定 NCCL 调试级别。默认为 none,以减少冗余输出。

2025-12-15

更新了 build-and-copy.sh 标志:

  • --triton-sha 重命名为 --triton-ref,使其除了 commit SHA 之外还支持分支和标签。
  • 新增了 --vllm-ref <ref>:指定 vLLM 的 commit SHA、分支或标签(默认为 main)。

2025-12-14

转换为多阶段 Docker 构建,缩短了构建时间并减小了最终镜像体积。builder 阶段现在与运行时阶段分离,最终镜像中不再包含不必要的构建工具。

build-and-copy.sh 中新增了耗时统计,用于跟踪 Docker 构建和镜像复制的时长,并在最后显示摘要。

Triton 现在从源码构建,连同其配套的 triton_kernels 包。Triton 版本默认设置为 v3.5.1,但可以使用 --triton-sha 参数更改。

build-and-copy.sh 中新增了标志:

  • --triton-sha <sha>:指定 Triton 的 commit SHA(目前默认为 v3.5.1)
  • --no-build:跳过构建,只复制现有镜像(需要 --copy-to

2025-12-11 更新

MiniMax-M2 的 PR 已合并到 main,因此从 Dockerfile 中移除了临时补丁。

2025-12-11

应用了一个补丁,修复了此提交之后某些量化版本中 MiniMax-M2 损坏的问题,直到此 PR 被批准。
详情参见此 issue

2025-12-05

为了方便起见新增了 build-and-copy.sh

2025-11-26

初始版本。
更新了 RoCE 配置示例,在列表中包含两个接口。
应用了补丁以在集群配置中启用 FastSafeTensors(实验性),并添加了关于 fastsafetensors 使用的文档。

1. 构建 Docker 镜像

手动构建

由于 Dockerfile 的复杂性,不再支持手动构建容器。请使用提供的构建脚本。

使用构建脚本

build-and-copy.sh 脚本会准备 runner 镜像,并可选择将其复制到一个或多个节点。默认情况下,它会拉取 eugr/spark-vllm:latest 并在本地打标签。使用 --use-wheels 可以只从下载的或本地的预编译 wheel 构建 runner。只有提供了显式的源码构建标志(例如 --rebuild-vllm--vllm-ref--apply-vllm-pr--rebuild-flashinfer--flashinfer-ref--apply-flashinfer-pr)时才会进行源码编译。

基本用法(准备本地镜像):

./build-and-copy.sh

使用自定义本地标签准备:

./build-and-copy.sh -t my-vllm-node

从 wheel 构建 runner 镜像:

./build-and-copy.sh --use-wheels

准备并复制到 Spark 节点:

使用与当前登录用户相同的用户名(单个主机):

./build-and-copy.sh --copy-to 192.168.177.12

复制到多个主机(标志后以空格或逗号分隔):

./build-and-copy.sh --copy-to 192.168.177.12 192.168.177.13

并行复制到多个主机:

./build-and-copy.sh --copy-to 192.168.177.12 192.168.177.13 --copy-parallel

使用自动发现进行准备和复制:

如果省略 --copy-to 后面的主机列表,脚本将尝试自动发现集群中的其他节点(不包括当前节点)并将镜像复制到它们。

./build-and-copy.sh --copy-to

使用不同的用户名:

./build-and-copy.sh --copy-to 192.168.177.12 --user your_username

强制从源码重新构建 vLLM:

./build-and-copy.sh --rebuild-vllm

强制从源码重新构建 FlashInfer(跳过预构建 wheel 下载):

./build-and-copy.sh --rebuild-flashinfer

组合示例(重新构建 vLLM 并复制到另一个节点):

./build-and-copy.sh --rebuild-vllm -c 192.168.177.12

针对特定 GPU 架构构建:

./build-and-copy.sh --gpu-arch 12.0f

使用自定义 PyTorch 版本构建 vLLM fork:

./build-and-copy.sh \
  --vllm-repo https://github.com/local-inference-lab/vllm.git \
  --vllm-ref dev/fathomless-firmament \
  --torch-version 2.12.0 \
  --torchvision-version 0.27.0 \
  --torchaudio-version none

对于持续维护的实验性 B12X 组合,等效的快捷方式是:

./build-and-copy.sh --exp-b12x

如果没有本地构建标志,这将拉取 eugr/spark-vllm-b12x:latest,并且除非提供了 -t,否则将其标记为 vllm-node-b12x。要从 local-inference-lab/vllm@dev/gilded-gnosis 和 B12X 仓库的 master 分支构建该维护组合,请运行:

./build-and-copy.sh --exp-b12x --rebuild-vllm

它可以与 --apply-vllm-pr <pr-num> 组合使用,以构建自定义的 vLLM 补丁。
该预设会在 vLLM 的 CUDA 13 CMake 配置中保留所选的 Blackwell 子架构。
这可以防止 10.3a 和默认的 12.1a 等目标被降级为通用的 sm_100sm_120,后者无法编译 B12X 分支的 NVFP4 缓存写入器。显式的 --gpu-arch 12.0a--gpu-arch 12.0f 选择仍然受支持,并且会原样转发。
FlashInfer 架构验证适用于所有标准 Dockerfile 构建,包括 B12X:当不存在匹配的架构标记时,替代目标会重新构建 FlashInfer,并且缓存的 wheel 会记录其架构,这样后续的构建就不会悄无声息地复用针对不同目标的 wheel。

自定义 vLLM 仓库会全新克隆,而不是使用共享的上游检出缓存。指定自定义仓库会强制进行 vLLM 源码构建。对于自定义仓库和 ref,默认会跳过上游预设 PR。

Wheel 配置文件会自动选择:

.wheel-cache/
├── flashinfer/
│   ├── regular/   # 常规和 B12X 构建共享
│   └── custom/    # 自定义 ref/PR 或非默认 GPU 目标
└── vllm/
    ├── regular/
    ├── b12x/
    └── custom/    # 自定义仓库/ref/PR、Torch 系列或 GPU 目标

只有常规 vLLM wheel 会从已发布的 wheel release 下载。
因此 --exp-b12x--use-wheels 不兼容:使用不带参数的
--exp-b12x 获取已发布的镜像,或添加 --rebuild-vllm 进行源码构建。

对于从 local-inference-lab/vllm 选择的任何分支、标签或 commit,runner 都会全新克隆 https://github.com/lukealonso/b12x.gitmaster ref,并自动构建和安装其 b12x 发行版。每次构建的缓存 key 可以防止 Docker 复用陈旧的源码检出。安装时使用 --no-deps 以保留 vLLM 选择的依赖版本(包括其 CUTLASS DSL 版本锁定),并将确切的源码 commit 记录在 /workspace/b12x-source-commit。B12X 需要 PyTorch 2.12 或更高版本。

复制现有镜像而不重新构建:

./build-and-copy.sh --no-build --copy-to 192.168.177.12

可用选项:

标志 描述
-t, --tag <tag> 本地镜像标签(默认:vllm-node;使用 --tf5 时自动设置为 vllm-node-tf5,使用 --exp-mxfp4 时为 vllm-node-mxfp4,使用 --exp-b12x 时为 vllm-node-b12x
--use-wheels 只从下载的或本地的预编译 wheel 构建 runner 镜像;绝不隐式编译缺失的 wheel。与 --exp-b12x 不兼容。
--gpu-arch <arch> wheel/源码构建的目标 GPU 架构。除非本地缓存已标记为该架构,否则非默认目标会重新构建 FlashInfer。默认值 12.1a 仍使用预构建镜像,除非设置了其他强制构建的标志。
--rebuild-flashinfer 跳过预构建 wheel 下载;强制进行全新的本地 FlashInfer 构建
--rebuild-vllm 强制从源码重新构建 vLLM
--force-flashinfer-download 强制下载 FlashInfer wheel,跳过缓存 wheel 检查
--force-vllm-download 强制下载 vLLM wheel,跳过缓存 wheel 检查
--force-download 强制下载所有预构建 wheel,跳过缓存 wheel 检查
--vllm-repo <url> vLLM Git 仓库。默认为 https://github.com/vllm-project/vllm.git;自定义仓库会绕过共享检出缓存并强制进行源码构建。
--vllm-ref <ref> vLLM 的 commit SHA、分支或标签(默认:main
--torch-version <version> 在源码构建和 runner 阶段安装的 PyTorch 版本(默认:2.11.0
--torchvision-version <version> 可选的 torchvision 版本;省略时由解析器选择兼容版本
--torchaudio-version <version> 可选的 torchaudio 版本;省略时由解析器选择兼容版本。使用 none 可省略 torchaudio。
--flashinfer-ref <ref> FlashInfer 的 commit SHA、分支或标签(默认:main
--apply-vllm-pr <pr-num> 在构建期间应用 vLLM PR 补丁。可以指定多次。
--apply-preset-vllm-prs 即使 --vllm-repo--vllm-ref--apply-vllm-pr 本会抑制预设 PR,也仍然应用预设的 vLLM PR
--apply-flashinfer-pr <pr-num> 在构建期间应用 FlashInfer PR 补丁。可以指定多次。
--tf5 已弃用的兼容性标志;除非设置了其他强制构建的标志,否则将预构建镜像拉取/标记为 vllm-node-tf5。别名:--pre-tf, --pre-transformers
--exp-mxfp4 使用实验性原生 MXFP4 支持进行构建。别名:--experimental-mxfp4
--exp-b12x 选择 B12X 配置文件。除非请求本地 wheel/镜像构建,否则拉取 eugr/spark-vllm-b12x:latest;本地标签默认为 vllm-node-b12x。别名:--experimental-b12x
-c, --copy-to <hosts> 准备完成后要复制镜像的主机(以空格或逗号分隔)。具有相同镜像 ID 的主机会被跳过。
--copy-to-host --copy-to 的别名(向后兼容)。
--copy-parallel 并行复制到所有指定主机。
-j, --build-jobs <jobs> 并行构建任务数(默认:16)
-u, --user <user> SSH 连接的用户名(默认:当前用户)
--full-log 启用完整的 Docker 构建输出(--progress=plain
--no-build 完全跳过镜像准备,只复制现有的本地镜像标签(需要 --copy-to
--network <name> 构建期间使用的 Docker 网络(例如 host)。
--cleanup 从每个 .wheel-cache 配置文件中删除缓存的 wheel 文件和溯源标记;这本身不会强制本地构建。
--config <file> .env 配置文件路径(默认:脚本目录中的 .env
--setup 强制自动发现并将配置保存到 .env(即使 .env 已存在)
-h, --help 显示帮助信息

重要提示:手动复制到其他节点时,请使用分配给 ConnectX 7 接口的 IP(enp1s0f*),而不是 10G/无线接口。使用不带地址的 -c 时,自动发现会自动选择正确的接口 — 在 mesh 模式下,它会使用直连 IB 的接口(enp1s0f0np0enp1s0f1np1)以获得最大传输速度。

将容器复制到其他 Spark 节点(手动方式)

或者,你也可以使用以下命令通过 ConnectX 7 接口手动将镜像直接复制到第二台 Spark 节点:

docker save vllm-node | ssh your_username@another_spark_hostname_or_ip "docker load"

重要提示:请确保使用分配给 Spark ConnectX 7 接口的 IP(enp1s0f1np1),而不是 10G 接口(enP7s7)!


2. 启动集群(推荐)

launch-cluster.sh 脚本简化了启动集群节点的过程。它会自动处理 Docker 参数、网络接口检测和节点配置。

基本用法

启动空闲集群容器(自动检测一切):

./launch-cluster.sh start

这将:

  1. 自动检测活动的 InfiniBand 和以太网接口。
  2. 自动检测节点 IP。
  3. 验证所选 Docker 镜像在头节点和每个 worker 上具有相同的内容寻址镜像 ID。
  4. 在头节点和 worker 节点上启动空闲容器。
  5. 启动 Ray 集群,除非选择了 solo 模式或 --no-ray

假设和限制:

  • 它假设你已在所有节点上配置好免密码 SSH 访问。如果尚未配置,请按照 NVIDIA 的 Connect Two Sparks Playbook 操作。建议在配置中设置静态 IP,而不是每次都自动分配,但该脚本应该也能与自动分配的地址配合使用。
  • 默认情况下,它假设容器镜像名称为 vllm-node。如果不同,你需要用 -t <name> 参数指定。
  • 在启动多节点集群之前,它会比较头节点和每个活动 worker 上所选镜像的 docker image inspect ID。如果镜像缺失或任何 ID 不同,启动将中止。
  • 如果两个 ConnectX 物理端口都在使用,且都有 IP 地址,它将使用最先找到的接口。使用 --eth-if 进行覆盖。
  • 它会忽略与物理接口的第二个"克隆"关联的 IP。例如,Spark 最外侧的端口有两个逻辑以太网接口:enp1s0f1np1enP2p1s0f1np1。只会使用 enp1s0f1np1。如需覆盖,请使用 --eth-if 参数。
  • 它假设所有节点上相同的物理接口命名相同(也就是说,enp1s0f1np1 在所有节点上指的是同一个物理端口)。如果不是这样,你将不得不手动启动集群节点或修改脚本。
  • 它默认清除 Docker 镜像的 entrypoint,这样定义了 entrypoint 的镜像(例如 vllm-openai)在执行命令之前仍然可以作为空闲集群容器启动。使用 --keep-entrypoint 可保留镜像的 entrypoint。
  • 在 solo 模式下,可以使用 -p / --publish 以 Docker 格式发布端口,例如 -p 8000:8000。使用端口发布时,启动器不使用 host 网络。集群模式不支持端口发布。
  • 默认情况下,它会在每个容器中设置 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,以减少 DGX Spark 上的分配器碎片化。需要时使用 -e PYTORCH_CUDA_ALLOC_CONF=<value> 覆盖。
  • 默认挂载 ~/.cache/huggingface~/.cache/vllm~/.cache/flashinfer~/.triton~/.tilelang。使用 --no-cache-dirs 可跳过 vLLM/FlashInfer/Triton/TileLang 缓存挂载。使用可重复的 Docker 风格 -v / --volume 选项添加其他挂载,例如 -v "$HOME/my-data:/data"

以 daemon 模式启动(后台):

./launch-cluster.sh -d start

停止容器:

./launch-cluster.sh stop

检查状态:

./launch-cluster.sh status

在运行中的容器内执行命令:

./launch-cluster.sh exec vllm serve ...

自动检测

脚本会尝试自动检测:

  • 以太网接口(ETH_IF): 由活动的 CX7 接口数量决定:
    • 2 个活动(标准):具有 IP 地址的 enp* 接口(不带大写 P)。
    • 4 个活动(mesh 拓扑):enP7s7(首选)或 wlP9s9(无线,会显示警告)— 在这种配置下,集群协调接口与 CX7 端口是分开的。
  • InfiniBand 接口(IB_IF): 所有活动的 RoCE 设备。在 mesh 模式下,这始终是 rocep1s0f0,roceP2p1s0f0,rocep1s0f1,roceP2p1s0f1
  • 集群对等节点: 通过扫描 ETH_IF 子网发现具有 SSH 访问权限具有 GB10 GPU 的主机(nvidia-smi --query-gpu=name 必须返回 NVIDIA GB10)。
  • 复制主机(COPY_HOSTS): 在标准模式下,与集群对等节点相同。在 mesh 模式下,在 enp1s0f0np0enp1s0f1np1 子网上单独扫描,使镜像/模型传输使用直连 InfiniBand 路径。

手动覆盖

如有需要,你可以覆盖自动检测的值:

./launch-cluster.sh --nodes "10.0.0.1,10.0.0.2" --eth-if enp1s0f1np1 --ib-if rocep1s0f1 -e MY_ENV=123
标志 描述
-n, --nodes 以逗号分隔的节点 IP 列表(头节点在前)。
-t Docker 镜像名称(默认:vllm-node)。
--name 容器名称(默认:vllm_node)。
--eth-if 以太网接口名称。
--ib-if InfiniBand 接口名称。
-e, --env 传递给容器的环境变量(例如 -e VAR=val)。可多次使用。
-j 构建环境变量对应的并行任务数(可选)。
--apply-mod 从指定目录应用 mods/补丁。可多次使用以应用多个 mod。
--nccl-debug NCCL 调试级别(例如 INFO、WARN)。如果提供了标志但省略了值,则默认为 INFO。
--check-config 检查配置和自动检测,但不启动。
--solo Solo 模式:跳过自动检测,只在当前节点启动,不启动 Ray 集群
-p, --publish 以 Docker 格式发布容器端口,例如 -p 8000:8000。仅限 solo 模式;替代 host 网络。可多次使用。
-v, --volume 以 Docker 格式映射卷,例如 -v /local/path:/container/path。应用于每个启动的节点,可多次使用。
--ray 为多节点 vLLM 启用 Ray,并在缺少时添加 --distributed-executor-backend ray
--no-ray 默认的多节点 no-Ray 模式;为兼容性而接受。
--master-port / --head-port 集群协调端口:Ray 头节点端口或 PyTorch 分布式 master 端口(默认:29501)。
--no-cache-dirs 不挂载默认缓存目录(~/.cache/vllm、~/.cache/flashinfer、~/.triton、~/.tilelang)。
--keep-entrypoint 保留 Docker 镜像的 entrypoint,而不是在启动空闲集群容器之前清除它。
--earlyoom earlyoom 作为容器前台进程运行,而不是 sleep infinity
--earlyoom-args 传递给 earlyoom 的参数(默认:-M 524288,102400 -s 100 -r 60)。隐含 --earlyoom
--launch-script 要在容器中执行的 bash 脚本路径(来自 examples/ 目录或绝对路径)。如果指定了启动脚本,则应省略 action。
-d 以 daemon 模式运行(分离)。
--non-privileged 以非特权模式运行(移除 --privileged--ipc=host)。
--mem-limit-gb 内存限制,单位为 GB(默认:110,仅限与 --non-privileged 配合使用)。
--mem-swap-limit-gb 内存+swap 限制,单位为 GB(默认:mem-limit + 10,仅限与 --non-privileged 配合使用)。
--pids-limit 进程数限制(默认:4096,仅限与 --non-privileged 配合使用)。
--shm-size-gb 共享内存大小,单位为 GB(默认:64,仅限与 --non-privileged 配合使用)。
--config <file> .env 配置文件路径(默认:脚本目录中的 .env)。
--setup 强制自动发现并将配置保存到 .env(即使 .env 已存在)。
start \| stop \| status \| exec 要执行的操作。使用 start 启动空闲容器,或使用 exec 运行命令。与 --launch-script 不兼容。
command 要在容器内执行的命令(仅限 exec 操作)。

Early OOM 监控器

--earlyoom 标志会以 earlyoom 作为 PID 1 启动空闲容器,而不是 sleep infinity,这样在通过 docker exec 启动 Ray 和 vLLM 的同时监控内存。这是可选的;没有 --earlyoom 时,容器仍然使用普通的空闲命令。

默认策略:

earlyoom -M 524288,102400 -s 100 -r 60

这些参数的含义:

  • -M 524288,102400:当可用内存低于 524288 KiB(512 MiB)时发送 SIGTERM,低于 102400 KiB(100 MiB)时发送 SIGKILL。
  • -s 100:不等待 swap 写满就采取行动。Earlyoom 通常要求内存和 swap 都低于各自的阈值;-s 100 使 swap 阈值实际上始终满足,因此仅主机内存压力就足以触发。如果你想要 TERM 和 KILL 的无 swap 阈值,请使用成对的值,例如 -s 70,50
  • -r 60:每 60 秒打印一次内存报告。使用 -r 0 禁用定期报告。

使用 --earlyoom-args 在每次启动时调整策略:

./launch-cluster.sh --earlyoom \
  --earlyoom-args "-M 1048576,262144 -s 70,50 -r 30" \
  exec vllm serve ...

同样的选项会透传到配方启动:

./run-recipe.sh minimax-m2-awq --solo \
  --earlyoom --earlyoom-args "-M 786432,196608 -s 100 -r 120"

你也可以通过环境变量设置默认参数:

VLLM_SPARK_EARLYOOM_ARGS="-M 786432,196608 -s 100 -r 120" \
  ./launch-cluster.sh --earlyoom exec vllm serve ...

其他有用的上游选项包括:--prefer REGEX--avoid REGEX 用于影响受害者选择,--dryrun 用于记录将要杀死什么而不实际杀死,以及 -g 用于杀死选定的进程组而不仅是选定的进程。请确保自定义参数值对 shell 安全,因为它们会作为命令参数通过启动器传递。

--earlyoom--keep-entrypoint 不兼容:启动器必须清除镜像的 entrypoint,earlyoom 才能成为容器的前台进程。

非特权模式

--non-privileged 标志允许在不使用完全特权访问的情况下运行容器,同时保持 RDMA/InfiniBand 功能:

./launch-cluster.sh --non-privileged exec vllm serve ...

指定 --non-privileged 时:

  • --cap-add=IPC_LOCK 替代 --privileged
  • --shm-size=64g 替代 --ipc=host(可通过 --shm-size-gb 配置)
  • 通过 --device=/dev/infiniband 暴露 RDMA 设备
  • 应用资源限制:内存(110GB)、内存+swap(120GB)、pids(4096)

所有启动模式都会将 Docker 的打开文件数 ulimit 设置为 1048576,以避免 Ray worker 并行打开高度分片的模型时出现加载器失败。如果你的主机需要不同的值,请使用 VLLM_SPARK_NOFILE_LIMIT 覆盖。

这些资源限制可以自定义:

./launch-cluster.sh --non-privileged \
  --mem-limit-gb 120 \
  --mem-swap-limit-gb 130 \
  --shm-size-gb 64 \
  exec vllm serve ...

3. 运行容器(手动方式)

如果你想完全控制 Docker 参数,手动 docker run 可能会很有用,但即使对于单台 Spark 也不推荐。对于多节点 Ray 或 no-Ray 启动,请使用 launch-cluster.sh;旧的独立 run-cluster-node.sh 流程已被移除,其逻辑现已集成到启动器中。

docker run -it --rm \
  --gpus all \
  --net=host \
  --ipc=host \
  --privileged \
  --ulimit nofile=1048576:1048576 \
  --name vllm_node \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  vllm-node bash

在容器内,直接运行 vllm serve ... 即可进行 solo 推理。

重要提示:对于集群命令,请使用与 ConnectX 7 接口关联的 IP 地址,而不是 10G 或无线接口。

标志说明:

  • --net=host集群命令必需。 Ray 和 NCCL 需要完全访问主机网络接口。
  • --ipc=host推荐。 允许 PyTorch/NCCL 访问共享内存。作为替代方案,你可以通过 --shm-size=16g 设置。
  • --privileged对 InfiniBand 推荐。 授予容器对 RDMA 设备(/dev/infiniband)的访问权限。作为替代方案,你可以传入 --ulimit memlock=-1 --ulimit stack=67108864 --device=/dev/infiniband
  • --ulimit nofile=1048576:1048576对大型分片模型推荐。 防止并行加载 safetensors 元数据时出现 Too many open files 错误。

4. 配置详情

集群配置(.env 文件)

这些脚本共享一个 .env 文件(默认:仓库目录中的 .env)用于持久化集群配置。它由自动发现自动创建 — 首次使用时运行 --discover(通过 run-recipe.sh)或 --setup(通过 launch-cluster.sh / build-and-copy.sh)。

支持的变量:

变量 描述
CLUSTER_NODES 用于 Ray/vLLM 集群的以逗号分隔的节点 IP(头节点在前)。
COPY_HOSTS 用于镜像和模型分发的以逗号分隔的节点 IP。在 mesh 模式下,这些是直连 IB 接口上的 IP,可能与 CLUSTER_NODES 不同。
LOCAL_IP 本地节点的 IP 地址。
ETH_IF 用于集群协调的以太网接口(例如 enp1s0f1np1enP7s7)。
IB_IF 以逗号分隔的 RoCE/IB 设备名称(例如 rocep1s0f0,roceP2p1s0f0,rocep1s0f1,roceP2p1s0f1)。
CONTAINER_* 任何以 CONTAINER_ 为前缀的变量(CONTAINER_NAME 除外)都会以 -e VAR=VALUE 的形式传递给容器。示例:CONTAINER_NCCL_DEBUG=INFO-e NCCL_DEBUG=INFO

Mesh 模式 NCCL 变量(检测到 mesh 拓扑时自动写入):

CONTAINER_NCCL_NET_PLUGIN=none
CONTAINER_NCCL_IB_SUBNET_AWARE_ROUTING=1
CONTAINER_NCCL_IB_MERGE_NICS=0

标准 2 节点集群的 .env 示例:

CLUSTER_NODES=192.168.177.11,192.168.177.12
COPY_HOSTS=192.168.177.12
LOCAL_IP=192.168.177.11
ETH_IF=enp1s0f1np1
IB_IF=rocep1s0f1,roceP2p1s0f1

要使用自定义配置文件路径,请向任何脚本传入 --config /path/to/file.env

自动发现工作流程

首次运行时,如果不存在 .env,脚本会自动触发自动发现。你也可以显式运行它:

# 通过 run-recipe.sh
./run-recipe.sh --discover

# 通过 launch-cluster.sh 或 build-and-copy.sh(即使 .env 存在也强制重新运行)
./launch-cluster.sh --setup exec vllm serve ...
./build-and-copy.sh --setup -c

自动发现:

  1. 检测活动的 CX7 接口,并确定 mesh 还是标准拓扑。
  2. 扫描网络寻找 SSH 可达的 GB10 对等节点。
  3. 在 mesh 模式下,在直连 IB 接口上单独发现 COPY_HOSTS
  4. CLUSTER_NODESCOPY_HOSTS 都要求逐节点确认。
  5. 将结果保存到 .env

环境持久化

启动器在每个容器启动时通过 Docker -e 标志注入节点特定的环境变量。如果你需要打开第二个终端进入运行中的容器进行调试,请运行:

docker exec -it vllm_node bash

新 shell 会继承容器环境,包括 NCCL、Ray 和 vLLM 网络设置。

5. Mods 与补丁

vLLM Docker 配置支持应用自定义 mods 和补丁,以解决特定的模型兼容性问题或应用实验性功能。该功能主要通过集群启动脚本中的 --apply-mod 选项管理,run-recipe.sh 可以将额外的 --apply-mod 标志透传给 launch-cluster.sh

可用的 Mods

仓库的 mods/ 目录中包含几个预配置的 mod:

  • fix-Salyut1-GLM-4.7-NVFP4/:修复 Salyut1/GLM-4.7-NVFP4 融合 QKV 量化的 GLM4MoE 解析器。
  • fix-glm-4.7-flash-AWQ/:应用 GLM-4.7-Flash-AWQ 兼容性和性能修复。
  • fix-qwen3.5-chat-template/fix-qwen3.6-chat-template/:安装 Qwen3.5 和 Qwen3.6 配方使用的修复版 chat template。
  • fix-qwen3.5-autoround/fix-qwen3-next-autoround/fix-qwen35-tp4-marlin/:特定模型的 Qwen AutoRound 和 Marlin 兼容性修复。
  • fix-qwen3-coder-next/:Qwen3-Coder-Next 运行时和性能修复。
  • dspark-instanttensor/:在 InstantTensor 或 safetensors I/O 之前过滤嵌入的 mtp.* DSpark draft 权重,避免第二次完整检查点加载。
  • gpu-mem-util-gb/:添加实验性的 --gpu-memory-utilization-gb 支持。
  • kv-cache-prealloc-cleanup/:应用针对特定模型的手动 KV 缓存启动调整:当环境变量禁用时跳过 CUDA graph profiling,并允许 --gpu-memory-utilization-gb--kv-cache-memory-bytes 共存。
  • uma-fix/:在 WSL 下使用 CUDA/NVML 内存统计,并在那里跳过主机内存 UMA 统计。
  • drop-caches/:定期清除在接近内存限制运行的大型模型的文件系统缓存。
  • diffusiongemma/:添加 DiffusionGemma 支持、动态因果注意力兼容性,以及 DiffusionGemma 配方使用的 Gemma4 推理/内容通道修复。
  • nemotron-nano/nemotron-super/:Nemotron 推理解析器和模型支持辅助工具。
  • inkling-sm12-paged-kv/:将 Inkling 的 SM12 paged-KV 相对注意力路由到内置的 FA4 实现,同时不影响其他模型和 GPU 架构。
  • instanttensor-hybrid-draft-loader/:对目标模型保留 InstantTensor,同时对符合条件的投机 draft 权重(包括嵌入的 MTP draft)使用懒加载 safetensors。
  • exp-b12x/:针对包含所需上游 vLLM 支持的构建的实验性 FlashInfer b12x 支持。
  • use-official-vllm/:在官方 vLLM 容器(基于 Ubuntu/Debian)中安装 gitearlyoom、InstantTensor 和 SciPy,使其他 mod 可以依赖 git apply,启动器可以使用 --earlyoom,vLLM 可以使用 --load-format instanttensor 和基于 SciPy 的功能。Python 安装会保留镜像现有的 Torch 构建。该 mod 还会将 pip 安装的 NCCL 库重定向到系统 libnccl2 库,以避免 DGX Spark 多节点 NCCL 挂起。使用官方 vLLM 镜像(例如 vllm-openai)时,请首先应用此 mod。

每个 mod 目录通常包含:

  • 用于代码修改的补丁文件(.patch)和/或其他资产。
  • 用于应用补丁的 run.sh 脚本。

补丁也可以表示为具有相同结构的 .zip 文件。

使用 Mods

要在启动集群时应用 mod,请使用 --apply-mod 标志:

./launch-cluster.sh --apply-mod ./mods/fix-Salyut1-GLM-4.7-NVFP4

你可以通过指定额外的 --apply-mod 标志来应用多个 mod:

./launch-cluster.sh --apply-mod ./mods/fix-Salyut1-GLM-4.7-NVFP4 --apply-mod ./mods/other-mod

使用配方时,会先应用配方中列出的 mod,然后再应用命令行提供的 mod:

./run-recipe.sh glm-4.7-flash-awq --solo --apply-mod ./mods/other-mod

创建自定义 Mods

要创建自己的 mod:

  1. mods/ 文件夹中创建一个新目录
  2. 根据需要添加补丁文件(.patch)或其他资产(可选)。
  3. 创建一个用于应用补丁的 run.sh 脚本。它不应接受任何参数。该脚本是必需的。
  4. 使用 --apply-mod path/to/your/mod 标志引用你的 mod

Mods 可用于:

  • 应用特定的模型兼容性修复
  • 测试实验性功能
  • 针对特定工作负载自定义 vLLM 行为
  • 无需重建整个镜像即可快速迭代开发

6. 启动脚本

启动脚本提供了一种定义可复用模型配置的简单方式。你不必传递冗长的命令行,而是创建一个 bash 脚本,它会被复制到容器中并直接执行。

基本用法

# 按名称使用启动脚本(在 examples/ 目录中查找)
./launch-cluster.sh --launch-script example-vllm-minimax

# 与显式节点一起使用
./launch-cluster.sh -n 192.168.1.1,192.168.1.2 --launch-script vllm-openai-gpt-oss-120b.sh

# 与需要补丁的模型的 mod 组合使用
./launch-cluster.sh --launch-script vllm-glm-4.7-nvfp4.sh --apply-mod mods/fix-Salyut1-GLM-4.7-NVFP4

脚本格式

启动脚本是在容器内直接运行的简单 bash 文件:

#!/bin/bash
# PROFILE: OpenAI GPT-OSS 120B
# DESCRIPTION: vLLM serving openai/gpt-oss-120b with FlashInfer MOE optimization

# 根据需要设置环境变量
export VLLM_USE_FLASHINFER_MOE_MXFP4_MXFP8=1

# 运行你的命令
vllm serve openai/gpt-oss-120b \
    --host 0.0.0.0 \
    --port 8000 \
    --tensor-parallel-size 2 \
    --distributed-executor-backend ray \
    --enable-auto-tool-choice

可用的启动脚本

examples/ 目录包含可直接使用的启动脚本:

  • example-vllm-minimax.sh - MiniMax-M2-AWQ 集群启动示例
  • vllm-openai-gpt-oss-120b.sh - 带 FlashInfer MOE 的 OpenAI GPT-OSS 120B
  • vllm-glm-4.7-nvfp4.sh - GLM-4.7-NVFP4(需要 glm4_moe 补丁 mod)

详细文档和更多示例请参见 examples/README.md

7. 使用集群模式进行推理

首选路径是让 launch-cluster.sh 启动容器并一步运行命令:

./launch-cluster.sh exec vllm serve RedHatAI/Qwen3-VL-235B-A22B-Instruct-NVFP4 \
  --port 8888 --host 0.0.0.0 \
  --gpu-memory-utilization 0.7 \
  -tp 2 \
  --distributed-executor-backend ray \
  --max-model-len 32768

对于 no-Ray 模式,在 exec 之前添加 --no-ray 并省略 Ray 后端标志。启动器会先启动 worker 命令,然后在头节点上运行 rank 0 命令:

./launch-cluster.sh --no-ray exec vllm serve RedHatAI/Qwen3-VL-235B-A22B-Instruct-NVFP4 \
  --port 8888 --host 0.0.0.0 \
  --gpu-memory-utilization 0.7 \
  -tp 2 \
  --max-model-len 32768

当存在并行标志时,启动器会自动裁剪活动节点列表,或者在需要的节点超过已配置数量时在启动之前报错。

8. 模型加载

此构建包含对 fastsafetensors 和 InstantTensor 加载的支持。

fastsafetensors 显著提升了加载速度,尤其是在目前 MMAP 性能较差的 DGX Spark 上。它使用更高效的多线程加载,同时避免使用 mmap。

要使用它,请在运行 vLLM 时包含 --load-format fastsafetensors

HF_HUB_OFFLINE=1 vllm serve openai/gpt-oss-120b --port 8888 --host 0.0.0.0 --trust_remote_code --swap-space 16 --gpu-memory-utilization 0.7 -tp 2 --distributed-executor-backend ray --load-format fastsafetensors

InstantTensor 可通过 --load-format instanttensor 使用。多个大模型配方使用它来降低加载时的内存压力。

9. 基准测试

我推荐使用 llama-benchy - 一个新的基准测试工具,可以以与 llama.cpp 套件的 llama-bench 相同的格式输出结果。

10. 下载模型

hf-download.sh 脚本提供了一种便捷的方式从 HuggingFace 下载模型并将其分发到集群节点。它通过 uvx 使用 Huggingface CLI 进行快速下载,并使用 rsync 在集群中分发。

前置条件

  • 必须已安装 uvx(如果缺失,脚本会提示你安装)。
  • 对其他节点的免密码 SSH 访问(如果需要复制)。

用法

下载模型(仅本地):

./hf-download.sh QuantTrio/MiniMax-M2-AWQ

下载并复制到特定节点:

./hf-download.sh -c 192.168.177.12,192.168.177.13 QuantTrio/MiniMax-M2-AWQ

使用自动发现下载并复制:

./hf-download.sh -c QuantTrio/MiniMax-M2-AWQ

并行下载并复制:

./hf-download.sh -c --copy-parallel QuantTrio/MiniMax-M2-AWQ

使用 .env 中的节点(遵循 COPY_HOSTS):

./hf-download.sh -c QuantTrio/MiniMax-M2-AWQ

当给出 -c 但没有显式主机时,脚本会先检查 .env 中的 COPY_HOSTS,然后回退到自动发现。在 mesh 模式下,这意味着传输会自动走直连 IB 接口。

使用自定义配置文件:

./hf-download.sh --config /path/to/cluster.env -c QuantTrio/MiniMax-M2-AWQ

可用选项:

标志 描述
<model-name> HuggingFace 模型 ID(例如 QuantTrio/MiniMax-M2-AWQ)。必需。
-c, --copy-to <hosts> 下载后要复制模型的主机(以空格或逗号分隔)。省略主机则使用 .env 中的 COPY_HOSTS 或自动发现。
--copy-to-host --copy-to 的别名(向后兼容)。
--copy-parallel 并行复制到所有主机,而不是串行。
-u, --user <user> 远程复制的 SSH 用户名(默认:当前用户)。
--config <file> .env 配置文件路径(默认:脚本目录中的 .env)。
-h, --help 显示帮助信息。

硬件架构

注意: 本项目面向 12.1a 架构(NVIDIA GB10 / DGX Spark)。如果你使用不同的硬件,可以在 ./build-and-copy.sh 中使用 --gpu-arch 标志。

此处评论已关闭