Bläddra i källkod

Add sparkring shared-image TP2 recipe (2x profile, digest-pinned)

Profile from their quickstart (RoCEnante 2-path, MTP3, KV 8.75G, 262K ctx);
model via NFS snapshot mount; pp=1 pinned (launcher default is pp=nnodes).
Launch needs a prod-downtime window: the 2x pair is the same physical
boxes running r28 4x prod (sm121 label probe sees them as occupied).
Alexander Korolev 1 månad sedan
förälder
incheckning
2c8328d8a9

+ 30 - 0
history/night-shifts/2026-09-08.md

@@ -287,3 +287,33 @@ sparkring.
   base — вопрос владельцу: native MTP — long-term path? (тогда не чиним),
   либо port из JJ R8; (3) 386B = capacity note, не баг.
 - Cluster: прод 4x r28 serving; 2nodes-dac свободен; dgx5 off (10G only).
+
+## 15:00 UTC+2 — SparkRing shared image: заготовлено, ждём окно
+
+Оператор: «есть имидж — давай попробуем, минимальные усилия». Публичный
+digest-only имидж `ghcr.io/fujitsupolycom/sparkring@f25cdb6...` (22.5 GB),
+pull на dgx1+dgx2 (первый pull по `:latest` — manifest unknown, имидж
+публикуется по digest; второй pull — ок; на dgx2 диск 95% полон, осталось
+49G — впритык, но влезло).
+
+Рецепт `glm53-flash-sparkring-2x`: профиль `glm53-flash-spark-tp2-mtp3`
+(TP2/DCP1, RoCEnante 2-path, KV 8.75 GiB fp8, max-len 262K, GMU 0.87, MTP3
+humming, block-size 256, b12x loader, patched NCCL LD_PRELOAD, 43 env —
+всё из profile.json их quickstart). Модель — снапшот df116c4f из NFS через
+extra_mount в /models/target (read_only); entrypoint = default имиджа
+(verify_sources.py --serve wrapper).
+
+Ошибки в ходе подготовки (все поправлено): (1) TOML: bare `args = [...]`
+после `[[extra_mounts]]` молча влетел в mount (тот же класс ловушки) —
+перенёс args/env до table headers; (2) рецепт без `name` — required field;
+(3) dry-run показал `--pp 2` — launcher по дефолту pp=nnodes, надо явное
+`pipeline_parallel_size = 1` в рецепте. Dry-run теперь чистый.
+
+**Почему serve упал с «0 nodes» (4 попытки)**: не баг, не SSH — пара 2x
+(dgx1+dgx2, ssh 88.14/88.10) — те же физические машины, что в 4nodes-switch,
+и на них сейчас стоит **production r28 4x** (sm121_glm53-flash-r28-4x-dcp4_0/_1).
+Probe по sm121-лейблам их видит → occupied → 0 free. Health/web показывают
+per-cluster view (у 2nodes-dac "no containers" — там свои лейблы), что
+маскирует занятость физикой. Вывод: любой sparkring-профиль (2x и 4x)
+требует сначала `sm121 stop --recipe glm53-flash-r28-4x-dcp4` (downtime
+production) — на согласованное окно. Оператору сообщено, ждём решения.

+ 107 - 0
recipes/glm53-flash-sparkring-2x/recipe.toml

@@ -0,0 +1,107 @@
+# SparkRing shared image (ghcr.io/fujitsupolycom/sparkring, digest-pinned)
+# — the sparkring TP2 profile `glm53-flash-spark-tp2-mtp3` from
+# runtime/profiles/glm53-flash-spark-tp2 (profile.json), adapted to sm121:
+# structural flags (--tp/--pp/--nnodes/--node-rank/--master-addr/--master-port/
+# --host/--port) come from the launcher; everything else is the profile's.
+# Model: local-inference-lab/GLM-5.3-Flash-NVFP4-Spark @ df116c4f (already in
+# the shared HF cache; mounted at /models/target as the profile expects).
+# Transport: the image ships the RoCEnante TP2 transport bundle; our DAC pair
+# is on the f1 HCA pair (rocep1s0f1, roceP2p1s0f1), which the launcher
+# injects via NCCL_IB_HCA from the 2nodes-dac [nccl] block.
+
+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"
+port = 8000
+required_nodes = 2
+tensor_parallel_size = 2
+pipeline_parallel_size = 1
+distributed_backend = "mp"
+
+args = [
+    "--decode-context-parallel-size", "1",
+    "--mamba-cache-mode", "align",
+    "--enable-prefix-caching",
+    "--enable-chunked-prefill",
+    "--dtype", "bfloat16",
+    "--attention-backend", "B12X",
+    "--moe-backend", "b12x",
+    "--no-enable-flashinfer-autotune",
+    "--reasoning-parser", "glm45",
+    "--tool-call-parser", "glm47",
+    "--enable-auto-tool-choice",
+    "--served-model-name", "GLM-5.3-Flash-NVFP4-Spark",
+    "--max-model-len", "262144",
+    "--max-num-seqs", "8",
+    "--max-num-batched-tokens", "8192",
+    "--prefill-schedule-interval", "8",
+    "--prefix-cache-retention-interval", "0",
+    "--recurrent-checkpoint-policy", "aligned",
+    "--block-size", "256",
+    "--kv-cache-memory-bytes", "9395240960",
+    "--kv-cache-dtype", "fp8",
+    "--mm-processor-cache-gb", "0",
+    "--mm-encoder-tp-mode", "data",
+    "--linear-backend", "b12x",
+    "--quantization", "modelopt_mixed",
+    "--kda-prefill-backend", "b12x",
+    "--gdn-decode-kernel", "b12x",
+    "--generation-config", "auto",
+    "--load-format", "b12x",
+    "--model-loader-extra-config", "{\"allocation\":\"managed\"}",
+    "--gpu-memory-utilization", "0.87",
+    "--speculative-config", "{\"method\": \"mtp\", \"num_speculative_tokens\": 3, \"moe_backend\": \"humming\", \"attention_backend\": \"B12X\"}",
+    "--compilation-config", "{\"mode\":0,\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"cudagraph_capture_sizes\":[1,2,4,8,12,16,20,24,28,32],\"max_cudagraph_capture_size\":32}",
+    "--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"
+CUDA_DEVICE_MAX_CONNECTIONS = "32"
+CUDA_DEVICE_ORDER = "PCI_BUS_ID"
+CUTE_DSL_ARCH = "sm_121a"
+FLASHINFER_CUDA_ARCH_LIST = "12.1f"
+FLASHINFER_DISABLE_VERSION_CHECK = "1"
+HF_HUB_OFFLINE = "1"
+NCCL_CUMEM_ENABLE = "0"
+NCCL_DEBUG = "WARN"
+NCCL_IB_EXTENDED_IPV4_GIDS = "1"
+NCCL_IB_GID_INDEX = "3"
+NCCL_IB_PRESERVE_PCI_DOMAIN = "1"
+NCCL_IB_ROUTE_DIAGNOSTICS = "1"
+NCCL_IB_SUBNET_AWARE_ROUTING = "0"
+NCCL_LOCAL_INFERENCE_PATH = "/opt/sparkring/nccl-pci/libnccl.so.2.30.7"
+NCCL_NET = "IB"
+NCCL_NET_PLUGIN = "none"
+NCCL_P2P_LEVEL = "SYS"
+NCCL_PROTO = "LL,LL128,Simple"
+OMP_NUM_THREADS = "2"
+PYTORCH_CUDA_ALLOC_CONF = "expandable_segments:True"
+TORCH_USE_RTLD_GLOBAL = "1"
+TRANSFORMERS_OFFLINE = "1"
+VLLM_B12X_KDA_PREFILL_COALESCING = "1"
+VLLM_B12X_MOE_FP4_FORCE_A16 = "0"
+VLLM_ENABLE_PCIE_ALLREDUCE = "0"
+VLLM_GDN_SPEC_DECODE_METADATA_FASTPATH = "1"
+VLLM_GLM53_KDA_GATE_SIDE_STREAM = "0"
+VLLM_GLM53_MHC_PREFILL_SHARD = "1"
+VLLM_GLM53_SPLIT_MAMBA_BLOCK_SIZE = "256"
+VLLM_GLM53_SPLIT_TARGET_BLOCK_SIZE = "2048"
+VLLM_LM_HEAD_A16 = "1"
+VLLM_MEMORY_PROFILE_INCLUDE_ATTN = "1"
+VLLM_MEMORY_PROFILER_ESTIMATE_CUDAGRAPHS = "1"
+VLLM_MTP_NVFP4_LM_HEAD = "1"
+VLLM_MXFP8_LM_HEAD = "1"
+VLLM_NO_USAGE_STATS = "1"
+VLLM_NCCL_SO_PATH = "/opt/sparkring/nccl-pci/libnccl.so.2.30.7"
+VLLM_PLUGINS = "b12x_loader"
+VLLM_WORKER_MULTIPROC_METHOD = "spawn"
+VLLM_DISABLED_KERNELS = "MarlinFP8ScaledMMLinearKernel"
+PYTHONDONTWRITEBYTECODE = "1"
+LD_PRELOAD = "/opt/sparkring/nccl-pci/libnccl.so.2.30.7"

+ 22 - 0
specs/tech-architecture/glm53-recipe-state.md

@@ -1104,3 +1104,25 @@ New recipe `glm53-flash-r28-4x-dcp4`: clone of the r27 4x-dcp4 recipe
 override folds into the build checksum (separate image, no r27 rebuild).
 A/B target: r27 4x DCP4 160/176 + 46.8 t/s; 2x (162/176, 27.4 t/s) after
 the 4x verdict.
+
+## SparkRing shared image (09-09)
+
+Оператор дал доступ к публичному imaged sparkring-стекa:
+`ghcr.io/fujitsupolycom/sparkring@sha256:f25cdb6bf7df85754ea5c62445b139dac3143bc6e910a0442d681b6e63c31c4b`
+(digest-only, тегов нет). Внутри: их vLLM-форк `0.1.dev1+gd377796e8`
+(revision 17bd258075f4), b12x 2883a5df, sparkcache d0cf7296, patched NCCL
+2.30.7, transport `tp2-rocenante-adaptive` (b12x.comm.roce — наш RoCEnante).
+Модель `local-inference-lab/GLM-5.3-Flash-NVFP4-Spark` @ df116c4f уже в
+NFS-кеше. Профили: **TP2/DCP1** (RoCEnante 2-path, KV 8.75 GiB, max-len
+262K, GMU 0.87, MTP3, block 256) и **TP4 switched** (plain NCCL, RoCEnante
+OFF, KV 24 GiB, max-len 1M, GMU 0.80, fastsafetensors).
+
+Рецепт `glm53-flash-sparkring-2x` (TP2-профиль, модель через extra_mount
+снапшота df116c4f в /models/target, entrypoint имиджа). Dry-run: чистый
+(ловля лауночера: `pipeline_parallel_size = 1` обязателен в рецепте, иначе
+pp=nnodes по дефолту; bare-ключи TOML — только до table headers).
+
+**Запуск требует окна downtime**: физическая пара 2x (dgx1+dgx2) = те же
+машинки, что держат production r28 4x (primes совпадают: 88.x/100.x/200.x —
+разные fabrics одной коробки). Probe по sm121-лейблам видит prod-контейнеры
+→ 0 free. И 2x, и 4x-профили требуют сначала `stop` prod.