build(vllm): upgrade to 0.25.1 and make CSCS images reproducible - #12
Merged
Conversation
Tracks upstream's own bump (NVIDIA-NeMo/RL#3280) so later ports diff directly against it. The 0.25 API moves this rebase covers: the serving renderer (OpenAIServingRender -> OnlineRenderer, with tool_parser/reasoning_parser folded into a single `parser`), the fused-MoE split (FusedMoE -> MoERunner + RoutedExperts) and fp8's weight_scale -> weight_scale_inv, and Ray env propagation through the official VLLM_RAY_EXTRA_ENV_VARS_TO_COPY hook. Two source patches retire: upstream fixed the Hermes tool-parser race, and the v1 executor patch is inert under 0.25's RayExecutorV2 default. Also carries the follow-ups upstream shipped in that commit which our v0.7.0-era tree lacked: - packed_broadcast's producer and consumer join their side streams before returning. 0.25's PyNcclCommunicator enqueues without blocking, so refit broadcasts could still be in flight while the caller mutated the source weights or generation read them. - RayExecutorV2 TCPStore port offset and MessageQueue bind retry, which fix deterministic EADDRINUSE startup failures for engines spanning nodes. - _init_workers_ray reports whether its anchor actually landed instead of logging success unconditionally, and the caller distinguishes applied, inert-under-v2, and broken-and-load-bearing. Upstream's tests for those come with them (test_vllm_patches, test_vllm_tcpstore_port, test_vllm_message_queue_port). The MoE-refit hunks of #3280 are deliberately not ported: they patch the checkpoint-engine loader (refit_loader/refit_layout), which post-dates v0.7.0 and does not exist here. Our refit goes through vLLM's own load_weights, which owns the .routed_experts. rename internally. build_nemo_rl_image.slurm builds the arm64 image with Podman on a compute node and exports SquashFS for the Container Engine; the machine-local EDF it produces is gitignored. The README documents the image, its build and cache lifecycle, and the environment traps certification surfaced: run one containerized step per allocation, and pin UV, since a personal uv predating the new [tool.uv] fields hard-fails worker-venv builds. Certified on that image: GRPO sync gen-KL 0.0003/0.0003/0.0004 on two separate nodes (job 3065064 and an in-allocation rerun), NeMo-Gym async 0.0008/0.0007/0.0008 in its established band, the xIELU CUDA training kernel forward+backward within one bf16 ulp, and generation kernel-free in every run. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
`uv run --locked` re-syncs the driver environment only. Worker venvs are reused whenever they carry the readiness marker, so the vLLM 0.20 -> 0.25.1 bump left generation workers importing 0.20 until 0.25-only code failed at refit with a ModuleNotFoundError on fused_moe.routed_experts. The venvs looked healthy the whole time; nothing in the run said which resolution they served. The marker now holds a digest of uv.lock and pyproject.toml instead of being an empty flag, and a venv counts as ready only when that digest matches. A mismatch flows into the rebuild-in-place path that already handles unmarked venvs, since `uv sync` is convergent. pyproject is digested alongside the lock because [tool.uv] build settings change the installed environment without changing the resolution. A waiter that sees a completed build with a different digest now fails with that reason rather than timing out. venvs.py also honors a pinned UV for its uv invocations, and the fixgate launcher exports it into the container: the bumped pyproject uses [tool.uv] fields that uv < 0.11 rejects, so a personal uv earlier on PATH turned worker venv builds into hard failures. The launcher change also picks up the probe recipe rename from the previous commit. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
The suite needs the test dependency group, so running it through the shared .venv re-syncs that venv to a shape training jobs do not want; a job starting alongside re-syncs it back and the suite dies mid-collection, which is how one run failed with a Ray abort while a multinode probe was starting. Point it at .venv-test instead, and gitignore that directory. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Rootless Podman stores its pause process under XDG_RUNTIME_DIR. A batch step has no logind session, so /run/user/<uid> is absent and the first podman command fails with `open .../libpod/tmp/pause.pid: no such file or directory`. Earlier builds only succeeded because they ran inside interactive allocations, which do have that directory. Point it at the allocation-local Podman storage base when the environment does not provide one. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
.dockerignore excluded `.venv` exactly, so a sibling environment such as `.venv-test` (the isolated venv the unit suite runs in) was tarred into the build context and the image build died seconds in. Match the whole family. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Three causes were found and two are fixed in code (the runtime directory under sbatch, and .dockerignore matching every local venv); the stale registry lock needs an operator step, and Podman is only reachable from the compute node host. Past that point the build still exits without a message, so note the state and leave the certified image in place rather than keep retrying on a node that has served many interrupted builds. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
The SquashFS was baked from 336136c-dirty-fd360335e307, before the packed_broadcast stream joins and the two RayExecutorV2 port patches landed. Verified against the artifact: its /opt/nemo-rl carries neither. Certification ran the checkout ahead of the baked tree on PYTHONPATH, so the published image is only self-contained for single-node engines until it is rebuilt. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
A batch step has no logind session, so rootless Podman cannot reach /run/user/<uid>/bus; the registry container starts and listens, but the launcher readiness probe never reaches port 5000 and the build stops before its first stage. XDG_RUNTIME_DIR alone does not cover this, so point the procedure back at an interactive allocation until the session side is solved. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Backport the FP8 refit storage fix and regression coverage from the upstream vLLM 0.25.1 integration commit cf766d5. Stable-shape refits now copy into existing allocations instead of rebinding tensor storage and fragmenting GPU memory. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Include the normalized worker launch command in readiness fingerprints so changing extras cannot silently reuse an incompatible environment. Keep dependency-file boundaries explicit and cover rebuild and normalization behavior. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Run the persistent registry on the host network so plain sbatch jobs do not depend on a logind session for rootless port publishing. Serialize cache writers with flock, pin the GH200 base manifest, reject dirty sources, and construct the image context from the committed tree plus recursive submodules. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Normalize checkout aliases in dependency fingerprints and retain actor extras until the final exact uv sync.
Backport vllm-project/vllm#49043 so compiled TP engines fall back when NVSwitch multicast is unavailable. Upstream-commit: 81962bb6995eaebd1e49998c2a91c9e01e24da27
Add the missing license header to the xIELU microbenchmark and mark the public hermetic dependency checksums as detect-secrets false positives.
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Alvorecer721
marked this pull request as ready for review
August 13, 2026 22:36
Upstream TP8 validation assumes 8-GPU nodes where the TP group stays inside NVLink; on quad-GH200 nodes the same setting becomes node-spanning and pays Slingshot latency per layer. Record the placement policy: TP <= 4 in-node, DP across nodes for generation throughput, PP across nodes for capacity, node-spanning TP8 as certified last resort. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
6 tasks
The certified SquashFS now has a group-readable copy under MLLM/containers with an intuitive name following that directory's conventions; the builder original on personal scratch remains the provenance-named artifact. Identity (SHA-256, OCI tag/ID) is unchanged. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
The certified SquashFS now lives at a stable group-readable path under MLLM/containers, so the EDF no longer embeds a user-specific path and can be checked in: clone-and-run needs no EDF authoring. Personal builds override only the image value. Signed-off-by: Alvorecer721 <yixuan.xu@ai.ethz.ch>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Upstream provenance
Validation
test_vllm_policy_generation_async[2-1]), including CUDA graph capture and TRT-LLM workspace fallback3076785)test_vllm_patches.py,test_venvs.py)main; full diff passesgit diff --check7c68228e4f09(Slurm job3077164, 2:03:51)3077837, 4:48)3078831, 3:27)The single-node TP4 result is the maximum relevant tensor-parallel certification for Clariden's quad-GH200 nodes. Two-node TP8 remains optional, non-blocking scalability evidence; the current Apertus-8B Async-GRPO placement uses TP2 inference plus TP2 training on one node and does not require TP8.
CSCS image notes
The certified SquashFS is
/iopsstor/scratch/cscs/xyixuan/ce-images/nemo-rl/nemo-rl-apertus-vllm-0.25.1-7c68228e4f09-38c6b702948c.sqsh(48,752,754,688 bytes), SHA-256d50f39e45f6104d13e12b9323dbe28cc91b0f13e3a250d029ce6cc7e7646742a, OCI image ID18c36e6a31df01fc0370f65f9446c373d741198abf821b35a89be8214c11e79e. The later PR commits add reusable certification probes and record their evidence; they do not change image contents.The persistent OCI cache lives under
/iopsstor/scratch/cscs/xyixuan/podman-cache/nemo-rl; the local registry process is allocation-scoped, while its blobs and exported SquashFS survive node changes. Release builds reject dirty source/submodules and encode the source commit, recursive submodule SHAs, base manifest, and build arguments in the artifact identity.The node-spanning TP8 probe deliberately routes collectives through PyTorch NCCL over the CSCS AWS OFI plugin because vLLM 0.25.1's direct PyNccl and Hopper symmetric-memory paths are incompatible with that topology. On the tested single-node TP2 and TP4 topologies, vLLM rejects the unusable FlashInfer MNNVL multicast workspace and safely initializes the compiled TRT-LLM FlashInfer all-reduce backend.