Skip to content

[Misc][DSv4] Official Spark GB10 container on vLLM v0.28.0 - #8

Draft
asterayx wants to merge 26 commits into
v0.28.0from
cursor/spark-v0280-dsv4-df88
Draft

asterayx wants to merge 26 commits into
v0.28.0from
cursor/spark-v0280-dsv4-df88

Conversation

@asterayx

@asterayx asterayx commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Purpose

Official DGX Spark / GB10 container line for DeepSeek-V4-Flash, rooted at official vLLM v0.28.0 (2cf0a6915), plus only the Spark/SM12x runtime patches that made dual-node serve green.

This is a replacement line, not a delta on today’s asterayx/vllm main. Base is the v0.28.0 branch (the official tag).

Latest: Vision-Exp mixed-warmup _out (285a71df4)

Worker died after SM12x: insert 4 extra KV slots for prefill pad 2 -> 6:

AttributeError: '_OpNamespace' '_C' object has no attribute 'fused_deepseek_v4_qnorm_rope_kv_rope_quant_insert_out'

v0.28.0 eager_scratch_pool calls that _out op. later-main never allocated the pool and used allocating fused_deepseek_v4_qnorm_rope_kv_rope_quant_insert. Host-mounted later-main _C_stable_libtorch does not register _out. SM12x now skips the pool and getattr-guards _out. No CUDA rebuild.

Previous: NameError: copy in DSpark capture (68c95e735) is fixed.

vs later-main (cursor/dsv4-flash-vision-exp-df88)

Vision-Exp serve path (k=3, in-vocab sentinels, vision gate, DSpark draft, Eagle3, FlashInfer dual-cache, graph-safe VL topk) was already on this line.

#52018 leftovers that were still missing and are now ported (285580c8a):

Intentionally not copied from later-main (v0.28.0 architecture / dropped on purpose):

AI assistance was used (Cursor Grok 4.6).

Test Plan

Cloud (x86 CPU, no GPU):

.venv/bin/python -m pytest \
  tests/utils/test_sm12x.py::test_sm12x_align_decode_q_len_snaps_to_safe_widths \
  tests/utils/test_sm12x.py::test_sm12x_align_tokens_unchanged_off_sm12x \
  tests/utils/test_sm12x.py::test_fused_qnorm_insert_out_is_optional \
  tests/utils/test_sm12x.py::test_dspark_init_cudagraph_manager_copies_capture_sizes \
  -v --noconftest
# 4 passed

Spark (host-mount Vision-Exp; worker then head):

git pull origin cursor/spark-v0280-dsv4-df88
NODE_RANK=1 VLLM_HOST_IP=192.168.100.11 HEADLESS=--headless ./docker/gb10/run-vision.sh
NODE_RANK=0 ./docker/gb10/run-vision.sh

Look for mixed warmup after SM12x: insert 4 extra KV slots for prefill pad 2 -> 6, not fused_deepseek_v4_qnorm_rope_kv_rope_quant_insert_out AttributeError.

Why this is not a duplicate

Open Spark PRs on later-main (#5 observability, #7 FlashInfer 0.6.18) are a different history. #52018 is not an ancestor of v0.28.0.

Open in Web Open in Cursor 

Rebase the proven SM12x / DSv4-Flash Spark runtime onto official
v0.28.0 instead of post-0.28.0 main. Drop trial debug scripts, the
FlashInfer nightly overlay, and later-main linear b12x APIs that do
not exist on this tag.

Pins: FlashInfer 0.6.18, official b12x==1.2.6. Wire --moe-backend
b12x through the v0.28.0 NVFP4 oracle (SwiGLU clamp included) so
run.sh can keep stock --linear-backend b12x --moe-backend b12x.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Cover --moe-backend b12x mapping, kernel class, and SwiGLU-clamp
allowlisting without constructing VllmConfig (no GPU in this env).

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
…6.18

PyTorch's cu130 index publishes packaging<=24.1. uv then ignores PyPI
and FlashInfer 0.6.18 (packaging>=24.2) fails to resolve. Use the same
UV_INDEX_STRATEGY=unsafe-best-match as the stock CUDA Dockerfile.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
run.sh keeps the dev mount of /home/roccen/src/vllm (or VLLM_SRC).
run-image.sh / run-vision-image.sh serve the baked /opt/vllm so the
container matches what build.sh produced.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
sync-image.sh was saving vllm-gb10:dspark even after build.sh tagged
the versioned image. Accept an explicit tag argument and fail if the
local image is missing.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
WORKDIR is /opt/vllm, so a bare `vllm` resolves to the source package
dir and bash reports "cannot execute: Is a directory". Launch via
python -m vllm.entrypoints.cli.main.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
run-image.sh stripped uv PEP 660 finders and left only a .pth. Imports
worked; importlib.metadata.version("vllm") did not, so the CLI died
before serve. Relocate finders only when bind-mounting host source.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Image-mode serve launches the baked CLI via PYTHONPATH=/opt/vllm.
uv's editable install is then invisible to importlib.metadata, so
version("vllm") dies at argparse. Write a stub dist-info under /tmp
(and site-packages) before exec. Host-script only; no image rebuild.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Image-mode serve set PYTHONPATH=/opt/vllm, so import vllm loaded the
source tree as a regular package. cmake .so files live on the uv
editable finder path, so vllm._C_stable_libtorch was missing. Leave
PYTHONPATH unset in image mode and symlink build/ extensions into
vllm/ when needed. Host-script only; no image rebuild unless the
image never compiled the extension.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
The first v0.28.0-dsv4-spark image had no _C_stable_libtorch*.so.
Force --torch-backend cu130 and VLLM_TARGET_DEVICE=cuda so setup.py
does not skip CUDA ops, then assert torch.version.cuda and the
compiled extension before tagging. No --no-cache needed.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
The first v0.28.0-dsv4-spark image had CUDA torch but no vLLM package
metadata and no _C_stable_libtorch. fa2/fa3 .so files were host leftovers
(dockerignore only excluded vllm/*.so). Install requirements/build/cuda.txt
before editable install, copy instead of hardlink, ignore all vllm .so
from the build context, and fail the image if metadata or the extension
is missing. Allow SM121 on CUDA 13.0.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Dockerfile.gb10 keeps /root/.cache/uv as a BuildKit mount so rebuilds
do not re-download torch/FlashInfer. pack-venv.sh now defaults to the
v0.28.0-dsv4-spark tag and refuses a host venv without
vllm._C_stable_libtorch (later-main ~/.venvs/vllm028).

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
The 15:19 v0.28.0-dsv4-spark image finished in ~30m with CUDA torch
but no vllm metadata and no _C_stable_libtorch. uv pip install -e .
was returning success without running cmake. Build extensions inplace
first (nvcc visible in the log), then reinstall the editable package.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
One script creates ~/.venvs/vllm028, installs cu130 + FlashInfer,
runs setup.py build_ext --inplace, writes editable metadata, and
installs b12x==1.2.6. Does not run use_existing_torch.py. pack-venv.sh
then copies that venv into vllm-gb10:v0.28.0-dsv4-spark.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
setuptools-rust runs build_rust after CUDA build_ext even when the
Rust frontend is optional. That fails host Spark compiles with
"can't find Rust compiler". Python serve does not need vllm-rs.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Do not skip the Rust frontend when rustc is missing. Source
~/.cargo/env and require rustc/cargo so setuptools-rust can
compile vllm-rs after the CUDA extensions.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
pack-venv copies the script to /tmp/check-extensions.py. pathlib
parents[2] then raises IndexError after relocate-venv already
succeeded. Resolve VLLM_ROOT=/opt/vllm or a tree that contains vllm/.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
pack-venv already imports the extension on the host. The image
check runs without the NVIDIA driver, so libcuda.so.1 is missing
even when the .so files and metadata are present.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Docker layers are already gzip-compressed. ssh -C only burns CPU
on the 100GbE link. Default is Compression=no; nc is documented
for a raw-TCP push.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Vision-Exp uses expert_dtype=fp4 (Mxfp4MoEMethod). --moe-backend b12x
was only wired for NVFP4, so serve died in map_mxfp4_backend. Map
b12x to W4A8 then W4A16, and call B12xExperts.process_weights after
the MXFP4 kernel is built.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
…t_ids

Replicate official vllm-project#52018 MXFP4 policy on v0.28.0: W4A8 first,
VLLM_B12X_MOE_FP4_FORCE_A16, exact dims, convert .data, and
b12x entry points on compressed_tensors / INC / online / quark.

Official processor pops input_ids; DeepseekV4VLProcessor only
emits vision tensors. Tokenize the prompt on the VL processor
and do not treat the HF call as applying placeholder updates.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Port the remaining later-main b12x surface onto v0.28.0: NVFP4
FORCE_A16 / use_a16 through convert and quant config, provider
MoE warmup plus existing linear warmup, eager b12x submodule
imports, docs, and the official test_b12x.py suite.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
init_cudagraph_manager copies compilation_config so Vision k=3
can capture at 6/12/18/24 without mutating the main sizes. The
copy.copy call was ported from later-main without import copy,
which NameError'd after encoder profile on Spark.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
v0.28.0 eager_scratch_pool calls
fused_deepseek_v4_qnorm_rope_kv_rope_quant_insert_out. later-main
never allocated that pool and host-mounted later-main
_C_stable_libtorch does not register _out, so Vision mixed warmup
AttributeError'd after the 2->6 prefill pad. Keep the allocating
insert on SM12x and getattr-guard _out.

Co-authored-by: Cursor Grok 4.6
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants