diff --git a/.buildkite/hardware_tests/cpu.yaml b/.buildkite/hardware_tests/cpu.yaml index d54688b574..a29b44ed3c 100644 --- a/.buildkite/hardware_tests/cpu.yaml +++ b/.buildkite/hardware_tests/cpu.yaml @@ -232,3 +232,57 @@ steps: "$$BUILDKITE_PARALLEL_JOB" "$REGISTRY/$REPO:$BUILDKITE_COMMIT-arm64-cpu" parallelism: 3 + +- label: ":docker: Build Zen CPU image" + key: zen-cpu-image-build + # Reuse the shared `:-cpu` image that image-build-cpu publishes + # to public ECR, so Dockerfile.zen just layers on top instead of recompiling + # vLLM from source. If the pull fails, the build script still falls back to + # building the CPU base from source. + depends_on: + - image-build-cpu + soft_fail: true + agents: + queue: amd-cpu + source_file_dependencies: + - .buildkite/hardware_tests/cpu.yaml + - .buildkite/image_build/image_build_zen_cpu.sh + - docker/Dockerfile.zen + - docker/Dockerfile.cpu + - requirements/cpu.txt + - requirements/build/cpu.txt + - requirements/test/cpu.txt + - cmake/cpu_extension.cmake + - vllm/model_executor/layers/utils.py + - vllm/model_executor/kernels/linear/zentorch_utils.py + - vllm/model_executor/kernels/linear/scaled_mm/zentorch.py + - vllm/model_executor/kernels/linear/mixed_precision/zentorch.py + - vllm/platforms/cpu.py + - vllm/platforms/zen_cpu.py + - vllm/platforms/__init__.py + - tests/model_executor/test_cpu_unquantized_gemm_dispatch.py + - tests/test_zen_cpu_platform_detection.py + - tests/kernels/moe/test_zen_cpu_fused_moe.py + - tests/kernels/moe/test_zen_cpu_int8_moe.py + - vllm/v1/attention/backends/zentorch_sdpa.py + - tests/test_zentorch_version_pin.py + - vllm/v1/attention/backends/mla/prefill/zen_cpu_sdpa.py + - vllm/model_executor/layers/fused_moe/experts/zentorch_moe.py + - tests/kernels/quantization/test_zen_da8w4.py + commands: + - .buildkite/image_build/image_build_zen_cpu.sh "$REGISTRY" "$REPO" "$BUILDKITE_COMMIT" + env: + DOCKER_BUILDKIT: "1" + # Install zentorch directly (if-branch in Dockerfile.zen) instead of + # `uv pip install "vllm[zen]"`, which forces uv to re-resolve vLLM's full + # dependency closure and chokes on its transitive triton-cpu URL dependency. + # Keep this pin in sync with the `zen` extra in setup.py. + ZENTORCH_VERSION: "2.13.0.1" + retry: + automatic: + - exit_status: 1 # Transient Docker/BuildKit failure + limit: 1 + - exit_status: -1 # Agent was lost + limit: 2 + - exit_status: -10 # Agent was lost + limit: 2 diff --git a/.buildkite/image_build/image_build_zen_cpu.sh b/.buildkite/image_build/image_build_zen_cpu.sh new file mode 100755 index 0000000000..3e42e38a8d --- /dev/null +++ b/.buildkite/image_build/image_build_zen_cpu.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# +# Build the AMD Zen CPU image (vLLM + zentorch) by layering docker/Dockerfile.zen +# on top of a CPU base image that already has vLLM installed. +# +# To avoid recompiling vLLM from source, prefer reusing the shared CPU image that +# the image-build-cpu step already builds and publishes for this commit +# (`:-cpu`). It lives in public ECR, which allows anonymous pulls, +# so no registry credentials are required. If the pull fails (e.g. the image +# isn't published yet), fall back to building the base from docker/Dockerfile.cpu. +# +# The zen image is not pushed to a registry. +# +# See docker/Dockerfile.zen for the build workflow this mirrors. +set -euo pipefail + +if [[ $# -lt 3 ]]; then + echo "Usage: $0 " + exit 1 +fi + +REGISTRY=$1 +REPO=$2 +BUILDKITE_COMMIT=$3 + +image_repo() { + if [[ -n "${REGISTRY}" ]]; then + printf '%s/%s' "${REGISTRY}" "${REPO}" + else + printf '%s' "${REPO}" + fi +} + +IMAGE_REPO="$(image_repo)" + +# The shared CPU image published by image-build-cpu (public ECR, anonymous pull). +SHARED_CPU_IMAGE="" +if [[ -n "${REGISTRY}" ]]; then + SHARED_CPU_IMAGE="$REGISTRY/$REPO:$BUILDKITE_COMMIT-cpu" +fi +FALLBACK_BASE_IMAGE="zen-cpu-base:$BUILDKITE_COMMIT" +IMAGE="$IMAGE_REPO:$BUILDKITE_COMMIT-zen-cpu" + +# ZENTORCH_VERSION is optional; when unset the Dockerfile falls back to +# installing zentorch via `vllm[zen]`. +ZENTORCH_VERSION=${ZENTORCH_VERSION:-} + +# Step 1: obtain the CPU base image that Dockerfile.zen layers on. Prefer pulling +# the published `-cpu` image; fall back to building it from source if unavailable. +if [[ -n "${SHARED_CPU_IMAGE}" ]] && docker pull "$SHARED_CPU_IMAGE"; then + echo "--- :docker: Using published CPU image as base: $SHARED_CPU_IMAGE" + BASE_IMAGE="$SHARED_CPU_IMAGE" +else + echo "--- :docker: Published CPU image unavailable; building base from source" + docker build --file docker/Dockerfile.cpu \ + --platform linux/amd64 \ + --build-arg buildkite_commit="$BUILDKITE_COMMIT" \ + --build-arg VLLM_CPU_X86=true \ + --tag "$FALLBACK_BASE_IMAGE" \ + --target vllm-openai \ + --progress plain . + BASE_IMAGE="$FALLBACK_BASE_IMAGE" +fi + +# Step 2: build the zen test image on top of the CPU base. +echo "--- :docker: Building Zen test image" +docker build --file docker/Dockerfile.zen \ + --platform linux/amd64 \ + --build-arg BASE_IMAGE="$BASE_IMAGE" \ + ${ZENTORCH_VERSION:+--build-arg ZENTORCH_VERSION="$ZENTORCH_VERSION"} \ + --tag "$IMAGE" \ + --target vllm-zen-test \ + --progress plain .