[ROCm] Add TheRock preview docker updates, Keep Python 3.12 and Ubuntu 22.04 (#49925)

Signed-off-by: Randall Smith <Randall.Smith@amd.com> Co-authored-by: Andreas Karatzas <akaratza@amd.com>

rasmith committed Aug 31, 2026 at 11:09 UTC 3593c964de198646a2a284c24fc53cccd21afd7e
7 files changed +1384 -7
docker/Dockerfile.rock new
+992
@@ -0,0 +1,992 @@
1 +# default base image
2 +ARG REMOTE_VLLM="0"
3 +ARG VLLM_REPO="https://github.com/vllm-project/vllm.git"
4 +ARG VLLM_BRANCH="main"
5 +ARG COMMON_WORKDIR=/app
6 +ARG BASE_IMAGE=rocm/vllm-dev:base
7 +ARG CI_BASE_IMAGE=rocm/vllm-dev:ci_base
8 +ARG ROCM_TRITON_KERNELS_COMMIT=0f380657dbf3ee86eb57558ff71df24f03b5d4e7
9 +ARG INSTALL_LMCACHE=false
10 +# NIC backend for MoRI RDMA support.
11 +# By default (all), drivers and userspace libraries for all supported NIC types
12 +# (ainic and bnxt) are installed; MoRI selects the appropriate one at runtime.
13 +# To install drivers for a single NIC type only, set NIC_BACKEND explicitly:
14 +# --build-arg NIC_BACKEND=ainic # AMD AINIC (Pensando) only
15 +# --build-arg NIC_BACKEND=bnxt # Broadcom Thor-2 only
16 +# --build-arg NIC_BACKEND=none # Install nothing.
17 +ARG NIC_BACKEND=all
18 +# AMD AINIC apt repo settings
19 +# Users can specify a custom version compatible with their host drivers.
20 +# The default version has been tested with ioinic-dkms=25.11.1.001
21 +ARG AINIC_VERSION=1.117.3-hydra
22 +ARG UBUNTU_CODENAME=jammy
23 +
24 +# Sccache configuration. Release builds use this today; CI can opt in when a
25 +# shared S3-compatible cache backend is available.
26 +ARG USE_SCCACHE
27 +ARG SCCACHE_DOWNLOAD_URL
28 +ARG SCCACHE_ENDPOINT
29 +ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
30 +ARG SCCACHE_REGION_NAME=us-west-2
31 +ARG SCCACHE_S3_NO_CREDENTIALS=0
32 +
33 +FROM ${BASE_IMAGE} AS base
34 +
35 +ARG ARG_PYTORCH_ROCM_ARCH
36 +ENV PYTORCH_ROCM_ARCH=${ARG_PYTORCH_ROCM_ARCH:-${PYTORCH_ROCM_ARCH}}
37 +
38 +# Install build dependencies and utilities
39 +RUN apt-get update -q -y && apt-get install -q -y \
40 + sqlite3 libsqlite3-dev libfmt-dev libmsgpack-dev libsuitesparse-dev \
41 + apt-transport-https ca-certificates wget curl \
42 + libnuma-dev ccache mold
43 +RUN --mount=type=cache,target=/root/.cache/pip \
44 + python3 -m pip install --upgrade pip
45 +# Note: mold is installed but not set as the system default linker because
46 +# some packages use JIT compilation at runtime with flags mold does not support.
47 +# Build stages opt in via LDFLAGS="-fuse-ld=mold".
48 +# Remove sccache only if not using sccache (it exists in base image from Dockerfile.rocm_base)
49 +ARG USE_SCCACHE
50 +RUN if [ "$USE_SCCACHE" != "1" ]; then \
51 + apt-get purge -y sccache || true; \
52 + python3 -m pip uninstall -y sccache || true; \
53 + rm -f "$(which sccache)" || true; \
54 + fi
55 +
56 +# Install UV — download first, then run, so a curl failure is not masked by the pipe
57 +RUN curl -LsSf --retry 3 --retry-delay 5 https://astral.sh/uv/install.sh -o /tmp/uv-install.sh \
58 + && env UV_INSTALL_DIR="/usr/local/bin" sh /tmp/uv-install.sh \
59 + && rm -f /tmp/uv-install.sh \
60 + && uv --version
61 +
62 +# This timeout (in seconds) is necessary when installing some dependencies via uv since it's likely to time out
63 +# Reference: https://github.com/astral-sh/uv/pull/1694
64 +ENV UV_HTTP_TIMEOUT=500
65 +ENV UV_INDEX_STRATEGY="unsafe-best-match"
66 +# Use copy mode to avoid hardlink failures with Docker cache mounts
67 +ENV UV_LINK_MODE=copy
68 +# ccache directory - persisted across layer rebuilds via cache mounts.
69 +ENV CCACHE_DIR=/root/.cache/ccache
70 +ENV CCACHE_COMPILERCHECK=content
71 +# Empty by default so build steps fall back to $(nproc); CI can override.
72 +ARG max_jobs
73 +ENV MAX_JOBS=${max_jobs}
74 +
75 +# Install sccache if USE_SCCACHE is enabled (for release builds)
76 +ARG USE_SCCACHE
77 +ARG SCCACHE_DOWNLOAD_URL
78 +ARG SCCACHE_ENDPOINT
79 +ARG SCCACHE_BUCKET_NAME
80 +ARG SCCACHE_REGION_NAME
81 +ARG SCCACHE_S3_NO_CREDENTIALS
82 +RUN if [ "$USE_SCCACHE" = "1" ]; then \
83 + if command -v sccache >/dev/null 2>&1; then \
84 + echo "sccache already installed, skipping installation"; \
85 + sccache --version; \
86 + else \
87 + echo "Installing sccache..." \
88 + && SCCACHE_ARCH="x86_64" \
89 + && SCCACHE_VERSION="v0.8.1" \
90 + && SCCACHE_DL_URL="${SCCACHE_DOWNLOAD_URL:-https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl.tar.gz}" \
91 + && curl -L -o /tmp/sccache.tar.gz ${SCCACHE_DL_URL} \
92 + && tar -xzf /tmp/sccache.tar.gz -C /tmp \
93 + && mv /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \
94 + && chmod +x /usr/bin/sccache \
95 + && rm -rf /tmp/sccache.tar.gz /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl \
96 + && sccache --version; \
97 + fi; \
98 + fi
99 +
100 +# Set sccache environment variables only when USE_SCCACHE=1
101 +# This prevents S3 config from leaking into images when sccache is not used
102 +ARG USE_SCCACHE
103 +ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}}
104 +ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}}
105 +ENV SCCACHE_S3_NO_CREDENTIALS=${USE_SCCACHE:+${SCCACHE_S3_NO_CREDENTIALS}}
106 +ENV SCCACHE_IDLE_TIMEOUT=${USE_SCCACHE:+0}
107 +
108 +ARG COMMON_WORKDIR
109 +WORKDIR ${COMMON_WORKDIR}
110 +
111 +
112 +# -----------------------
113 +# vLLM fetch stages
114 +FROM base AS fetch_vllm_0
115 +ONBUILD COPY ./ vllm/
116 +FROM base AS fetch_vllm_1
117 +ARG VLLM_REPO
118 +ARG VLLM_BRANCH
119 +ONBUILD RUN git clone ${VLLM_REPO} \
120 + && cd vllm \
121 + && git fetch -v --prune -- origin ${VLLM_BRANCH} \
122 + && git checkout FETCH_HEAD \
123 + && if [ ${VLLM_REPO} != "https://github.com/vllm-project/vllm.git" ] ; then \
124 + git remote add upstream "https://github.com/vllm-project/vllm.git" \
125 + && git fetch upstream ; fi
126 +FROM fetch_vllm_${REMOTE_VLLM} AS fetch_vllm
127 +
128 +# Resolve the device-independent source version once for every downstream
129 +# artifact. setuptools-scm reads Git metadata for local/remote sources and the
130 +# archive metadata generated for canonical CI contexts.
131 +FROM fetch_vllm AS vllm-version
132 +ARG COMMON_WORKDIR
133 +RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
134 + cd ${COMMON_WORKDIR}/vllm \
135 + && uv pip install --system -r requirements/build/rust.txt \
136 + && python3 -c \
137 + "from setuptools_scm import get_version; print(get_version())" \
138 + > /vllm-version.txt
139 +
140 +# -----------------------
141 +# Rust toolchain inputs
142 +#
143 +# Keep these separate from Rust source inputs so Rust source-only changes do not
144 +# invalidate the long-lived ci_base image that carries the toolchain.
145 +FROM scratch AS rust_toolchain_input_0
146 +COPY rust-toolchain.toml /rust-toolchain-input/vllm/rust-toolchain.toml
147 +
148 +FROM base AS rust_toolchain_input_1
149 +ARG VLLM_REPO
150 +ARG VLLM_BRANCH
151 +RUN git clone --no-checkout --filter=blob:none ${VLLM_REPO} /rust-toolchain-input/vllm \
152 + && cd /rust-toolchain-input/vllm \
153 + && git fetch -v --prune -- origin ${VLLM_BRANCH} \
154 + && git sparse-checkout init --no-cone \
155 + && git sparse-checkout set \
156 + rust-toolchain.toml \
157 + && git checkout FETCH_HEAD
158 +
159 +FROM rust_toolchain_input_${REMOTE_VLLM} AS rust-toolchain-input
160 +
161 +# -----------------------
162 +# Rust build inputs
163 +#
164 +# REMOTE_VLLM=0: use only the local files that can affect Rust artifacts.
165 +# REMOTE_VLLM=1: fetch only those same files from the requested remote ref.
166 +FROM scratch AS rust_input_0
167 +COPY requirements/build/rust.txt /rust-input/vllm/requirements/build/rust.txt
168 +COPY rust/Cargo.lock rust/Cargo.toml /rust-input/vllm/rust/
169 +COPY rust/proto /rust-input/vllm/rust/proto
170 +COPY rust/src /rust-input/vllm/rust/src
171 +COPY rust-toolchain.toml /rust-input/vllm/rust-toolchain.toml
172 +COPY tools/build_rust.py /rust-input/vllm/tools/build_rust.py
173 +COPY build_rust.sh /rust-input/vllm/build_rust.sh
174 +
175 +FROM base AS rust_input_1
176 +ARG VLLM_REPO
177 +ARG VLLM_BRANCH
178 +RUN git clone --no-checkout --filter=blob:none ${VLLM_REPO} /rust-input/vllm \
179 + && cd /rust-input/vllm \
180 + && git fetch -v --prune -- origin ${VLLM_BRANCH} \
181 + && git sparse-checkout init --no-cone \
182 + && git sparse-checkout set \
183 + requirements/build/rust.txt \
184 + rust/Cargo.lock \
185 + rust/Cargo.toml \
186 + rust/proto/** \
187 + rust/src/** \
188 + rust-toolchain.toml \
189 + tools/build_rust.py \
190 + build_rust.sh \
191 + && git checkout FETCH_HEAD
192 +
193 +FROM rust_input_${REMOTE_VLLM} AS rust-input
194 +
195 +# -----------------------
196 +# Rust toolchain
197 +FROM base AS rust-toolchain
198 +
199 +ENV CARGO_HOME=/root/.cargo
200 +ENV RUSTUP_HOME=/root/.rustup
201 +ENV PATH=${CARGO_HOME}/bin:${PATH}
202 +
203 +RUN apt-get update -q -y && apt-get install -q -y --no-install-recommends \
204 + ca-certificates curl \
205 + && rm -rf /var/lib/apt/lists/*
206 +
207 +COPY --from=rust-toolchain-input /rust-toolchain-input/vllm/rust-toolchain.toml /tmp/rust-toolchain.toml
208 +RUN TOOLCHAIN="$(grep '^channel' /tmp/rust-toolchain.toml | sed 's/.*= *"\(.*\)"/\1/')" \
209 + && if ! command -v rustup >/dev/null 2>&1; then \
210 + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
211 + | sh -s -- -y --default-toolchain none; \
212 + fi \
213 + && rustup toolchain install "${TOOLCHAIN}" \
214 + && rustup default "${TOOLCHAIN}" \
215 + && rustc --version \
216 + && cargo --version
217 +
218 +# -----------------------
219 +# Rust build stage
220 +# Builds the `vllm-rs` frontend in a dedicated stage so the wheel build stages
221 +# don't need the rust toolchain.
222 +FROM rust-toolchain AS rust-build
223 +ARG COMMON_WORKDIR
224 +ARG USE_SCCACHE
225 +
226 +# Cap cargo parallelism to avoid exhausting the AMD CI host's open-file limit
227 +# (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise).
228 +ENV CARGO_BUILD_JOBS=4
229 +ENV CARGO_NET_RETRY=10
230 +ENV RUSTUP_MAX_RETRIES=10
231 +
232 +WORKDIR ${COMMON_WORKDIR}/vllm
233 +
234 +COPY --from=rust-input /rust-input/vllm/requirements/build/rust.txt requirements/build/rust.txt
235 +
236 +# BuildKit can run this stage in parallel with ROCm native builds. Keep Rust on
237 +# a separate local sccache daemon while sharing the same remote cache backend.
238 +ENV SCCACHE_SERVER_PORT=4227
239 +
240 +RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
241 + uv pip install --system -r requirements/build/rust.txt
242 +
243 +COPY --from=rust-input /rust-input/vllm/rust rust
244 +COPY --from=rust-input /rust-input/vllm/rust-toolchain.toml rust-toolchain.toml
245 +COPY --from=rust-input /rust-input/vllm/tools/build_rust.py tools/build_rust.py
246 +COPY --from=rust-input /rust-input/vllm/build_rust.sh build_rust.sh
247 +COPY --from=vllm-version /vllm-version.txt /tmp/vllm-version.txt
248 +
249 +# Build the release binary. Cargo's registry/git caches can be written by
250 +# concurrent BuildKit jobs on shared workers, so lock those cache mounts while
251 +# keeping the cache benefit. Do not cache target/, because stale target metadata
252 +# can outlive source updates across BuildKit cache reuse.
253 +RUN --mount=type=cache,id=vllm-rocm-cargo-registry,target=/root/.cargo/registry,sharing=locked \
254 + --mount=type=cache,id=vllm-rocm-cargo-git,target=/root/.cargo/git,sharing=locked \
255 + if [ "$USE_SCCACHE" = "1" ]; then \
256 + export RUSTC_WRAPPER=sccache \
257 + && sccache --show-stats; \
258 + fi \
259 + && export SETUPTOOLS_SCM_PRETEND_VERSION="$(cat /tmp/vllm-version.txt)" \
260 + && bash build_rust.sh \
261 + && test -x vllm/vllm-rs \
262 + && if [ "$USE_SCCACHE" = "1" ]; then \
263 + sccache --show-stats; \
264 + fi
265 +
266 +# -----------------------
267 +# Shared vLLM build dependencies
268 +#
269 +# Install requirements once, before bringing source-specific inputs into either
270 +# consumer. Native compilation and wheel packaging then share this expensive
271 +# layer while retaining their independent source cache boundaries.
272 +FROM base AS build_vllm_dependencies
273 +ARG COMMON_WORKDIR
274 +ENV VLLM_TARGET_DEVICE=rocm
275 +WORKDIR ${COMMON_WORKDIR}/vllm
276 +
277 +COPY --from=fetch_vllm \
278 + ${COMMON_WORKDIR}/vllm/requirements/common.txt \
279 + ${COMMON_WORKDIR}/vllm/requirements/rocm.txt \
280 + requirements/
281 +
282 +# Use constraints file to protect triton, pybind11, and torch dependencies.
283 +RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
284 + uv pip install --system -c /etc/rocm-constraints.txt -r requirements/rocm.txt
285 +
286 +# Fetch only the pinned ROCm Triton kernels package. Keeping this before the
287 +# vLLM source COPYs makes the download reusable when native sources change.
288 +FROM base AS rocm-triton-kernels
289 +ARG ROCM_TRITON_KERNELS_COMMIT
290 +ADD https://codeload.github.com/ROCm/triton/tar.gz/${ROCM_TRITON_KERNELS_COMMIT} \
291 + /tmp/rocm-triton.tar.gz
292 +RUN mkdir -p /opt/rocm-triton-kernels \
293 + && tar --extract --gzip --file /tmp/rocm-triton.tar.gz \
294 + --directory /opt/rocm-triton-kernels --strip-components=4 \
295 + --no-same-owner \
296 + "triton-${ROCM_TRITON_KERNELS_COMMIT}/python/triton_kernels/triton_kernels" \
297 + && test -f /opt/rocm-triton-kernels/__init__.py \
298 + && rm /tmp/rocm-triton.tar.gz
299 +
300 +# -----------------------
301 +# vLLM native build stages
302 +#
303 +# csrc-build intentionally copies only files that affect ROCm native extension
304 +# compilation. That keeps unrelated CI/test/docs edits from invalidating the
305 +# expensive HIP/C++ build layer.
306 +FROM build_vllm_dependencies AS csrc-build
307 +ARG ROCM_TRITON_KERNELS_COMMIT
308 +COPY --from=rocm-triton-kernels \
309 + /opt/rocm-triton-kernels /opt/rocm-triton-kernels
310 +ENV TRITON_KERNELS_SRC_DIR=/opt/rocm-triton-kernels
311 +
312 +# pyproject.toml is bind-mounted so it is not persisted in the csrc-build image,
313 +# but it still participates in the BuildKit cache key for this RUN step.
314 +COPY setup.py CMakeLists.txt ./
315 +COPY tools/build_rust.py tools/build_rust.py
316 +COPY cmake cmake/
317 +COPY csrc csrc/
318 +COPY vllm/envs.py vllm/envs.py
319 +COPY vllm/__init__.py vllm/__init__.py
320 +
321 +ENV SETUPTOOLS_SCM_PRETEND_VERSION="0.0.0+rocm.csrc.build"
322 +
323 +RUN --mount=type=bind,source=pyproject.toml,target=${COMMON_WORKDIR}/vllm/pyproject.toml \
324 + --mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
325 + grep -Fq "set(TRITON_KERNELS_TAG \"${ROCM_TRITON_KERNELS_COMMIT}\")" \
326 + cmake/external_projects/triton_kernels.cmake \
327 + && export CCACHE_BASEDIR="$PWD" \
328 + && echo "=== ccache stats before ROCm native build ===" \
329 + && (ccache --show-stats || true) \
330 + && (ccache --zero-stats || true) \
331 + && EFFECTIVE_MAX_JOBS="${MAX_JOBS:-$(nproc)}" \
332 + && echo "Building ROCm native extension wheel with MAX_JOBS=${EFFECTIVE_MAX_JOBS}" \
333 + && PYTHONDONTWRITEBYTECODE=1 LDFLAGS="-fuse-ld=mold" MAX_JOBS="${EFFECTIVE_MAX_JOBS}" python3 setup.py bdist_wheel --dist-dir=dist \
334 + && test -d dist \
335 + && ls dist/*.whl >/dev/null \
336 + && echo "=== ccache stats after ROCm native build ===" \
337 + && (ccache --show-stats || true)
338 +
339 +# Build the full vLLM ROCm wheel by reusing the native extension wheel from
340 +# csrc-build. This stage still rebuilds for Python/package changes, but skips
341 +# the expensive dependency installation and HIP/C++ compilation when their
342 +# respective inputs are unchanged.
343 +FROM build_vllm_dependencies AS build_vllm
344 +COPY --from=fetch_vllm ${COMMON_WORKDIR}/vllm ${COMMON_WORKDIR}/vllm
345 +COPY --from=csrc-build ${COMMON_WORKDIR}/vllm/dist /precompiled-wheels
346 +COPY --from=vllm-version /vllm-version.txt /tmp/vllm-version.txt
347 +
348 +# Drop the pre-built Rust artifacts into the source tree. setup.py detects
349 +# them and ships them as-is, skipping the local Rust build.
350 +COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/vllm-rs ${COMMON_WORKDIR}/vllm/vllm/vllm-rs
351 +COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/_rust_*.so ${COMMON_WORKDIR}/vllm/vllm/
352 +
353 +RUN cd "${COMMON_WORKDIR}/vllm" \
354 + && export SETUPTOOLS_SCM_PRETEND_VERSION="$(cat /tmp/vllm-version.txt)" \
355 + && export VLLM_USE_PRECOMPILED=1 \
356 + && export VLLM_PRECOMPILED_WHEEL_LOCATION="$(ls /precompiled-wheels/*.whl)" \
357 + && export VLLM_DOCKER_BUILD_CONTEXT=1 \
358 + && echo "Packaging vLLM ROCm wheel using precompiled extensions from ${VLLM_PRECOMPILED_WHEEL_LOCATION}" \
359 + && PYTHONDONTWRITEBYTECODE=1 python3 setup.py bdist_wheel --dist-dir=dist \
360 + && test -d dist \
361 + && ls dist/*.whl >/dev/null
362 +FROM scratch AS export_vllm
363 +ARG COMMON_WORKDIR
364 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/dist/*.whl /
365 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/requirements /requirements
366 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/benchmarks /benchmarks
367 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/tests /tests
368 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/examples /examples
369 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/scripts/benchmark_helion_kernels.py /scripts/benchmark_helion_kernels.py
370 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/tools/install_torchcodec_rocm.sh /tools/install_torchcodec_rocm.sh
371 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile /docker/Dockerfile
372 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.cpu /docker/Dockerfile.cpu
373 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm /docker/
374 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm_base /docker/Dockerfile.rocm_base
375 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/ci-rocm.hcl /docker/ci-rocm.hcl
376 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/docker-bake.hcl /docker/docker-bake.hcl
377 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/docker-bake-rocm.hcl /docker/docker-bake-rocm.hcl
378 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/.buildkite /.buildkite
379 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/pyproject.toml /pyproject.toml
380 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/rust /rust
381 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/rust-toolchain.toml /rust-toolchain.toml
382 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/vllm/v1 /vllm_v1
383 +
384 +# NIXL/UCX build stages
385 +FROM base AS build_nixl
386 +ARG NIXL_BRANCH="231d56753047c989062a5cb2ac703a1ad761c7d2"
387 +ARG NIXL_REPO="https://github.com/ai-dynamo/nixl.git"
388 +ARG UCX_BRANCH="96e58a16039f6d7d213bc967b8069238742c5194"
389 +ARG UCX_REPO="https://github.com/openucx/ucx.git"
390 +ENV UCX_HOME=/usr/local/ucx
391 +ENV NIXL_HOME=/usr/local/nixl
392 +
393 +# NIXL build system dependencies and RDMA support
394 +RUN apt-get -y update && apt-get -y install autoconf libtool pkg-config \
395 + libgrpc-dev \
396 + libgrpc++-dev \
397 + libprotobuf-dev \
398 + protobuf-compiler-grpc \
399 + libcpprest-dev \
400 + libaio-dev \
401 + librdmacm1 \
402 + librdmacm-dev \
403 + libibverbs1 \
404 + libibverbs-dev \
405 + ibverbs-utils \
406 + rdmacm-utils \
407 + ibverbs-providers \
408 + && rm -rf /var/lib/apt/lists/*
409 +
410 +RUN --mount=type=cache,target=/root/.cache/uv \
411 + uv pip install --system meson meson-python pyyaml types-PyYAML \
412 + auditwheel build patchelf pytest tomlkit "setuptools>=80.9.0"
413 +
414 +RUN --mount=type=cache,target=/root/.cache/ccache \
415 + cd /usr/local/src && \
416 + git clone ${UCX_REPO} && \
417 + cd ucx && \
418 + git checkout ${UCX_BRANCH} && \
419 + ./autogen.sh && \
420 + mkdir build && cd build && \
421 + CC="ccache gcc" CXX="ccache g++" \
422 + ../configure \
423 + --prefix=/usr/local/ucx \
424 + --enable-shared \
425 + --disable-static \
426 + --disable-doxygen-doc \
427 + --enable-optimizations \
428 + --enable-devel-headers \
429 + --with-rocm=${ROCM_PATH} \
430 + --with-verbs \
431 + --with-dm \
432 + --enable-mt && \
433 + make -j$(nproc) && \
434 + make install
435 +
436 +ENV PATH=/usr/local/ucx/bin:$PATH
437 +ENV LD_LIBRARY_PATH=${UCX_HOME}/lib:${LD_LIBRARY_PATH}
438 +
439 +RUN --mount=type=cache,target=/root/.cache/ccache \
440 + git clone ${NIXL_REPO} /opt/nixl && \
441 + cd /opt/nixl && \
442 + git checkout ${NIXL_BRANCH} && \
443 + CC="ccache gcc" CXX="ccache g++" \
444 + meson setup build --prefix=${NIXL_HOME} \
445 + -Ducx_path=${UCX_HOME} \
446 + -Dwheel_variant=rocm \
447 + -Dbuild_tests=false \
448 + -Dbuild_examples=false && \
449 + cd build && \
450 + ninja -j$(nproc) && \
451 + ninja install && \
452 + echo "${NIXL_HOME}/lib/$(uname -m)-linux-gnu" \
453 + > /etc/ld.so.conf.d/nixl.conf && \
454 + echo "${NIXL_HOME}/lib/$(uname -m)-linux-gnu/plugins" \
455 + >> /etc/ld.so.conf.d/nixl.conf && \
456 + ldconfig
457 +
458 +# Generate the ROCm NIXL wheel. Upstream's generic wheel helper detects CUDA,
459 +# so configure the ROCm wheel variant directly through Meson.
460 +# Exclude libcore and libpull from auditwheel: transitive dependencies
461 +# that are not shipped in the wheel and vary across base images.
462 +RUN cd /opt/nixl && \
463 + ./contrib/tomlutil.py --wheel-name nixl-rocm pyproject.toml && \
464 + CC="ccache gcc" CXX="ccache g++" \
465 + uv build --wheel --no-build-isolation --out-dir /tmp/nixl_wheels \
466 + --python ${PYTHON_VERSION} \
467 + -Csetup-args=-Ducx_path=${UCX_HOME} \
468 + -Csetup-args=-Dwheel_variant=rocm \
469 + -Csetup-args=-Dbuild_tests=false \
470 + -Csetup-args=-Dbuild_examples=false && \
471 + mkdir -p /tmp/nixl_wheels/repaired /app/install && \
472 + auditwheel repair \
473 + --exclude 'libamdhip64*' \
474 + --exclude 'libcore*' \
475 + --exclude 'libpull*' \
476 + /tmp/nixl_wheels/nixl_rocm*.whl \
477 + --plat manylinux_2_34_$(uname -m) \
478 + --wheel-dir /tmp/nixl_wheels/repaired && \
479 + ./contrib/wheel_add_ucx_plugins.py \
480 + --ucx-plugins-dir ${UCX_HOME}/lib/ucx \
481 + --nixl-plugins-dir ${NIXL_HOME}/lib/$(uname -m)-linux-gnu/plugins \
482 + /tmp/nixl_wheels/repaired/*.whl && \
483 + cp /tmp/nixl_wheels/repaired/*.whl /app/install
484 +
485 +# Fetch and verify pinned LMCache source.
486 +FROM base AS lmcache_source
487 +ARG LMCACHE_REPO="https://github.com/LMCache/LMCache.git"
488 +ARG LMCACHE_REF="140819c9d57a975dbc5678a6459a218e544cb58b"
489 +ARG LMCACHE_VERSION="0.5.3"
490 +
491 +# Remove NVIDIA-only dependencies and accept the release image's NumPy version.
492 +RUN printf '%s\n' "${LMCACHE_REF}" | grep -Eq '^[0-9a-f]{40}$' \
493 + && git clone --depth=1 --branch "v${LMCACHE_VERSION}" \
494 + "${LMCACHE_REPO}" /app/lmcache \
495 + && test "$(git -C /app/lmcache rev-parse HEAD)" = "${LMCACHE_REF}" \
496 + && test "$(grep -Ec '^(cufile-python|nvtx)([<=>[:space:]]|$)' \
497 + /app/lmcache/requirements/common.txt)" -eq 2 \
498 + && test "$(grep -Fxc 'numpy<=2.2.6' \
499 + /app/lmcache/requirements/common.txt)" -eq 1 \
500 + && sed -i -E \
501 + -e '/^(cufile-python|nvtx)([<=>[:space:]]|$)/d' \
502 + -e 's/^numpy<=2\.2\.6$/numpy<=2.3.5/' \
503 + /app/lmcache/requirements/common.txt \
504 + && rm -rf /app/lmcache/.git
505 +
506 +FROM base AS build_lmcache
507 +COPY --from=lmcache_source \
508 + /app/lmcache/requirements/build.txt /tmp/lmcache-build-requirements.txt
509 +RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
510 + uv pip install --system -r /tmp/lmcache-build-requirements.txt
511 +
512 +ARG LMCACHE_VERSION="0.5.3"
513 +ARG LMCACHE_ROCM_ARCH="gfx942;gfx950"
514 +ARG USE_SCCACHE
515 +
516 +COPY --from=lmcache_source /app/lmcache /app/lmcache
517 +WORKDIR /app/lmcache
518 +
519 +RUN --mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
520 + set -eu; \
521 + printf '%s\n' "${LMCACHE_ROCM_ARCH}" \
522 + | grep -Eq '^gfx[0-9a-z]+(;gfx[0-9a-z]+)*$'; \
523 + offload_flags="$(printf '%s' "${LMCACHE_ROCM_ARCH}" \
524 + | sed 's/;/ --offload-arch=/g; s/^/--offload-arch=/')"; \
525 + if [ "${USE_SCCACHE:-0}" = "1" ]; then \
526 + export HIP_CLANG_PATH=/opt/sccache-wrappers; \
527 + fi; \
528 + mkdir -p /app/install; \
529 + SETUPTOOLS_SCM_PRETEND_VERSION="${LMCACHE_VERSION}" \
530 + PYTORCH_ROCM_ARCH="${LMCACHE_ROCM_ARCH}" \
531 + HIPCC_COMPILE_FLAGS_APPEND="${offload_flags}" \
532 + BUILD_WITH_HIP=1 CXX=hipcc \
533 + python3 setup.py bdist_wheel --dist-dir=/app/install; \
534 + test "$(find /app/install -maxdepth 1 -name '*.whl' | wc -l)" -eq 1
535 +
536 +RUN --mount=type=tmpfs,target=/tmp/lmcache-wheel \
537 + set -eu; \
538 + python3 -m zipfile -e /app/install/*.whl /tmp/lmcache-wheel; \
539 + c_ops="$(find /tmp/lmcache-wheel -type f -name 'c_ops*.so')"; \
540 + test "$(find /tmp/lmcache-wheel -type f -name 'c_ops*.so' | wc -l)" -eq 1; \
541 + expected="$(printf '%s' "${LMCACHE_ROCM_ARCH}" | tr ';' '\n' | sort -u)"; \
542 + actual="$(llvm-objdump --offloading "${c_ops}" \
543 + | grep -oE 'gfx[0-9a-z]+' | sort -u)"; \
544 + if [ "${actual}" != "${expected}" ]; then \
545 + printf 'LMCache code objects mismatch\nexpected:\n%s\nactual:\n%s\n' \
546 + "${expected}" "${actual}" >&2; \
547 + exit 1; \
548 + fi
549 +
550 +# DeepEP build stage. ROCShmem is provided by TheRock SDK
551 +# ROCSHMEM_DIR set to the SDK install path so DeepEP finds the headers, etc.
552 +FROM base AS build_deepep
553 +ENV ROCSHMEM_DIR=${ROCM_PATH}
554 +ARG DEEPEP_BRANCH="0f63d3e9"
555 +ARG DEEPEP_REPO="https://github.com/ROCm/DeepEP.git"
556 +ARG DEEPEP_NIC="cx7"
557 +
558 +# Build DeepEP wheel. DeepEP looks for rocshmem at ROCSHMEM_DIR.
559 +# DeepEP only supports gfx942 and gfx950, so avoid gfx90a in the default list.
560 +# We pass --rocm-gfx942-fp8-fnuz-max 224 to align the DeepEP dispatch FP8
561 +# quantization bound with vLLM's own clamp
562 +# (vllm/model_executor/layers/quantization/utils/fp8_utils.py): 224 for E4M3FNUZ
563 +RUN --mount=type=cache,target=/root/.cache/ccache \
564 + export PYTORCH_ROCM_ARCH="gfx942;gfx950" \
565 + && git clone ${DEEPEP_REPO} \
566 + && cd DeepEP \
567 + && git checkout ${DEEPEP_BRANCH} \
568 + && LDFLAGS="-fuse-ld=mold" MAX_JOBS="${MAX_JOBS:-$(nproc)}" python3 setup.py --variant rocm --rocm-explicit-ctx --nic ${DEEPEP_NIC} --rocm-gfx942-fp8-fnuz-max 224 bdist_wheel --dist-dir=/app/deep_install
569 +
570 +# MoRI runtime dependencies live in Dockerfile.rocm so NIC backend changes do
571 +# not force users to rebuild the long-lived Dockerfile.rocm_base image.
572 +FROM base AS mori_base
573 +ARG NIC_BACKEND
574 +ARG AINIC_VERSION
575 +ARG UBUNTU_CODENAME
576 +RUN /bin/bash -lc 'set -euo pipefail; \
577 + \
578 + install_ainic() { \
579 + apt-get update && apt-get install -y --no-install-recommends ca-certificates curl gnupg apt-transport-https; \
580 + rm -rf /var/lib/apt/lists/*; \
581 + mkdir -p /etc/apt/keyrings; \
582 + curl -fsSL https://repo.radeon.com/rocm/rocm.gpg.key | gpg --dearmor > /etc/apt/keyrings/amdainic.gpg; \
583 + echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/amdainic.gpg] https://repo.radeon.com/amdainic/pensando/ubuntu/${AINIC_VERSION} ${UBUNTU_CODENAME} main" \
584 + > /etc/apt/sources.list.d/amdainic.list; \
585 + apt-get update && apt-get install -y --no-install-recommends \
586 + libionic-dev \
587 + ionic-common \
588 + ; \
589 + rm -rf /var/lib/apt/lists/*; \
590 + }; \
591 + \
592 + # NOTE: requires FW 235.2.86.0 and kernel drivers on the host: \
593 + # bnxt-en-dkms=1.10.3.235.2.86.0 bnxt-re-dkms=235.2.86.0 (from packages.broadcom.com PPA) \
594 + install_bnxt() { \
595 + install -m 0755 -d /etc/apt/keyrings; \
596 + curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/PackagesKey/public \
597 + -o /etc/apt/keyrings/broadcom-nic.asc; \
598 + chmod a+r /etc/apt/keyrings/broadcom-nic.asc; \
599 + echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/broadcom-nic.asc] https://packages.broadcom.com/artifactory/ethernet-nic-debian-public jammy main" \
600 + > /etc/apt/sources.list.d/broadcom-nic.list; \
601 + apt-get update && apt-get install -y --no-install-recommends \
602 + bnxt-rocelib=235.2.86.0 \
603 + ; \
604 + cp -a /usr/local/lib/x86_64-linux-gnu/libbnxt_re* /usr/local/lib/; \
605 + ldconfig; \
606 + rm -rf /var/lib/apt/lists/*; \
607 + }; \
608 + \
609 + echo "[MORI] Install MoRI proxy deps"; \
610 + pip install --quiet --ignore-installed blinker && \
611 + pip install --quiet quart msgpack aiohttp pyzmq; \
612 + echo "[MORI] NIC_BACKEND=${NIC_BACKEND}"; \
613 + \
614 + # NIC backend deps — mori auto-detects NIC at runtime (MORI_DEVICE_NIC env var override). \
615 + # Only vendor packages are installed here for dlopen; no compile-time flags needed. \
616 + case "${NIC_BACKEND}" in \
617 + none) ;; \
618 + all) install_ainic; install_bnxt ;; \
619 + ainic) install_ainic ;; \
620 + bnxt) install_bnxt ;; \
621 + *) echo "ERROR: unknown NIC_BACKEND=${NIC_BACKEND}. Use one of: none, ainic, bnxt, all"; exit 2 ;; \
622 + esac'
623 +
624 +# -----------------------
625 +# vLLM wheel release build stage (for building distributable wheels)
626 +# This stage pins dependencies to custom ROCm wheel versions and handles version detection
627 +FROM fetch_vllm AS build_vllm_wheel_release
628 +
629 +ARG COMMON_WORKDIR
630 +ARG ROCM_TRITON_KERNELS_COMMIT
631 +COPY --from=vllm-version /vllm-version.txt /tmp/vllm-version.txt
632 +COPY --from=rocm-triton-kernels \
633 + /opt/rocm-triton-kernels /opt/rocm-triton-kernels
634 +ENV TRITON_KERNELS_SRC_DIR=/opt/rocm-triton-kernels
635 +
636 +# Drop the pre-built Rust artifacts into the source tree. setup.py detects
637 +# them and ships them as-is, skipping the local Rust build.
638 +COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/vllm-rs ${COMMON_WORKDIR}/vllm/vllm/vllm-rs
639 +COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/_rust_*.so ${COMMON_WORKDIR}/vllm/vllm/
640 +
641 +# Create /install directory for custom wheels
642 +RUN mkdir -p /install
643 +
644 +# Copy custom ROCm wheels from docker/context if they exist
645 +# COPY ensures Docker cache is invalidated when wheels change
646 +# .keep file ensures directory always exists for COPY to work
647 +COPY docker/context/base-wheels/ /tmp/base-wheels/
648 +# This is how we know if we are building for a wheel release or not.
649 +# If there are not wheels found there, we are not building for a wheel release.
650 +# So we exit with an error. To skip this stage.
651 +RUN if [ -n "$(ls /tmp/base-wheels/*.whl 2>/dev/null)" ]; then \
652 + echo "Found custom wheels - copying to /install"; \
653 + cp /tmp/base-wheels/*.whl /install/ && \
654 + echo "Copied custom wheels:"; \
655 + ls -lh /install/; \
656 + else \
657 + echo "ERROR: No custom wheels found in docker/context/base-wheels/"; \
658 + echo "Wheel releases require pre-built ROCm wheels."; \
659 + exit 1; \
660 + fi
661 +
662 +# GIT_REPO_CHECK: Verify repo is clean and tags are available (for release builds)
663 +# This matches CUDA's Dockerfile behavior for proper version detection via setuptools_scm
664 +ARG GIT_REPO_CHECK=0
665 +RUN if [ "$GIT_REPO_CHECK" != "0" ]; then \
666 + echo "Running repository checks..."; \
667 + cd vllm && bash tools/check_repo.sh; \
668 + fi
669 +
670 +# Install the packaging helpers before modifying requirements/rocm.txt.
671 +RUN --mount=type=cache,target=/root/.cache/uv \
672 + grep -Fq "set(TRITON_KERNELS_TAG \"${ROCM_TRITON_KERNELS_COMMIT}\")" \
673 + vllm/cmake/external_projects/triton_kernels.cmake \
674 + && cd vllm \
675 + && uv pip install --system setuptools_scm regex
676 +
677 +# Fail if git-based package dependencies are found in requirements files
678 +# (uv doesn't handle git+ URLs well, and packages should be distributed on PyPI)
679 +# Extra notes: pip install is able to handle git+ URLs, but uv doesn't.
680 +RUN echo "Checking for git-based packages in requirements files..." \
681 + && echo "Checking common.txt for git-based packages:" \
682 + && if grep -q 'git+' ${COMMON_WORKDIR}/vllm/requirements/common.txt; then \
683 + echo "ERROR: Git-based packages found in common.txt:"; \
684 + grep 'git+' ${COMMON_WORKDIR}/vllm/requirements/common.txt; \
685 + echo "Please publish these packages to PyPI instead of using git dependencies."; \
686 + exit 1; \
687 + else \
688 + echo " ✓ No git-based packages found in common.txt"; \
689 + fi \
690 + && echo "Checking rocm.txt for git-based packages:" \
691 + && if grep -q 'git+' ${COMMON_WORKDIR}/vllm/requirements/rocm.txt; then \
692 + echo "ERROR: Git-based packages found in rocm.txt:"; \
693 + grep 'git+' ${COMMON_WORKDIR}/vllm/requirements/rocm.txt; \
694 + echo "Please publish these packages to PyPI instead of using git dependencies."; \
695 + exit 1; \
696 + else \
697 + echo " ✓ No git-based packages found in rocm.txt"; \
698 + fi \
699 + && echo "All requirements files are clean - no git-based packages found"
700 +
701 +# Pin vLLM dependencies to exact versions of custom ROCm wheels
702 +# This ensures 'pip install vllm' automatically installs correct torch/triton/torchvision/amdsmi
703 +COPY tools/vllm-rocm/pin_rocm_dependencies.py /tmp/pin_rocm_dependencies.py
704 +RUN echo "Pinning vLLM dependencies to custom wheel versions..." \
705 + && python3 /tmp/pin_rocm_dependencies.py /install ${COMMON_WORKDIR}/vllm/requirements/rocm.txt
706 +
707 +# Install dependencies using custom wheels from /install
708 +RUN --mount=type=cache,target=/root/.cache/uv \
709 + cd vllm \
710 + && echo "Building vLLM with custom wheels from /install" \
711 + && uv pip install --system --find-links /install -r requirements/rocm.txt
712 +
713 +# Build wheel using the shared source version to avoid dirty state from modified requirements/rocm.txt
714 +# (setup.py auto-detects ccache/sccache in PATH)
715 +RUN --mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
716 + cd vllm \
717 + && export CCACHE_BASEDIR="$PWD" \
718 + && export SETUPTOOLS_SCM_PRETEND_VERSION="$(cat /tmp/vllm-version.txt)" \
719 + && echo "Building wheel with version: ${SETUPTOOLS_SCM_PRETEND_VERSION}" \
720 + && MAX_JOBS="${MAX_JOBS:-$(nproc)}" python3 setup.py bdist_wheel --dist-dir=dist
721 +
722 +FROM scratch AS export_vllm_wheel_release
723 +ARG COMMON_WORKDIR
724 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/dist/*.whl /
725 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/requirements /requirements
726 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/benchmarks /benchmarks
727 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/tests /tests
728 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/examples /examples
729 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/scripts/benchmark_helion_kernels.py /scripts/benchmark_helion_kernels.py
730 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/tools/install_torchcodec_rocm.sh /tools/install_torchcodec_rocm.sh
731 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile /docker/Dockerfile
732 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.cpu /docker/Dockerfile.cpu
733 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm /docker/
734 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm_base /docker/Dockerfile.rocm_base
735 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/ci-rocm.hcl /docker/ci-rocm.hcl
736 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/docker-bake.hcl /docker/docker-bake.hcl
737 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/docker-bake-rocm.hcl /docker/docker-bake-rocm.hcl
738 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/.buildkite /.buildkite
739 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/pyproject.toml /pyproject.toml
740 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/rust /rust
741 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/rust-toolchain.toml /rust-toolchain.toml
742 +COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/vllm/v1 /vllm_v1
743 +
744 +# -----------------------
745 +# CI base image (Tier 1) - stable, rarely changing CI dependencies.
746 +# Per-PR test builds pull this as CI_BASE_IMAGE so the test stage only layers
747 +# in the vLLM artifacts for the current commit.
748 +FROM mori_base AS ci_base
749 +ARG COMMON_WORKDIR
750 +
751 +ENV CARGO_HOME=/root/.cargo
752 +ENV RUSTUP_HOME=/root/.rustup
753 +ENV PATH=${CARGO_HOME}/bin:${PATH}
754 +
755 +# Bake the Rust toolchain into ci_base so Rust build/test steps do not
756 +# need to fetch it on each per-commit image build.
757 +COPY --from=rust-toolchain /root/.cargo /root/.cargo
758 +COPY --from=rust-toolchain /root/.rustup /root/.rustup
759 +
760 +# Update rdma-core to support latest rocshmem.
761 +ARG DEEPEP_NIC
762 +RUN if [ "${DEEPEP_NIC}" = "cx7" ] || [ "${DEEPEP_NIC}" = "io" ]; then \
763 + git clone --branch v62.0 --depth 1 https://github.com/linux-rdma/rdma-core.git /tmp/rdma-core && \
764 + cd /tmp/rdma-core && \
765 + mkdir -p build && cd build && \
766 + cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr -DNO_MAN_PAGES=1 .. && \
767 + ninja && ninja install && ldconfig && rm -rf /tmp/rdma-core; \
768 +fi
769 +
770 +# Install NIXL + DeepEP wheels.
771 +RUN --mount=type=bind,from=build_nixl,src=/app/install,target=/nixl_install \
772 + --mount=type=bind,from=build_deepep,src=/app/deep_install,target=/deep_install \
773 + uv pip install --system /nixl_install/*.whl /deep_install/*.whl
774 +
775 +# RDMA userspace libraries plus FFmpeg dev libs needed by torchcodec.
776 +RUN apt-get update -q -y && apt-get install -q -y --no-install-recommends \
777 + librdmacm1 \
778 + libibverbs1 \
779 + ibverbs-providers \
780 + ibverbs-utils \
781 + util-linux \
782 + unzip \
783 + pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev \
784 + libswscale-dev libavdevice-dev libavfilter-dev libswresample-dev \
785 + && rm -rf /var/lib/apt/lists/*
786 +
787 +# Install torchcodec from source for ROCm/torch ABI compatibility.
788 +COPY tools/install_torchcodec_rocm.sh /tmp/install_torchcodec.sh
789 +RUN --mount=type=cache,target=/root/.cache/uv \
790 + --mount=type=cache,target=/root/.cache/pip \
791 + --mount=type=cache,target=/root/.cache/torchcodec-wheels \
792 + bash /tmp/install_torchcodec.sh \
793 + && rm /tmp/install_torchcodec.sh \
794 + && apt-get clean && rm -rf /var/lib/apt/lists/*
795 +
796 +# Pre-install shared ROCm runtime dependencies.
797 +COPY requirements/common.txt requirements/rocm.txt /tmp/ci-base-requirements/
798 +RUN --mount=type=cache,target=/root/.cache/uv \
799 + uv pip install --system -c /etc/rocm-constraints.txt \
800 + -r /tmp/ci-base-requirements/rocm.txt \
801 + && rm -rf /tmp/ci-base-requirements
802 +
803 +# Enable fast and less brittle model downloads in tests.
804 +ENV HF_XET_HIGH_PERFORMANCE=1
805 +ENV HF_HUB_DOWNLOAD_TIMEOUT=60
806 +
807 +# Keep torch.cuda.is_available() fork-safe (see vllm/env_override.py).
808 +ENV PYTORCH_NVML_BASED_CUDA_CHECK=1
809 +
810 +# Pre-install vLLM test dependencies.
811 +COPY requirements/test/rocm.txt /tmp/rocm-test-reqs.txt
812 +RUN --mount=type=cache,target=/root/.cache/uv \
813 + uv pip install --system -r /tmp/rocm-test-reqs.txt
814 +
815 +# Rebuild fastsafetensors from source so its C++ extension is compiled with
816 +# USE_ROCM and can detect libamdhip64.so at runtime.
817 +RUN --mount=type=cache,target=/root/.cache/pip \
818 + FASTSAFETENSORS_REQ="$(grep -E '^fastsafetensors(==| @ )' /tmp/rocm-test-reqs.txt | head -1)" \
819 + && test -n "${FASTSAFETENSORS_REQ}" \
820 + && python3 -m pip install --force-reinstall --no-deps \
821 + --no-binary fastsafetensors "${FASTSAFETENSORS_REQ}" \
822 + && rm /tmp/rocm-test-reqs.txt
823 +
824 +# Set MIOPEN ENVS to resolve performance regressions in MIOpen 3D convolution kernel.
825 +# See: https://github.com/pytorch/pytorch/issues/169857
826 +ENV MIOPEN_DEBUG_CONV_DIRECT=0
827 +ENV MIOPEN_DEBUG_CONV_GEMM=0
828 +
829 +# Use legacy IPC mode for HSA to avoid GPU memory pinning issues with UCX rocm_ipc.
830 +# See: https://github.com/ROCm/rocm-libraries/issues/6266
831 +ENV HSA_ENABLE_IPC_MODE_LEGACY=1
832 +ENV UCX_RMA_PPLN_ENABLE=y
833 +ENV UCX_ROCM_COPY_SIGPOOL_MAX_ELEMS=inf
834 +
835 +# ROCm profiler limits workaround.
836 +RUN echo "ROCTRACER_MAX_EVENTS=10000000" > ${COMMON_WORKDIR}/libkineto.conf
837 +ENV KINETO_CONFIG="${COMMON_WORKDIR}/libkineto.conf"
838 +
839 +# Install vllm_test_utils in ci_base for ci_base + wheel parity.
840 +COPY tests/vllm_test_utils /tmp/vllm_test_utils
841 +RUN --mount=type=cache,target=/root/.cache/uv \
842 + uv pip install --system /tmp/vllm_test_utils \
843 + && rm -rf /tmp/vllm_test_utils
844 +
845 +RUN --mount=type=bind,from=build_lmcache,src=/app/install,target=/lmcache_install \
846 + --mount=type=bind,source=requirements/test/rocm.txt,target=/tmp/lmcache-constraints.txt \
847 + --mount=type=cache,target=/root/.cache/uv \
848 + uv pip install --system --constraint /tmp/lmcache-constraints.txt \
849 + /lmcache_install/*.whl \
850 + && python3 -c "import lmcache, lmcache.c_ops; print('lmcache', lmcache.__version__)"
851 +
852 +# -----------------------
853 +# Test vLLM image (Tier 2) - vLLM-only layer on top of ci_base.
854 +FROM ${CI_BASE_IMAGE} AS test
855 +ARG COMMON_WORKDIR
856 +
857 +# Install the vLLM wheel (--no-deps: all deps already in ci_base).
858 +RUN --mount=type=bind,from=export_vllm,src=/,target=/install \
859 + --mount=type=cache,target=/root/.cache/uv \
860 + cd /install \
861 + && uv pip install --system --no-deps *.whl
862 +
863 +# Store the vLLM wheel in the image for python-only install tests.
864 +COPY --from=export_vllm /*.whl /opt/vllm-wheels/
865 +
866 +WORKDIR /vllm-workspace
867 +COPY --from=build_vllm ${COMMON_WORKDIR}/vllm /vllm-workspace
868 +
869 +# Copy in the v1 package (for python-only install test group).
870 +COPY --from=export_vllm /vllm_v1 /usr/local/lib/python${PYTHON_VERSION}/dist-packages/vllm/v1
871 +
872 +# Hide source under src/ so it won't shadow the installed package in tests.
873 +RUN mkdir src && mv vllm src/vllm
874 +
875 +# Catch GPU<->CPU syncs in execute_model/sample_tokens during tests.
876 +ENV VLLM_GPU_SYNC_CHECK=error
877 +
878 +# -----------------------
879 +# Final vLLM image
880 +FROM mori_base AS final_common
881 +
882 +RUN python3 -m pip install --upgrade pip && rm -rf /var/lib/apt/lists/*
883 +
884 +# Clean up sccache from release image (not needed at runtime)
885 +# This removes the binary and wrappers that may have been installed during build
886 +RUN rm -f /usr/bin/sccache || true \
887 + && rm -rf /opt/sccache-wrappers || true
888 +
889 +# Unset sccache environment variables for the release image
890 +# This prevents S3 bucket config from leaking into production images
891 +ENV SCCACHE_BUCKET=
892 +ENV SCCACHE_REGION=
893 +ENV SCCACHE_ENDPOINT=
894 +ENV SCCACHE_S3_NO_CREDENTIALS=
895 +ENV SCCACHE_IDLE_TIMEOUT=
896 +
897 +# Error related to odd state for numpy 1.20.3 where there is no METADATA etc, but an extra LICENSES_bundled.txt.
898 +# Manually remove it so that later steps of numpy upgrade can continue
899 +RUN case "$(which python3)" in \
900 + *"/opt/conda/envs/py_3.9"*) \
901 + rm -rf /opt/conda/envs/py_3.9/lib/python3.9/site-packages/numpy-1.20.3.dist-info/;; \
902 + *) ;; esac
903 +
904 +RUN --mount=type=cache,target=/root/.cache/uv \
905 + uv pip install --system --upgrade huggingface-hub[cli]
906 +
907 +# Install vLLM using uv (inherited from base stage)
908 +# Note: No -U flag to avoid upgrading PyTorch ROCm to CUDA version
909 +RUN --mount=type=bind,from=export_vllm,src=/,target=/install \
910 + --mount=type=cache,target=/root/.cache/uv \
911 + cd /install \
912 + && uv pip install --system -c /etc/rocm-constraints.txt -r requirements/rocm.txt \
913 + && pip uninstall -y vllm \
914 + && uv pip install --system -c /etc/rocm-constraints.txt *.whl
915 +
916 +# Install NIXL ROCm wheel
917 +RUN --mount=type=bind,from=build_nixl,src=/app/install,target=/nixl_install \
918 + uv pip install --system /nixl_install/*.whl
919 +
920 +# Recompute the base's triton fingerprint to detect resolver interference.
921 +RUN EXPECTED=$(grep '^TRITON_SHA256: ' /app/versions.txt | cut -d' ' -f2) \
922 + && ACTUAL=$(find $(python3 -c 'import triton, os; print(os.path.dirname(triton.__file__))') \
923 + -type f \( -name '*.py' -o -name '*.so' \) | sort | xargs sha256sum | sha256sum | cut -d' ' -f1) \
924 + && echo "triton sha256 expected=${EXPECTED} actual=${ACTUAL}" \
925 + && test -n "${EXPECTED}" \
926 + && test "${EXPECTED}" = "${ACTUAL}" \
927 + && python3 -c "import torch; assert torch.version.hip, f'non-ROCm torch: {torch.__version__}'; print(f'torch={torch.__version__}')"
928 +
929 +# Recompute the base's pybind11 fingerprint to detect resolver interference.
930 +RUN EXPECTED=$(grep '^PYBIND11_SHA256: ' /app/versions.txt | cut -d' ' -f2) \
931 + && EXPECTED_ABI=$(grep '^PYBIND11_INTERNALS_VERSION: ' /app/versions.txt | cut -d' ' -f2) \
932 + && INC=$(python3 -c 'import pybind11; print(pybind11.get_include())') \
933 + && ACTUAL=$(find "${INC}" -type f -name '*.h' | sort | xargs sha256sum | sha256sum | cut -d' ' -f1) \
934 + && ACTUAL_ABI=$(grep -rhE '^#[[:space:]]*define PYBIND11_INTERNALS_VERSION' "${INC}" | awk '{print $NF}') \
935 + && echo "pybind11 $(pip show pybind11 | awk '/^Version:/ {print $2}')" \
936 + "sha256 expected=${EXPECTED} actual=${ACTUAL}" \
937 + "internals expected=${EXPECTED_ABI} actual=${ACTUAL_ABI}" \
938 + && test -n "${EXPECTED}" \
939 + && test "${EXPECTED}" = "${ACTUAL}" \
940 + && test "${EXPECTED_ABI}" = "${ACTUAL_ABI}"
941 +
942 +ARG COMMON_WORKDIR
943 +ARG BASE_IMAGE
944 +ARG NIC_BACKEND
945 +ARG AINIC_VERSION
946 +
947 +# Copy over the benchmark scripts as well
948 +COPY --from=export_vllm /benchmarks ${COMMON_WORKDIR}/vllm/benchmarks
949 +COPY --from=export_vllm /examples ${COMMON_WORKDIR}/vllm/examples
950 +COPY --from=export_vllm /docker ${COMMON_WORKDIR}/vllm/docker
951 +
952 +# Use legacy IPC mode for HSA to avoid GPU memory pinning issues with UCX rocm_ipc
953 +# See: https://github.com/ROCm/rocm-libraries/issues/6266
954 +ENV HSA_ENABLE_IPC_MODE_LEGACY=1
955 +ENV UCX_RMA_PPLN_ENABLE=y
956 +ENV UCX_ROCM_COPY_SIGPOOL_MAX_ELEMS=inf
957 +
958 +ENV TOKENIZERS_PARALLELISM=false
959 +
960 +# ENV that can improve safe tensor loading, and end-to-end time
961 +ENV SAFETENSORS_FAST_GPU=1
962 +
963 +# Performance environment variable.
964 +ENV HIP_FORCE_DEV_KERNARG=1
965 +
966 +# Keep torch.cuda.is_available() fork-safe (see vllm/env_override.py).
967 +ENV PYTORCH_NVML_BASED_CUDA_CHECK=1
968 +
969 +# Workaround for ROCm profiler limits
970 +RUN echo "ROCTRACER_MAX_EVENTS=10000000" > ${COMMON_WORKDIR}/libkineto.conf
971 +ENV KINETO_CONFIG="${COMMON_WORKDIR}/libkineto.conf"
972 +RUN echo "VLLM_BASE_IMAGE=${BASE_IMAGE}" >> ${COMMON_WORKDIR}/versions.txt \
973 + && echo "MORI_NIC_BACKEND=${NIC_BACKEND}" >> ${COMMON_WORKDIR}/versions.txt \
974 + && echo "AINIC_VERSION=${AINIC_VERSION}" >> ${COMMON_WORKDIR}/versions.txt
975 +
976 +CMD ["/bin/bash"]
977 +
978 +FROM final_common AS final_lmcache_false
979 +
980 +FROM final_common AS final_lmcache_true
981 +RUN --mount=type=bind,from=build_lmcache,src=/app/install,target=/lmcache_install \
982 + --mount=type=cache,target=/root/.cache/uv \
983 + uv pip install --system /lmcache_install/*.whl \
984 + && test "$(python3 -c 'import numpy; print(numpy.__version__)')" = "2.3.5" \
985 + && uv pip check --system \
986 + && python3 -c "import lmcache, lmcache.c_ops; print('lmcache', lmcache.__version__)"
987 +
988 +FROM final_lmcache_${INSTALL_LMCACHE} AS final
989 +
990 +#Set entrypoint for vllm-openai official images
991 +FROM final AS vllm-openai
992 +ENTRYPOINT ["vllm", "serve"]
docker/Dockerfile.rock_base new
+360
@@ -0,0 +1,360 @@
1 +ARG BASE_IMAGE=ubuntu:22.04
2 +ARG PYTHON_VERSION=3.12
3 +ARG TORCH_VERSION=2.12.0+rocm7.14.0
4 +ARG TORCHVISION_VERSION=0.27.0+rocm7.14.0
5 +ARG TORCHAUDIO_VERSION=2.11.0+rocm7.14.0
6 +ARG TRITON_BRANCH="f0b55c07da61c71775bef6d1a15ebf846430ac75" # release/internal/3.7.x as of 08/13
7 +ARG TRITON_REPO="https://github.com/ROCm/triton.git"
8 +ARG FA_BRANCH="0e60e394"
9 +ARG FA_REPO="https://github.com/Dao-AILab/flash-attention.git"
10 +ARG AITER_BRANCH="v0.1.19"
11 +ARG AITER_REPO="https://github.com/ROCm/aiter.git"
12 +ARG MORI_BRANCH="f95cd5e0ca7b730f92f9ffdfb358484d6965d9f7" # TheRock compatible v1.1.0
13 +ARG MORI_REPO="https://github.com/ROCm/mori.git"
14 +
15 +
16 +# TheRock configuration
17 +ARG SITE_PACKAGES=/usr/local/lib/python${PYTHON_VERSION}/dist-packages
18 +ARG ROCM_RELEASE_WHEELS_MULTIARCH_URL="https://repo.amd.com/rocm/whl-multi-arch/" # For pre-built GPU images, packages, etc.
19 +ARG ROCM_NIGHTLY_WHEELS_MULTIARCH_URL="https://rocm.nightlies.amd.com/whl-multi-arch/" # For torch, triton, etc. wheels with latest fixes.
20 +ARG ROCM_SDK_VERSION=7.14.0
21 +
22 +# Build configuration
23 +ARG PYTORCH_ROCM_ARCH="gfx90a;gfx942;gfx950;gfx1100;gfx1101;gfx1200;gfx1201;gfx1150;gfx1151"
24 +ARG AITER_ROCM_ARCH="gfx942;gfx950"
25 +
26 +# Sccache configuration (only used in release pipeline)
27 +ARG USE_SCCACHE
28 +ARG SCCACHE_DOWNLOAD_URL
29 +ARG SCCACHE_ENDPOINT
30 +ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
31 +ARG SCCACHE_REGION_NAME=us-west-2
32 +ARG SCCACHE_S3_NO_CREDENTIALS=0
33 +
34 +FROM ${BASE_IMAGE} AS base
35 +
36 +ARG PYTORCH_ROCM_ARCH
37 +ENV PYTORCH_ROCM_ARCH="${PYTORCH_ROCM_ARCH}"
38 +ARG AITER_ROCM_ARCH
39 +ENV AITER_ROCM_ARCH="${AITER_ROCM_ARCH}"
40 +
41 +ARG SITE_PACKAGES
42 +ENV SITE_PACKAGES=${SITE_PACKAGES}
43 +ENV SDK_DEV="$SITE_PACKAGES/_rocm_sdk_devel" \
44 + SDK_CORE="$SITE_PACKAGES/_rocm_sdk_core"
45 +ENV ROCM_PATH="$SDK_DEV" \
46 + ROCM_HOME="$SDK_DEV" \
47 + HIP_PATH="$SDK_DEV" \
48 + HIP_CLANG_PATH="$SDK_DEV/lib/llvm/bin" \
49 + HIP_DEVICE_LIB_PATH="$SDK_CORE/lib/llvm/amdgcn/bitcode"
50 +ENV LD_LIBRARY_PATH="$SDK_DEV/lib:$SDK_DEV/lib/rocm_sysdeps/lib:$SDK_CORE/lib:$SDK_CORE/lib/rocm_sysdeps/lib"
51 +ENV PATH="$SDK_DEV/bin:$SDK_DEV/lib/llvm/bin:$SDK_CORE/bin:$PATH"
52 +
53 +# Required for RCCL in ROCm7.1
54 +ENV HSA_NO_SCRATCH_RECLAIM=1
55 +
56 +ARG PYTHON_VERSION
57 +ENV PYTHON_VERSION=${PYTHON_VERSION}
58 +
59 +RUN mkdir -p /app
60 +WORKDIR /app
61 +ENV DEBIAN_FRONTEND=noninteractive
62 +
63 +# Install Python and other dependencies
64 +RUN apt-get update -y \
65 + && apt-get install -y software-properties-common build-essential git curl sudo vim less libgfortran5 libopenmpi-dev libpci-dev liblzma-dev pkg-config libdrm-dev libnuma-dev kmod \
66 + && for i in 1 2 3; do \
67 + add-apt-repository -y ppa:deadsnakes/ppa && break || \
68 + { echo "Attempt $i failed, retrying in 5s..."; sleep 5; }; \
69 + done \
70 + && apt-get update -y \
71 + && apt-get install -y python${PYTHON_VERSION} python${PYTHON_VERSION}-dev python${PYTHON_VERSION}-venv \
72 + python${PYTHON_VERSION}-lib2to3 python-is-python3 \
73 + && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python${PYTHON_VERSION} 1 \
74 + && update-alternatives --set python3 /usr/bin/python${PYTHON_VERSION} \
75 + && ln -sf /usr/bin/python${PYTHON_VERSION}-config /usr/bin/python3-config \
76 + && curl -sS https://bootstrap.pypa.io/get-pip.py | python${PYTHON_VERSION} \
77 + && python3 --version && python3 -m pip --version
78 +
79 +RUN pip install -U packaging 'cmake<4' ninja wheel 'setuptools<80' pybind11==3.0.4 Cython
80 +RUN apt-get update && apt-get install -y libjpeg-dev libsox-dev libsox-fmt-all sox && rm -rf /var/lib/apt/lists/*
81 +
82 +# Install ROCm SDK via TheRock
83 +ARG ROCM_RELEASE_WHEELS_MULTIARCH_URL
84 +ARG ROCM_NIGHTLY_WHEELS_MULTIARCH_URL
85 +ARG ROCM_SDK_VERSION
86 +RUN pip install --index-url ${ROCM_RELEASE_WHEELS_MULTIARCH_URL} \
87 + --extra-index-url ${ROCM_NIGHTLY_WHEELS_MULTIARCH_URL} \
88 + "rocm[libraries,devel]${ROCM_SDK_VERSION:+==${ROCM_SDK_VERSION}}" \
89 + && rocm-sdk init
90 +
91 +# Install PyTorch wheels (nightly for latest torch, release as fallback)
92 +ARG TORCH_VERSION
93 +ARG TORCHAUDIO_VERSION
94 +ARG TORCHVISION_VERSION
95 +RUN pip install \
96 + --index-url ${ROCM_RELEASE_WHEELS_MULTIARCH_URL} \
97 + --extra-index-url ${ROCM_NIGHTLY_WHEELS_MULTIARCH_URL} \
98 + "torch==${TORCH_VERSION}" \
99 + "torchaudio==${TORCHAUDIO_VERSION}" \
100 + "torchvision==${TORCHVISION_VERSION}"
101 +RUN python3 -c "import torch; print(f'torch={torch.__version__}, hip={torch.version.hip}')"
102 +
103 +# Install the AMD-compiled device kernels corresponding to PYTORCH_ROCM_ARCH:
104 +
105 +# Possible values that can be in PYTORCH_ROCM_ARCH:
106 +#
107 +# gfx90a (MI210/250), gfx942 (MI300), gfx950 (MI350), gfx1100 (7900XTX),
108 +# gfx1101 (7800XT), gfx1200 (9070XT), gfx1201 (9070), gfx1150/1151 (Strix APU)
109 +
110 +# For each arch in PYTORCH_ROCM_ARCH, install the precompiled GPU code that
111 +# PyTorch needs to run on that specific chip.
112 +SHELL ["/bin/bash", "-c"]
113 +RUN TORCH_VER=$(python3 -c "import torch; print(torch.__version__)") \
114 + && for arch in $(echo "${PYTORCH_ROCM_ARCH}" | tr ';' ' '); do \
115 + echo "Installing device packages for ${arch}" \
116 + && pip install --index-url ${ROCM_RELEASE_WHEELS_MULTIARCH_URL} \
117 + --extra-index-url ${ROCM_NIGHTLY_WHEELS_MULTIARCH_URL} \
118 + amd-torch-device-${arch}==${TORCH_VER} \
119 + rocm-sdk-device-${arch}==${ROCM_SDK_VERSION}; \
120 + done
121 +
122 +# Remove gfx90a xnack kpacks (ASAN artifacts that cause hipErrorInvalidImage on MI250)
123 +RUN rm -f "${SITE_PACKAGES}/torch/.kpack/torch_gfx90a:xnack+.kpack" \
124 + "${SITE_PACKAGES}/torch/.kpack/torch_gfx90a:xnack-.kpack"
125 +
126 +RUN cd $SITE_PACKAGES/_rocm_sdk_core/share/amd_smi && pip install .
127 +ENV PYTHONPATH=$SITE_PACKAGES/_rocm_sdk_core/share/amd_smi
128 +
129 +# TheRock runtime fixes
130 +RUN if [ -f "${SITE_PACKAGES}/rocm_sdk/__init__.py" ]; then \
131 + sed -i 's/rtld_global: bool = True/rtld_global: bool = False/g' "${SITE_PACKAGES}/rocm_sdk/__init__.py"; \
132 + fi \
133 + && if [ -f "${SITE_PACKAGES}/_rocm_sdk_core/lib/librocm_smi64.so.1" ] \
134 + && [ ! -e "${ROCM_PATH}/lib/librocm_smi64.so.7" ]; then \
135 + ln -sfn "${SITE_PACKAGES}/_rocm_sdk_core/lib/librocm_smi64.so.1" "${ROCM_PATH}/lib/librocm_smi64.so.7"; \
136 + fi \
137 + && printf '%s\n%s\n' "${ROCM_PATH}/lib" "${SITE_PACKAGES}/_rocm_sdk_core/lib" > /etc/ld.so.conf.d/rocm-pip.conf \
138 + && for f in ${SITE_PACKAGES}/_rocm_sdk_core/lib/libamdhip64.so*; do \
139 + bn=$(basename "$f"); \
140 + if [ -f "${ROCM_PATH}/lib/${bn}" ] && [ -f "$f" ] && [ ! -L "$f" ]; then \
141 + rm -f "$f"; \
142 + ln -sfn "${ROCM_PATH}/lib/${bn}" "$f"; \
143 + fi; \
144 + done \
145 + && ldconfig
146 +
147 +# Install sccache if USE_SCCACHE is enabled (for release builds)
148 +ARG USE_SCCACHE
149 +ARG SCCACHE_DOWNLOAD_URL
150 +ARG SCCACHE_ENDPOINT
151 +ARG SCCACHE_BUCKET_NAME
152 +ARG SCCACHE_REGION_NAME
153 +ARG SCCACHE_S3_NO_CREDENTIALS
154 +RUN if [ "$USE_SCCACHE" = "1" ]; then \
155 + echo "Installing sccache..." \
156 + && SCCACHE_ARCH="x86_64" \
157 + && SCCACHE_VERSION="v0.8.1" \
158 + && SCCACHE_DL_URL="${SCCACHE_DOWNLOAD_URL:-https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl.tar.gz}" \
159 + && curl -L -o /tmp/sccache.tar.gz ${SCCACHE_DL_URL} \
160 + && tar -xzf /tmp/sccache.tar.gz -C /tmp \
161 + && mv /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \
162 + && chmod +x /usr/bin/sccache \
163 + && rm -rf /tmp/sccache.tar.gz /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl \
164 + && sccache --version; \
165 + fi
166 +
167 +# Setup sccache for HIP compilation via HIP_CLANG_PATH
168 +# This creates wrapper scripts in a separate directory and points HIP to use them
169 +# This avoids modifying the original ROCm binaries which can break detection
170 +# NOTE: HIP_CLANG_PATH is NOT set as ENV to avoid affecting downstream images (Dockerfile.rocm)
171 +# Instead, each build stage should export HIP_CLANG_PATH=/opt/sccache-wrappers if USE_SCCACHE=1
172 +RUN if [ "$USE_SCCACHE" = "1" ]; then \
173 + echo "Setting up sccache wrappers for HIP compilation..." \
174 + && mkdir -p /opt/sccache-wrappers \
175 + && printf '#!/bin/bash\nexec sccache %s/lib/llvm/bin/clang++ "$@"\n' "${ROCM_PATH}" > /opt/sccache-wrappers/clang++ \
176 + && chmod +x /opt/sccache-wrappers/clang++ \
177 + && printf '#!/bin/bash\nexec sccache %s/lib/llvm/bin/clang "$@"\n' "${ROCM_PATH}" > /opt/sccache-wrappers/clang \
178 + && chmod +x /opt/sccache-wrappers/clang \
179 + && echo "sccache wrappers created in /opt/sccache-wrappers"; \
180 + fi
181 +
182 +ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}}
183 +ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}}
184 +ENV SCCACHE_S3_NO_CREDENTIALS=${USE_SCCACHE:+${SCCACHE_S3_NO_CREDENTIALS}}
185 +ENV SCCACHE_IDLE_TIMEOUT=${USE_SCCACHE:+0}
186 +
187 +
188 +###
189 +### Triton Build
190 +###
191 +FROM base AS build_triton
192 +ARG TRITON_BRANCH
193 +ARG TRITON_REPO
194 +RUN git clone ${TRITON_REPO}
195 +RUN cd triton \
196 + && git checkout ${TRITON_BRANCH} \
197 + && if [ ! -f setup.py ]; then cd python; fi \
198 + && python3 setup.py bdist_wheel --dist-dir=dist \
199 + && mkdir -p /app/install && cp dist/*.whl /app/install
200 +
201 +
202 +###
203 +### MORI Build
204 +###
205 +FROM base AS build_mori
206 +ARG MORI_BRANCH
207 +ARG MORI_REPO
208 +RUN git clone ${MORI_REPO}
209 +RUN cd mori \
210 + && git checkout ${MORI_BRANCH} \
211 + && git submodule update --init --recursive \
212 + && ln -sfn ${ROCM_PATH} /opt/rocm \
213 + && mkdir -p /usr/lib64 && ln -sf /usr/lib/x86_64-linux-gnu/libc.so /usr/lib64/libc.so \
214 + && python3 setup.py bdist_wheel --dist-dir=dist && ls /app/mori/dist/*.whl
215 +RUN mkdir -p /app/install && cp /app/mori/dist/*.whl /app/install
216 +
217 +###
218 +### FlashAttention Build
219 +###
220 +FROM base AS build_fa
221 +ARG FA_BRANCH
222 +ARG FA_REPO
223 +ARG USE_SCCACHE
224 +RUN git clone ${FA_REPO}
225 +RUN cd flash-attention \
226 + && git checkout ${FA_BRANCH} \
227 + && git submodule update --init \
228 + && if [ "$USE_SCCACHE" = "1" ]; then \
229 + export HIP_CLANG_PATH=/opt/sccache-wrappers \
230 + && sccache --show-stats; \
231 + fi \
232 + && GPU_ARCHS=$(echo ${PYTORCH_ROCM_ARCH} | sed -e 's/;gfx1[0-9]\{3\}//g') python3 setup.py bdist_wheel --dist-dir=dist \
233 + && if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi
234 +RUN mkdir -p /app/install && cp /app/flash-attention/dist/*.whl /app/install
235 +
236 +
237 +###
238 +### AITER Build
239 +###
240 +FROM base AS build_aiter
241 +ARG AITER_BRANCH
242 +ARG AITER_REPO
243 +ARG USE_SCCACHE
244 +RUN git clone --recursive --branch ${AITER_BRANCH} ${AITER_REPO}
245 +RUN cd aiter \
246 + && git submodule update --init --recursive \
247 + && pip install -r requirements.txt
248 +# AITER_USE_SYSTEM_TRITON keeps setup.py off the index triton, which would
249 +# otherwise displace the one we built.
250 +RUN pip install pyyaml && cd aiter \
251 + && if [ "$USE_SCCACHE" = "1" ]; then \
252 + export HIP_CLANG_PATH=/opt/sccache-wrappers \
253 + && sccache --show-stats; \
254 + fi \
255 + && PREBUILD_KERNELS=1 AITER_USE_SYSTEM_TRITON=1 GPU_ARCHS=${AITER_ROCM_ARCH} python3 setup.py bdist_wheel --dist-dir=dist \
256 + && if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi \
257 + && ls /app/aiter/dist/*.whl
258 +RUN mkdir -p /app/install && cp /app/aiter/dist/*.whl /app/install
259 +
260 +
261 +###
262 +### Final Build
263 +###
264 +
265 +# Wheel release stage -
266 +# only includes dependencies used by wheel release pipeline
267 +FROM base AS debs_wheel_release
268 +RUN mkdir /app/debs
269 +RUN --mount=type=bind,from=build_triton,src=/app/install/,target=/install \
270 + cp /install/*.whl /app/debs
271 +RUN --mount=type=bind,from=build_fa,src=/app/install/,target=/install \
272 + cp /install/*.whl /app/debs
273 +RUN --mount=type=bind,from=build_aiter,src=/app/install/,target=/install \
274 + cp /install/*.whl /app/debs
275 +
276 +FROM base AS debs
277 +RUN mkdir /app/debs
278 +RUN --mount=type=bind,from=build_triton,src=/app/install/,target=/install \
279 + cp /install/*.whl /app/debs
280 +RUN --mount=type=bind,from=build_fa,src=/app/install/,target=/install \
281 + cp /install/*.whl /app/debs
282 +RUN --mount=type=bind,from=build_aiter,src=/app/install/,target=/install \
283 + cp /install/*.whl /app/debs
284 +RUN --mount=type=bind,from=build_mori,src=/app/install/,target=/install \
285 + cp /install/*.whl /app/debs
286 +
287 +FROM base AS final
288 +
289 +# Remove the torch wheel's Requires-Dist: triton entry in METADATA and the SHA
290 +# hash (its optional) from RECORD. These will cause Python to reinstall
291 +# Triton and a constraints file can't fix it. This doesn't exist for source
292 +# builds, so it wasn't needed there.
293 +RUN TORCH_DIST_INFO=$(ls -d ${SITE_PACKAGES}/torch-*.dist-info) \
294 + && grep -q '^Requires-Dist: triton' "$TORCH_DIST_INFO/METADATA" \
295 + && sed -i '/^Requires-Dist: triton/d' "$TORCH_DIST_INFO/METADATA" \
296 + && sed -i "s|^\(${TORCH_DIST_INFO##*/}/METADATA\),.*|\1,,|" "$TORCH_DIST_INFO/RECORD"
297 +
298 +# Other wheels first, so they resolve against the index triton. Ours goes in last
299 +# with --no-deps, where it can't pull the resolver anywhere.
300 +RUN --mount=type=bind,from=debs,src=/app/debs,target=/install \
301 + pip install $(ls /install/*.whl | grep -v '/triton-') \
302 + && pip install --no-deps --force-reinstall /install/triton-*.whl \
303 + # With the pin gone this must be clean, so any complaint is real.
304 + && ! pip check 2>&1 | grep -iE '^(torch|triton) ' \
305 + # Create a constraints file to protect the versions we need, especially
306 + # triton, requirements will try to reinstall repeatedly.
307 + && pip list --format=freeze \
308 + | grep -E '^(torch|triton|torchaudio|torchvision|pybind11)==' > /etc/rocm-constraints.txt \
309 + && echo "ROCm constraints:" && cat /etc/rocm-constraints.txt \
310 + && test "$(wc -l < /etc/rocm-constraints.txt)" -eq 5 \
311 + && grep -q '^pybind11==3\.0\.' /etc/rocm-constraints.txt \
312 + && python3 -c "import torch; assert torch.version.hip, f'non-ROCm torch: {torch.__version__}'; print(f'torch={torch.__version__}')" \
313 + && python3 -c "import triton; print(f'triton={triton.__version__}')" \
314 + && pip list 2>/dev/null | grep -iE '^(torch|triton) '
315 +
316 +ARG BASE_IMAGE
317 +ARG PYTHON_VERSION
318 +ARG ROCM_SDK_VERSION
319 +ARG TORCH_VERSION
320 +ARG TORCHAUDIO_VERSION
321 +ARG TORCHVISION_VERSION
322 +ARG PYTORCH_ROCM_ARCH
323 +ARG AITER_ROCM_ARCH
324 +ARG TRITON_BRANCH
325 +ARG TRITON_REPO
326 +ARG FA_BRANCH
327 +ARG FA_REPO
328 +ARG AITER_BRANCH
329 +ARG AITER_REPO
330 +ARG MORI_BRANCH
331 +ARG MORI_REPO
332 +# Record hashes for Triton and pybind11 so we can verify later.
333 +RUN echo "BASE_IMAGE: ${BASE_IMAGE}" > /app/versions.txt \
334 + && echo "PYTHON_VERSION: ${PYTHON_VERSION}" >> /app/versions.txt \
335 + && echo "ROCM_SDK_VERSION: ${ROCM_SDK_VERSION}" >> /app/versions.txt \
336 + && echo "TORCH_VERSION: ${TORCH_VERSION}" >> /app/versions.txt \
337 + && echo "TORCHAUDIO_VERSION: ${TORCHAUDIO_VERSION}" >> /app/versions.txt \
338 + && echo "TORCHVISION_VERSION: ${TORCHVISION_VERSION}" >> /app/versions.txt \
339 + && echo "PYTORCH_ROCM_ARCH: ${PYTORCH_ROCM_ARCH}" >> /app/versions.txt \
340 + && echo "AITER_ROCM_ARCH: ${AITER_ROCM_ARCH}" >> /app/versions.txt \
341 + && echo "TRITON_BRANCH: ${TRITON_BRANCH}" >> /app/versions.txt \
342 + && echo "TRITON_REPO: ${TRITON_REPO}" >> /app/versions.txt \
343 + && echo "FA_BRANCH: ${FA_BRANCH}" >> /app/versions.txt \
344 + && echo "FA_REPO: ${FA_REPO}" >> /app/versions.txt \
345 + && echo "AITER_BRANCH: ${AITER_BRANCH}" >> /app/versions.txt \
346 + && echo "AITER_REPO: ${AITER_REPO}" >> /app/versions.txt \
347 + && echo "MORI_BRANCH: ${MORI_BRANCH}" >> /app/versions.txt \
348 + && echo "MORI_REPO: ${MORI_REPO}" >> /app/versions.txt \
349 + # Fingerprint our triton so Dockerfile.rocm can prove it survived the build.
350 + && echo "TRITON_VERSION: $(pip show triton | awk '/^Version:/ {print $2}')" >> /app/versions.txt \
351 + && echo "TRITON_SHA256: $(find $(python3 -c 'import triton, os; print(os.path.dirname(triton.__file__))') \
352 + -type f \( -name '*.py' -o -name '*.so' \) | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)" \
353 + >> /app/versions.txt \
354 + && echo "PYBIND11_VERSION: $(pip show pybind11 | awk '/^Version:/ {print $2}')" >> /app/versions.txt \
355 + && echo "PYBIND11_INTERNALS_VERSION: $(grep -rhE '^#[[:space:]]*define PYBIND11_INTERNALS_VERSION' \
356 + $(python3 -c 'import pybind11; print(pybind11.get_include())') | awk '{print $NF}')" \
357 + >> /app/versions.txt \
358 + && echo "PYBIND11_SHA256: $(find $(python3 -c 'import pybind11; print(pybind11.get_include())') \
359 + -type f -name '*.h' | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)" \
360 + >> /app/versions.txt
pyproject.toml
+1
@@ -138,6 +138,7 @@ ignore-hidden = false
138 extend-ignore-identifiers-re = [".*[Uu][Ee][0-9][Mm][0-9].*"]
139
140 [tool.typos.default.extend-identifiers]
141 +a63ede7 = "a63ede7"
142 bbc5b7ede = "bbc5b7ede"
143 NOOPs = "NOOPs"
144 nin_shortcut = "nin_shortcut"
requirements/build/rock.txt new
+19
@@ -0,0 +1,19 @@
1 +# Common dependencies
2 +-r ../common.txt
3 +
4 +
5 +--extra-index-url https://repo.amd.com/rocm/whl-multi-arch/
6 +torch==2.12.0+rocm7.14.0
7 +torchvision==0.27.0+rocm7.14.0
8 +torchaudio==2.11.0+rocm7.14.0
9 +triton==3.7.1+git0263a6a6.rocm7.14.0
10 +cmake>=3.26.1,<4
11 +packaging>=26.2
12 +setuptools>=77.0.3,<80.0.0
13 +setuptools-scm>=8
14 +setuptools-rust>=1.9.0
15 +wheel
16 +jinja2>=3.1.6
17 +amdsmi==7.0.2
18 +timm>=1.0.17
19 +tilelang==0.1.10
requirements/build/rocm.txt
+6 -6
@@ -2,13 +2,13 @@
2 -r ../common.txt
3
4
5 ---extra-index-url https://download.pytorch.org/whl/rocm7.1
6 -torch==2.11.0
7 -torchvision==0.26.0
8 -torchaudio==2.11.0
9 -triton==3.6.0
5 +--extra-index-url https://repo.amd.com/rocm/whl-multi-arch/
6 +torch==2.12.0+rocm7.14.0
7 +torchvision==0.27.0+rocm7.14.0
8 +torchaudio==2.11.0+rocm7.14.0
9 +triton==3.7.1+git0263a6a6
10 cmake>=3.26.1,<4
11 -packaging>=24.2
11 +packaging>=26.2
12 setuptools>=77.0.3,<80.0.0
13 setuptools-scm>=8
14 setuptools-rust>=1.9.0
requirements/test/rocm.in
+1
@@ -39,6 +39,7 @@ transformers==5.15.0
39 tokenizers==0.22.2
40 schemathesis>=4.0.0 # Required for openai schema test
41 # quantization
42 +bitsandbytes==0.50.0
43 buildkite-test-collector==0.1.9
44 tilelang==0.1.10
45
requirements/test/rocm.txt
+5 -1
@@ -72,6 +72,8 @@ azure-storage-blob==12.28.0
72 # via runai-model-streamer-azure
73 backoff==2.2.1
74 # via -r requirements/test/rocm.in
75 +bitsandbytes==0.50.0
76 + # via -r requirements/test/rocm.in
77 black==26.3.1
78 # via datamodel-code-generator
79 blake3==1.0.8
@@ -566,6 +568,7 @@ numpy==2.2.6
568 # -r requirements/test/../common.txt
569 # accelerate
570 # albumentations
571 + # bitsandbytes
572 # bm25s
573 # contourpy
574 # cupy-cuda12x
@@ -691,10 +694,11 @@ outlines-core==0.2.14
694 # via
695 # -c requirements/common.txt
696 # -r requirements/test/../common.txt
694 -packaging==26.0
697 +packaging==26.2
698 # via
699 # -c requirements/rocm.txt
700 # accelerate
701 + # bitsandbytes
702 # black
703 # datasets
704 # evaluate