Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 6 additions & 41 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
ARG BASE_IMAGE=vllm/vllm-openai:v0.22.0-cu129-ubuntu2404
ARG BASE_IMAGE=vllm/vllm-openai:v0.23.0-cu129-ubuntu2404
FROM ${BASE_IMAGE}

# ======================================== Arguments =============================================

ARG PATCH_VERSION=latest
ARG MEGATRON_COMMIT=1dcf0dafa884ad52ffb243625717a3471643e087

ARG ENABLE_CUDA_13=0
ARG TMS_CUDA_MAJOR=

# ======================================== Setup =============================================

WORKDIR /root/
Expand Down Expand Up @@ -53,33 +50,10 @@ RUN if [ "${INSTALL_FLASHQLA}" = "1" ]; then \
fi
RUN pip install tilelang -f https://tile-ai.github.io/whl/nightly/cu128/

# cublas + (cu13) cuda dev headers. The arm64 (sbsa) vllm/vllm-openai base ships
# the cublas runtime .so but not the dev header (cublas_v2.h) / unversioned .so
# symlink that the x86 base has; TE needs the header and its CMake only creates
# the CUDA::cublas target when both exist. The dev pkg must match the toolkit
# CUDA major. For cu13 the top apt block's -12-9 dev set is the wrong major, so
# also install the -13-0 nvrtc/nvtx/etc. headers TE's nvcc build needs. Placed
# after the slow flash-attn layers so their cache is preserved; before TE.
RUN apt-get update && \
if [ "${ENABLE_CUDA_13}" = "1" ]; then \
apt-get install -y libcublas-dev-13-0 \
cuda-nvrtc-dev-13-0 cuda-nvtx-13-0 cuda-nvml-dev-13-0 cuda-profiler-api-13-0 \
libcusparse-dev-13-0 libcusolver-dev-13-0 libcufft-dev-13-0 libcurand-dev-13-0; \
else apt-get install -y libcublas-dev-12-9; fi && \
rm -rf /var/lib/apt/lists/*
# cublas dev header for TE CMake (arm64 base ships runtime .so but not the header).
RUN apt-get update && apt-get install -y libcublas-dev-12-9 && rm -rf /var/lib/apt/lists/*

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To keep the Docker image size as small as possible, it is recommended to use the --no-install-recommends flag with apt-get install. This prevents the installation of recommended but non-essential packages.

RUN apt-get update && apt-get install -y --no-install-recommends libcublas-dev-12-9 && rm -rf /var/lib/apt/lists/*


# TE does not have wheel on cuda 13 yet, thus need to install from source.
# TE is built with --no-build-isolation, so its build deps must be pre-installed;
# install the set TE's release_v2.10 CI uses (wheel packaging ninja pybind11).
# nvidia-mathdx is left unpinned (as in TE CI): 26.6.0 is x86-only, arm64 (sbsa)
# max is 25.6.0, and TE release_v2.10 does not pin or reference it (it links plain
# CUDA::cublas), so the resolver picking the per-arch latest is safe.
RUN if [ "${ENABLE_CUDA_13}" = "1" ]; then \
pip install nvidia-mathdx pybind11 ninja wheel packaging && \
pip -v install --no-build-isolation git+https://github.com/NVIDIA/TransformerEngine.git@release_v2.10; \
else \
pip -v install --no-build-isolation "transformer_engine[pytorch]==2.10.0"; \
fi
RUN pip -v install --no-build-isolation "transformer_engine[pytorch]==2.10.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to use the --no-cache-dir flag with pip install to prevent caching of wheel files and package downloads, which helps minimize the Docker image size.

RUN pip -v install --no-cache-dir --no-build-isolation "transformer_engine[pytorch]==2.10.0"


RUN NVCC_APPEND_FLAGS="--threads 4" \
pip -v install --disable-pip-version-check --no-cache-dir \
Expand All @@ -89,20 +63,11 @@ RUN NVCC_APPEND_FLAGS="--threads 4" \
RUN git clone https://github.com/NVIDIA/Megatron-LM.git --recursive && \
cd Megatron-LM && git checkout ${MEGATRON_COMMIT}

# torch_memory_saver pinned to a193d9dd (upstream slime #1916). The newer commit
# ships a multi-CUDA wheel and requires TMS_CUDA_MAJOR at build time; default it
# to the running torch's CUDA major (slime #1924).
RUN TMS_CUDA_MAJOR="${TMS_CUDA_MAJOR:-$(python -c 'import torch; print(torch.version.cuda.split(".")[0])')}" && \
export TMS_CUDA_MAJOR && \
pip install git+https://github.com/fzyzcjy/torch_memory_saver.git@a193d9dd1b877d33c64a41cfb3db9f867df2d926 --no-cache-dir --force-reinstall
# torch_memory_saver pinned to a193d9dd (upstream slime #1916).
RUN pip install git+https://github.com/fzyzcjy/torch_memory_saver.git@a193d9dd1b877d33c64a41cfb3db9f867df2d926 --no-cache-dir --force-reinstall
RUN pip install git+https://github.com/radixark/Megatron-Bridge.git@bridge --no-deps --no-build-isolation
RUN pip install nvidia-modelopt[torch]>=0.37.0 --no-build-isolation

# This patch from masahi will be included in later Triton releases
RUN if [ "$ENABLE_CUDA_13" = "1" ]; then \
(cd /root && git clone -b feat/v350_plus_8045 https://github.com/fzyzcjy/triton.git && cd triton && pip install -r python/requirements.txt && pip install --verbose -e .); \
fi

COPY requirements.txt /tmp/requirements.txt
RUN pip install --ignore-installed PyJWT && \
pip install -r /tmp/requirements.txt
Expand Down
27 changes: 6 additions & 21 deletions docker/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,23 @@
# both the linux/amd64 and linux/arm64 digests and `docker pull` auto-selects
# the platform. No arch suffix is ever published as a tag.
#
# CUDA 12.9 is the default, so it carries NO cu marker in the tag. Only the
# non-default cu13 variant is suffixed.
#
# The CUDA + source-built FA/TE images can't be cross-emulated, so each arch is
# built on its own native host and pushed BY DIGEST (no tag lands in the hub),
# then the two digests are fused into the final tag with `just manifest`.
#
# Tag scheme:
# inferactinc/public:vime-<version> immutable, multi-arch (cu12.9)
# inferactinc/public:vime-latest rolling, multi-arch (cu12.9)
# inferactinc/public:vime-cu13-<version> immutable, multi-arch (cu13 variant)
# inferactinc/public:vime-cu13-latest rolling, multi-arch (cu13 variant)
# inferactinc/public:vime-<version> immutable, multi-arch
# inferactinc/public:vime-latest rolling, multi-arch
# <version> comes from docker/version.txt.

IMAGE := "inferactinc/public"
BUILDER := "vime-builder"

# ---- per-arch build, pushed BY DIGEST (run once on an amd64 host, once on an arm64 host) ----

# Default — cu12.9, no cu marker in the tag.
build:
ARG_TAG_SUFFIX="" ARG_BUILD_EXTRA_ARGS="--build-arg INSTALL_FLASHQLA=1" just _build-digest

# cu13 variant — vLLM default-CUDA base; ENABLE_CUDA_13 builds the CUDA-13
# TransformerEngine/Triton on top.
build-cu13:
ARG_TAG_SUFFIX="-cu13" ARG_BUILD_EXTRA_ARGS='--build-arg BASE_IMAGE=vllm/vllm-openai:v0.22.0-ubuntu2404 --build-arg ENABLE_CUDA_13=1' just _build-digest

_build-digest:
#!/bin/bash
set -euxo pipefail
Expand All @@ -48,19 +37,15 @@ _build-digest:
jq -r '."containerimage.digest"' "$META"

# ---- fuse the two per-arch digests into one multi-arch tag ----
# Run once after `build` (or `build-cu13`) has pushed on BOTH hosts, passing the
# digests it printed. For the default cu12.9 image leave VARIANT empty:
# just manifest "" sha256:<amd64> sha256:<arm64> -> vime-<version> + vime-latest
# just manifest cu13 sha256:<amd64> sha256:<arm64> -> vime-cu13-<version> + vime-cu13-latest
manifest VARIANT AMD_DIGEST ARM_DIGEST:
# Run once after `build` has pushed on BOTH hosts, passing the digests it printed:
# just manifest sha256:<amd64> sha256:<arm64> -> vime-<version> + vime-latest
manifest AMD_DIGEST ARM_DIGEST:
#!/bin/bash
set -euxo pipefail
cd ..

VERSION="$(cat docker/version.txt | tr -d '\n')"
SUFFIX=""
[ -n "{{VARIANT}}" ] && SUFFIX="-{{VARIANT}}"
docker buildx imagetools create -t "{{IMAGE}}:vime${SUFFIX}-${VERSION}" -t "{{IMAGE}}:vime${SUFFIX}-latest" "{{IMAGE}}@{{AMD_DIGEST}}" "{{IMAGE}}@{{ARM_DIGEST}}"
docker buildx imagetools create -t "{{IMAGE}}:vime-${VERSION}" -t "{{IMAGE}}:vime-latest" "{{IMAGE}}@{{AMD_DIGEST}}" "{{IMAGE}}@{{ARM_DIGEST}}"

# ---- single-arch test/debug image for the run-ci-image validation job ----
# The e2e-test-image runner is x86, so this is amd64-only and
Expand Down
46 changes: 19 additions & 27 deletions docker/patch/latest/vllm.patch
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
diff --git a/vllm/v1/engine/core.py b/vllm/v1/engine/core.py
--- a/vllm/v1/engine/core.py
+++ b/vllm/v1/engine/core.py
@@ -750,8 +750,10 @@
if tags is None or tags:
self.model_executor.wake_up(tags)
diff --git a/vllm/model_executor/layers/fused_moe/all2all_utils.py b/vllm/model_executor/layers/fused_moe/all2all_utils.py
--- a/vllm/model_executor/layers/fused_moe/all2all_utils.py
+++ b/vllm/model_executor/layers/fused_moe/all2all_utils.py
@@ -5,7 +5,6 @@ from typing import Any

- # Resume scheduling (applies to all levels)
- self.resume_scheduler()
+ # Partial wakes intentionally keep the remaining allocations asleep.
+ # Resume scheduling only once all executor memory is resident again.
+ if not self.model_executor.is_sleeping:
+ self.resume_scheduler()
import torch

def is_sleeping(self) -> bool:
"""Check if engine is sleeping at any level."""
@@ -1844,8 +1846,11 @@
continue
-from vllm.config import get_current_vllm_config
from vllm.distributed import (
get_ep_group,
)
@@ -240,9 +239,7 @@ def maybe_make_prepare_finalize(

# We are in a running state and so must execute a dummy pass
- # if the model didn't execute any ready requests.
- self.execute_dummy_batch()
+ # if the model didn't execute any ready requests -- unless the executor is
+ # asleep (#44483: a decode-shaped dummy batch reads freed KV -> illegal memory
+ # access). The finished-sync all-reduce below still runs (DP lockstep).
+ if not self.is_sleeping():
+ self.execute_dummy_batch()

# 3) All-reduce operation to determine global unfinished reqs.
self.engines_running = self._has_global_unfinished_reqs(
elif moe.use_fi_nvl_one_sided_kernels:
assert quant_config is not None
- max_num_tokens = (
- get_current_vllm_config().scheduler_config.max_num_batched_tokens
- )
+ max_num_tokens = moe.max_num_tokens
if quant_config.quant_dtype is None:
dispatch_dtype_bytes_per_elem = 2
dispatch_scale_bytes_per_token = 0