Browse Source

sparkring-shared image dir: thin FROM wrapper over the pinned digest

Digest-only pulls leave an untagged image that the launcher cannot match
by tag and that docker prune reaps as dangling. The wrapper tags it under
the normal build/sync flow (buildx on a build node, save|ssh load to the
rest, checksum label).

Dockerfile also bridges the b12x loader JIT: the profile links
-L/opt/cuda-13.3/lib64 -lcudart, but this CUDA 13 image ships libcudart
only as pip nvidia/cu13/lib/libcudart.so.13 (no lib64 dir at all). The
first serve died with 'ld: cannot find -lcudart'; the symlink + a
pre-build of the loader extension fixes it and bakes the native cache
into the image.

Recipe fixes from the live bring-up: model path through the standard
HF-cache mount (a bare snapshot bind-mount leaves the HF blob symlinks
dangling inside the container), pipeline_parallel_size=1 (launcher
default is pp=nnodes), PORT + SERVED_MODEL_NAME env (the wrapper's
warmup targets 127.0.0.1:$PORT and uses $SERVED_MODEL_NAME as the
warmup model name; both defaulted to wrong values -> 1800s warmup
deadline or a 404 loop), DFLASH_WARMUP_TIMEOUT_SECONDS 1800 for the
cold first-run JIT.
Alexander Korolev 1 month ago
parent
commit
87340498fb

+ 24 - 0
docker-images/sparkring-shared/Dockerfile

@@ -0,0 +1,24 @@
+# syntax=docker/dockerfile:1.7
+# SparkRing shared stack (FujitsuPolycom/sparkring) as a sm121-managed image.
+#
+# The public image is published digest-only (no tags), so a raw pull leaves an
+# untagged image that (a) sm121's image-presence probe cannot match by tag and
+# (b) `docker image prune` reaps as dangling. Wrapping it in a thin FROM with
+# a local tag puts it under the normal sm121 build/sync flow: built once on a
+# build node, `docker save | ssh docker load` to the rest, checksum-label
+# stamped, and safe from prune.
+#
+# No stages, no layers: the entire runtime lives upstream of the FROM.
+ARG BASE_IMAGE
+FROM ${BASE_IMAGE}
+LABEL sm121.source="ghcr.io/fujitsupolycom/sparkring" sm121.digest="sha256:f25cdb6bf7df85754ea5c62445b139dac3143bc6e910a0442d681b6e63c31c4b"
+
+# The b12x loader JIT-compiles _storage.c with `-L/opt/cuda-13.3/lib64 -lcudart`,
+# but this CUDA 13 image ships libcudart only as pip nvidia/cu13/lib/libcudart.so.13
+# (no lib64 dir, no dev symlink) — the first serve attempt dies with
+# "ld: cannot find -lcudart". Bridge it, then pre-build the extension so the
+# runtime cache is baked into the image and serves never hit the JIT.
+RUN set -eux; \
+    mkdir -p /opt/cuda-13.3/lib64; \
+    ln -s /usr/local/lib/python3.12/dist-packages/nvidia/cu13/lib/libcudart.so.13 /opt/cuda-13.3/lib64/libcudart.so; \
+    python3 -c "import b12x.loader._native as n; n.load(); print('b12x loader native pre-built')"

+ 25 - 0
docker-images/sparkring-shared/build.sh

@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+# Build the SparkRing shared-image wrapper (thin FROM over the pinned digest).
+#
+# Generic driver: forwards every KEY=VAL pin in versions.env as a
+# --build-arg to the Dockerfile (no hardcoded variable list). The sm121
+# launcher writes a merged versions.env here when a recipe carries
+# [build.versions] overrides (recipe wins over the image defaults).
+set -euo pipefail
+cd "$(dirname "$0")"
+TAG="${TAG:-sparkring-shared:local}"
+
+ARGS=()
+while IFS= read -r line; do
+    # Skip blank lines and comments (# ...).
+    case "$line" in
+        ''|\#*) continue ;;
+    esac
+    key="${line%%=*}"
+    val="${line#*=}"
+    [ -n "$key" ] && ARGS+=(--build-arg "${key}=${val}")
+done < versions.env
+
+echo "=== Building ${TAG} ==="
+docker buildx build "${ARGS[@]}" --progress=plain --load -t "${TAG}" -f Dockerfile . 2>&1
+echo "=== Done: ${TAG} ==="

+ 5 - 0
docker-images/sparkring-shared/versions.env

@@ -0,0 +1,5 @@
+# versions.env - build input for the SparkRing shared-image wrapper.
+# The image is a thin, fully-pinned FROM wrapper over the public SparkRing
+# digest (no rebuildable stages — everything lives upstream of the FROM).
+# Convention: KEY=VAL, no spaces around = (the build.sh driver parses literally).
+BASE_IMAGE=ghcr.io/fujitsupolycom/sparkring@sha256:f25cdb6bf7df85754ea5c62445b139dac3143bc6e910a0442d681b6e63c31c4b

+ 12 - 6
recipes/glm53-flash-sparkring-2x/recipe.toml

@@ -11,8 +11,9 @@
 
 engine = "vllm"
 name = "GLM-5.3-Flash NVFP4-Spark (SparkRing shared img, TP2 RoCEnante profile)"
-docker_image = "ghcr.io/fujitsupolycom/sparkring@sha256:f25cdb6bf7df85754ea5c62445b139dac3143bc6e910a0442d681b6e63c31c4b"
-model = "/models/target"
+docker_image = "sparkring-shared:local"
+docker_image_dir = "sparkring-shared"
+model = "/root/.cache/huggingface/hub/models--local-inference-lab--GLM-5.3-Flash-NVFP4-Spark/snapshots/df116c4fb16b1d37ae43d2cfd624de26ffbc832e"
 port = 8000
 required_nodes = 2
 tensor_parallel_size = 2
@@ -56,10 +57,6 @@ args = [
     "--limit-mm-per-prompt", "{\"image\": 4, \"video\": 0}",
 ]
 
-[[extra_mounts]]
-host = "/mnt/nas/ai/huggingface/hub/models--local-inference-lab--GLM-5.3-Flash-NVFP4-Spark/snapshots/df116c4fb16b1d37ae43d2cfd624de26ffbc832e"
-container = "/models/target"
-read_only = true
 
 [env]
 B12X_POLICY_MODE = "auto"
@@ -105,3 +102,12 @@ VLLM_WORKER_MULTIPROC_METHOD = "spawn"
 VLLM_DISABLED_KERNELS = "MarlinFP8ScaledMMLinearKernel"
 PYTHONDONTWRITEBYTECODE = "1"
 LD_PRELOAD = "/opt/sparkring/nccl-pci/libnccl.so.2.30.7"
+PORT = "8000"
+SERVED_MODEL_NAME = "GLM-5.3-Flash-NVFP4-Spark"
+DFLASH_WARMUP = "1"
+DFLASH_WARMUP_CONCURRENCIES = "1"
+DFLASH_WARMUP_SHAPE_WORDS = "8"
+DFLASH_WARMUP_MAX_TOKENS = "16"
+DFLASH_WARMUP_TIMEOUT_SECONDS = "1800"
+SPARKRING_LIVENESS_ENABLED = "1"
+SPARKRING_LIVENESS_PORT = "8001"

File diff suppressed because it is too large
+ 8 - 0
recipes/glm53-flash-sparkring-2x/reports/2026-09-09_154033_sparkring-2x.log


+ 128 - 0
recipes/glm53-flash-sparkring-4x/recipe.toml

@@ -0,0 +1,128 @@
+# SparkRing shared image — TP4 SWITCHED profile
+# (`/opt/sparkring/profiles/glm53-flash-spark-tp4-switched/profile.json`,
+# "glm53-flash-spark-tp4-switched-mtp3", status: research-only — "not validated
+# on switched hardware"). Plain NCCL (RoCEnante OFF), NCCL_ALGO=Ring,
+# KV 24 GiB fp8, max-len 1M, MTP3 with draft TP4. Structural flags
+# (--tp/--pp/--nnodes/--node-rank/--master-addr/--master-port/--host/--port)
+# come from the launcher (master-port: 25000 vs their 29795 — cosmetic).
+# Model: local-inference-lab/GLM-5.3-Flash-NVFP4-Spark @ df116c4f from the
+# shared NFS cache, mounted read-only at /models/target as the profile expects.
+
+engine = "vllm"
+name = "GLM-5.3-Flash NVFP4-Spark (SparkRing shared img, TP4 switched profile)"
+docker_image = "sparkring-shared:local"
+docker_image_dir = "sparkring-shared"
+model = "/root/.cache/huggingface/hub/models--local-inference-lab--GLM-5.3-Flash-NVFP4-Spark/snapshots/df116c4fb16b1d37ae43d2cfd624de26ffbc832e"
+port = 8000
+required_nodes = 4
+tensor_parallel_size = 4
+pipeline_parallel_size = 1
+distributed_backend = "mp"
+
+args = [
+    "--decode-context-parallel-size", "1",
+    "--cp-kv-cache-interleave-size", "1",
+    "--disable-custom-all-reduce",
+    "--mamba-cache-mode", "align",
+    "--limit-mm-per-prompt", "{\"image\":4,\"video\":1}",
+    "--enable-chunked-prefill",
+    "--dtype", "bfloat16",
+    "--kv-cache-dtype", "fp8",
+    "--quantization", "modelopt_mixed",
+    "--attention-backend", "B12X",
+    "--block-size", "512",
+    "--mamba-block-size", "512",
+    "--recurrent-checkpoint-policy", "aligned",
+    "--prefix-cache-retention-interval", "0",
+    "--moe-backend", "b12x",
+    "--linear-backend", "b12x",
+    "--no-enable-flashinfer-autotune",
+    "--load-format", "fastsafetensors",
+    "--enable-auto-tool-choice",
+    "--tool-call-parser", "glm47",
+    "--reasoning-parser", "glm45",
+    "--kda-prefill-backend", "b12x",
+    "--gpu-memory-utilization", "0.80",
+    "--kv-cache-memory-bytes", "25769803776",
+    "--max-model-len", "1048576",
+    "--max-num-seqs", "16",
+    "--max-num-batched-tokens", "8192",
+    "--prefill-schedule-interval", "2",
+    "--speculative-config", "{\"method\":\"mtp\",\"num_speculative_tokens\":3,\"draft_tensor_parallel_size\":4,\"kv_cache_dtype\":\"auto\",\"draft_sample_method\":\"probabilistic\",\"rejection_sample_method\":\"standard\",\"draft_load_config\":{\"load_format\":\"safetensors\"},\"attention_backend\":\"B12X\"}",
+    "--compilation-config", "{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"cudagraph_capture_sizes\":[4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64],\"custom_ops\":[\"all\"],\"pass_config\":{\"fuse_allreduce_rms\":false}}",
+    "--max-cudagraph-capture-size", "64",
+    "--async-scheduling",
+    "--enable-prefix-caching",
+    "--cudagraph-metrics",
+    "--enable-prompt-tokens-details",
+    "--served-model-name", "glm-5.3-flash-spark",
+]
+
+
+[env]
+PYTHONDONTWRITEBYTECODE = "1"
+VLLM_SPARK_SHARED_CAPTURE_STREAM = "0"
+SPARK_TP4_HEALTH_GATE = "0"
+SPARK_CUDAGRAPH_REPLAY_TIMING = "0"
+SPARK_TP4_DCP_COLLECTIVE_AUDIT = "0"
+SPARK_GDN_PREFILL_CHECKPOINTS = "0"
+SPARK_GDN_CONTINUATION_CHECKPOINTS = "0"
+SPARK_MHC_PREFILL_SHARD = "0"
+SPARK_MTP_CAPTURE_TAIL_MAX_REQS = "0"
+VLLM_ENABLE_PCIE_ALLREDUCE = "0"
+VLLM_ENABLE_ROCE_ALLREDUCE = "0"
+VLLM_ALLREDUCE_USE_FLASHINFER = "0"
+VLLM_ALLREDUCE_USE_SYMM_MEM = "0"
+VLLM_USE_NCCL_SYMM_MEM = "0"
+NCCL_SWITCHLESS_RING_ONLY = "0"
+NCCL_IB_SUBNET_AWARE_ROUTING = "0"
+NCCL_IB_EXTENDED_IPV4_GIDS = "1"
+NCCL_IB_PRESERVE_PCI_DOMAIN = "1"
+NCCL_IB_ROUTE_DIAGNOSTICS = "0"
+NCCL_NET = "IB"
+NCCL_NET_PLUGIN = "none"
+NCCL_IB_DISABLE = "0"
+NCCL_ALGO = "Ring"
+NCCL_PROTO = "LL,LL128,Simple"
+NCCL_DEBUG = "WARN"
+NCCL_CUMEM_ENABLE = "0"
+NCCL_IB_MERGE_NICS = "0"
+NCCL_CROSS_NIC = "1"
+VLLM_NCCL_SO_PATH = "/opt/sparkring/nccl-pci/libnccl.so.2.30.7"
+LD_PRELOAD = "/opt/sparkring/nccl-pci/libnccl.so.2.30.7"
+VLLM_USE_V2_MODEL_RUNNER = "1"
+VLLM_B12X_KDA_PREFILL_COALESCING = "1"
+VLLM_GLM53_MHC_PREFILL_SHARD = "1"
+VLLM_GLM53_MHC_PREFILL_DIAGNOSTICS = "1"
+VLLM_GLM53_KDA_GATE_SIDE_STREAM = "1"
+VLLM_DCP_TOPK_OWNER_MERGE = "0"
+VLLM_DCP_OWNER_FUSED_ENDPOINTS = "0"
+VLLM_DCP_COMPACT_INDEX_CACHE_OWNER = "0"
+VLLM_DCP_COMPACT_INDEX_TENSOR_VOTE = "0"
+VLLM_DCP_COMPACT_INDEX_LOCAL_WIDTHS = "0"
+VLLM_DCP_COMPACT_INDEX_PROFILE = "0"
+SPARKCACHE_ENABLED = "0"
+SPARKCACHE_ASYNC_PAGE_CAPTURE = "0"
+VLLM_GLM53_SPLIT_TARGET_BLOCK_SIZE = "512"
+VLLM_GLM53_SPLIT_MAMBA_BLOCK_SIZE = "512"
+VLLM_B12X_MLA_CKV_GATHER = "1"
+VLLM_MTP_NVFP4_LM_HEAD = "1"
+VLLM_LM_HEAD_A16 = "1"
+VLLM_MXFP8_LM_HEAD = "0"
+VLLM_B12X_MOE_FP4_FORCE_A16 = "0"
+VLLM_GDN_SPEC_DECODE_METADATA_FASTPATH = "1"
+VLLM_FASTSAFETENSORS_QUEUE_SIZE = "1"
+VLLM_WORKER_MULTIPROC_METHOD = "spawn"
+VLLM_NO_USAGE_STATS = "1"
+HF_HUB_OFFLINE = "1"
+TRANSFORMERS_OFFLINE = "1"
+PORT = "8000"
+SERVED_MODEL_NAME = "glm-5.3-flash-spark"
+DFLASH_WARMUP = "1"
+DFLASH_WARMUP_CONCURRENCIES = "1"
+DFLASH_WARMUP_SHAPE_WORDS = "8"
+DFLASH_WARMUP_MAX_TOKENS = "16"
+DFLASH_WARMUP_TIMEOUT_SECONDS = "1800"
+SPARKRING_WARMUP_TEMPERATURE = "1"
+SPARKRING_LIVENESS_ENABLED = "1"
+SPARKRING_LIVENESS_PORT = "8001"

Some files were not shown because too many files changed in this diff