[ROCm][CI] Refresh ROCm base images when docker rocm_base changes (#46904)
Signed-off-by: Rohan138 <rohanpotdar138@gmail.com> Signed-off-by: Codex <codex@example.invalid> Signed-off-by: Micah Williamson <micah.williamson@amd.com> Signed-off-by: Matthew Wong <Matthew.Wong2@amd.com> Signed-off-by: Andreas Karatzas <akaratza@amd.com> Co-authored-by: Rohan138 <rohanpotdar138@gmail.com> Co-authored-by: Codex <codex@example.invalid> Co-authored-by: Micah Williamson <micah.williamson@amd.com> Co-authored-by: Matthew Wong <Matthew.Wong2@amd.com>
Andreas Karatzas committed
Jul 7, 2026 at 05:10 UTC
cbb5f045beb1f82bc139e14a4d3b2a904a8b358e
14 files changed
+724
-52
.buildkite/ci_config_rocm.yaml
+1
@@ -8,6 +8,7 @@ run_all_patterns:
8
- "docker/docker-bake-rocm.hcl"
9
- ".buildkite/hardware_tests/amd.yaml"
10
- ".buildkite/scripts/ci-bake-rocm.sh"
11
+ - ".buildkite/scripts/rocm/"
12
- ".buildkite/scripts/hardware_ci/run-amd-test.py"
13
- ".buildkite/scripts/hardware_ci/run-amd-test.sh"
14
- "CMakeLists.txt"
.buildkite/hardware_tests/amd.yaml
+32
-29
@@ -1,5 +1,28 @@
1
group: Hardware - AMD Build
2
+
3
+# ROCm image flow:
4
+# 1. Refresh the long-lived ROCm base image only when Dockerfile.rocm_base changes.
5
+# 2. Build ci_base from either the stable base or the freshly refreshed base.
6
+# 3. Build the per-commit ROCm CI image and smoke-test it before GPU jobs run.
7
steps:
8
+ - label: "AMD: :docker: refresh ROCm base"
9
+ key: refresh-rocm-base-amd
10
+ depends_on: []
11
+ device: amd_cpu
12
+ no_plugin: true
13
+ commands:
14
+ - bash .buildkite/scripts/rocm/refresh-base-image.sh
15
+ env:
16
+ DOCKER_BUILDKIT: "1"
17
+ BUILDKIT_PROGRESS: "tty"
18
+ TERM: "xterm-256color"
19
+ retry:
20
+ automatic:
21
+ - exit_status: -1 # Agent was lost
22
+ limit: 1
23
+ - exit_status: -10 # Agent was lost
24
+ limit: 1
25
+
26
# Ensure ci_base is up-to-date before building the test image.
27
# Compares a content hash of ci_base-affecting files against the remote
28
# image label. If hashes match the build is skipped (< 30 s); if they
@@ -7,13 +30,16 @@ steps:
30
- label: "AMD: :docker: ensure ci_base"
31
key: ensure-ci-base-amd
32
soft_fail: false
10
- depends_on: []
33
+ depends_on:
34
+ - refresh-rocm-base-amd
35
device: amd_cpu
36
no_plugin: true
37
commands:
14
- - bash .buildkite/scripts/ci-bake-rocm.sh ci-base-rocm-ci-with-deps
38
+ - bash .buildkite/scripts/rocm/build-ci-base.sh
39
env:
40
DOCKER_BUILDKIT: "1"
41
+ BUILDKIT_PROGRESS: "tty"
42
+ TERM: "xterm-256color"
43
VLLM_BAKE_FILE: "docker/docker-bake-rocm.hcl"
44
PYTORCH_ROCM_ARCH: "gfx90a;gfx942;gfx950"
45
REMOTE_VLLM: "1"
@@ -33,35 +59,12 @@ steps:
59
device: amd_cpu
60
no_plugin: true
61
commands:
36
- - |
37
- if [[ "${ROCM_CI_ARTIFACT_ONLY:-0}" == "1" ]]; then
38
- echo "ROCM_CI_ARTIFACT_ONLY=1; building ROCm wheel artifact only"
39
- IMAGE_TAG="" bash .buildkite/scripts/ci-bake-rocm.sh test-rocm-ci-with-artifacts
40
- else
41
- bash .buildkite/scripts/ci-bake-rocm.sh test-rocm-ci-with-wheel
42
- fi
43
- - |
44
- docker run --rm --network=none --entrypoint /bin/bash "rocm/vllm-ci:${BUILDKITE_COMMIT}" -ec '
45
- if [ ! -d /vllm-workspace ]; then echo Missing directory: /vllm-workspace >&2; exit 1; fi
46
- if [ ! -d /vllm-workspace/tests ]; then echo Missing directory: /vllm-workspace/tests >&2; exit 1; fi
47
- if [ ! -d /vllm-workspace/src/vllm ]; then echo Missing directory: /vllm-workspace/src/vllm >&2; exit 1; fi
48
- if [ ! -x /vllm-workspace/src/vllm/vllm-rs ]; then echo Missing executable: /vllm-workspace/src/vllm/vllm-rs >&2; exit 1; fi
49
- command -v python3
50
- command -v uv
51
- command -v pytest
52
- if ! command -v amd-smi >/dev/null 2>&1 && ! command -v rocminfo >/dev/null 2>&1; then
53
- echo No ROCm CLI found in image >&2
54
- exit 1
55
- fi
56
- python3 - <<PY
57
- import torch, vllm
58
- print(torch.__version__)
59
- print(vllm.__version__)
60
- PY
61
- echo AMD image smoke OK
62
- '
62
+ - bash .buildkite/scripts/rocm/build-test-image.sh
63
+ - bash .buildkite/scripts/rocm/smoke-test-image.sh
64
env:
65
DOCKER_BUILDKIT: "1"
66
+ BUILDKIT_PROGRESS: "tty"
67
+ TERM: "xterm-256color"
68
VLLM_BAKE_FILE: "docker/docker-bake-rocm.hcl"
69
PYTORCH_ROCM_ARCH: "gfx90a;gfx942;gfx950"
70
IMAGE_TAG: "rocm/vllm-ci:$BUILDKITE_COMMIT"
.buildkite/scripts/ci-bake-rocm.sh
+25
-3
@@ -15,7 +15,7 @@ set -euo pipefail
15
16
DEFAULT_REPO_SLUG="vllm-project/vllm"
17
DEFAULT_CI_HCL_SOURCE="docker/ci-rocm.hcl"
18
-DEFAULT_CI_BASE_CONTENT_FILES="requirements/common.txt requirements/rocm.txt requirements/test/rocm.txt docker/Dockerfile.rocm_base docker/ci-rocm.hcl docker/docker-bake-rocm.hcl tools/install_torchcodec_rocm.sh tests/vllm_test_utils .buildkite/scripts/ci-bake-rocm.sh"
18
+DEFAULT_CI_BASE_CONTENT_FILES="requirements/common.txt requirements/rocm.txt requirements/test/rocm.txt docker/Dockerfile.rocm_base docker/ci-rocm.hcl docker/docker-bake-rocm.hcl tools/install_torchcodec_rocm.sh tests/vllm_test_utils .buildkite/scripts/ci-bake-rocm.sh .buildkite/scripts/rocm/build-ci-base.sh"
19
DEFAULT_CI_BASE_DOCKERFILE="docker/Dockerfile.rocm"
20
DEFAULT_CI_BASE_DOCKERFILE_STAGES="base build_rixl build_rocshmem build_deepep mori_base ci_base"
21
DEFAULT_CI_BASE_METADATA_VERSION="1"
@@ -393,6 +393,16 @@ should_upload_wheel_artifacts() {
393
|| "${TARGET}" == *"artifact"* ]]
394
}
395
396
+set_buildkite_metadata() {
397
+ local key="$1"
398
+ local value="$2"
399
+
400
+ [[ -n "${value}" ]] || return 0
401
+ if command -v buildkite-agent >/dev/null 2>&1; then
402
+ buildkite-agent meta-data set "${key}" "${value}" || true
403
+ fi
404
+}
405
+
406
get_remote_image_label() {
407
local image_ref="$1"
408
local label_key="$2"
@@ -733,6 +743,8 @@ configure_ci_base_image_refs() {
743
744
if is_ci_base_target; then
745
IMAGE_TAG="${primary_tag}"
746
+ CI_BASE_IMAGE="${primary_tag}"
747
+ export CI_BASE_IMAGE
748
export IMAGE_TAG
749
750
echo "ci_base primary image tag: ${CI_BASE_IMAGE_TAG}"
@@ -750,6 +762,10 @@ configure_ci_base_image_refs() {
762
echo "ci_base stable alias will not be pushed for this build"
763
echo "Set NIGHTLY=1 on ${CI_BASE_STABLE_BRANCH:-main} to refresh ${stable_tag}"
764
fi
765
+ set_buildkite_metadata "rocm-ci-base-image" "${CI_BASE_IMAGE_TAG}"
766
+ set_buildkite_metadata "rocm-ci-base-image-content" "${content_tag}"
767
+ set_buildkite_metadata "rocm-ci-base-image-commit" "${CI_BASE_IMAGE_TAG_COMMIT:-}"
768
+ set_buildkite_metadata "rocm-ci-base-image-stable" "${CI_BASE_IMAGE_TAG_STABLE:-}"
769
return 0
770
fi
771
@@ -1779,7 +1795,10 @@ seed_dependency_caches_if_needed() {
1795
1796
echo "--- :docker: Seeding ${target}"
1797
echo "Expected cache ref: ${cache_ref}"
1782
- docker buildx bake "${BAKE_FILES[@]}" --progress plain "${target}"
1798
+ docker buildx bake \
1799
+ "${BAKE_FILES[@]}" \
1800
+ --progress "${BUILDKIT_PROGRESS:-plain}" \
1801
+ "${target}"
1802
verify_dependency_cache_ref "${cache_ref}"
1803
done
1804
}
@@ -1807,7 +1826,10 @@ run_bake() {
1826
local build_rc=0
1827
1828
echo "--- :docker: Building ${TARGET}"
1810
- docker buildx bake "${BAKE_FILES[@]}" --progress plain "${BAKE_TARGETS[@]}" || build_rc=$?
1829
+ docker buildx bake \
1830
+ "${BAKE_FILES[@]}" \
1831
+ --progress "${BUILDKIT_PROGRESS:-plain}" \
1832
+ "${BAKE_TARGETS[@]}" || build_rc=$?
1833
1834
if [[ ${build_rc} -eq 0 ]]; then
1835
echo "--- :white_check_mark: Build complete"
.buildkite/scripts/hardware_ci/run-amd-test.sh
+25
-1
@@ -28,6 +28,17 @@
28
###############################################################################
29
set -o pipefail
30
31
+: "${BUILDKIT_PROGRESS:=plain}"
32
+: "${TERM:=xterm-256color}"
33
+: "${FORCE_COLOR:=1}"
34
+: "${CLICOLOR_FORCE:=1}"
35
+: "${PY_COLORS:=1}"
36
+: "${ROCM_DOCKER_TTY:=1}"
37
+if [[ " ${PYTEST_ADDOPTS:-} " != *" --color"* ]]; then
38
+ PYTEST_ADDOPTS="${PYTEST_ADDOPTS:+${PYTEST_ADDOPTS} }--color=yes"
39
+fi
40
+export BUILDKIT_PROGRESS TERM FORCE_COLOR CLICOLOR_FORCE PY_COLORS PYTEST_ADDOPTS ROCM_DOCKER_TTY
41
+
42
# Export Python path for commands that run directly on the host. Containerized
43
# tests set this to /vllm-workspace below so spawned Python processes do not
44
# depend on their current working directory.
@@ -149,6 +160,7 @@ EOF
160
echo "--- Building local ROCm test image"
161
docker build \
162
--pull=false \
163
+ --progress "${BUILDKIT_PROGRESS}" \
164
--build-arg "BASE_IMAGE=${base_image}" \
165
-t "${artifact_image}" \
166
"${context_dir}" || return 1
@@ -535,6 +547,13 @@ if is_multi_node "$commands"; then
547
else
548
echo "--- Single-node job"
549
echo "Render devices: $BUILDKITE_AGENT_META_DATA_RENDER_DEVICES"
550
+ docker_run_terminal_args=(-i)
551
+ if [[ "${ROCM_DOCKER_TTY}" == "1" ]]; then
552
+ docker_run_terminal_args+=(-t)
553
+ echo "Docker interactive stdin: enabled; TTY allocation: enabled"
554
+ else
555
+ echo "Docker interactive stdin: enabled; TTY allocation: disabled"
556
+ fi
557
558
ulimit_core_hard=$(ulimit -H -c)
559
if [[ "$ulimit_core_hard" == "unlimited" ]]; then
@@ -551,7 +570,7 @@ else
570
fi
571
572
docker run \
554
- -t -i \
573
+ "${docker_run_terminal_args[@]}" \
574
--device /dev/kfd $BUILDKITE_AGENT_META_DATA_RENDER_DEVICES \
575
$RDMA_FLAGS \
576
--network=host \
@@ -566,6 +585,11 @@ else
585
-e AWS_SECRET_ACCESS_KEY \
586
-e BUILDKITE_PARALLEL_JOB \
587
-e BUILDKITE_PARALLEL_JOB_COUNT \
588
+ -e TERM \
589
+ -e FORCE_COLOR \
590
+ -e CLICOLOR_FORCE \
591
+ -e PY_COLORS \
592
+ -e PYTEST_ADDOPTS \
593
-v "${HF_CACHE}:${HF_MOUNT}" \
594
-e "HF_HOME=${HF_MOUNT}" \
595
-e "PYTHONPATH=${MYPYTHONPATH}" \
.buildkite/scripts/rocm/build-ci-base.sh
new
+32
@@ -0,0 +1,32 @@
1
+#!/usr/bin/env bash
2
+# Build the ROCm ci_base image, optionally from a freshly rebuilt ROCm base.
3
+
4
+set -euo pipefail
5
+
6
+metadata_get() {
7
+ local key="$1"
8
+ if command -v buildkite-agent >/dev/null 2>&1; then
9
+ buildkite-agent meta-data get "${key}" 2>/dev/null || true
10
+ fi
11
+}
12
+
13
+main() {
14
+ local base_refreshed=""
15
+
16
+ base_refreshed="$(metadata_get rocm-base-refresh)"
17
+ if [[ "${base_refreshed}" == "1" ]]; then
18
+ export BASE_IMAGE
19
+ export CI_BASE_PUSH_STABLE_TAG
20
+
21
+ BASE_IMAGE="$(metadata_get rocm-base-image)"
22
+ CI_BASE_PUSH_STABLE_TAG="$(metadata_get rocm-base-push-stable-tag)"
23
+ CI_BASE_PUSH_STABLE_TAG="${CI_BASE_PUSH_STABLE_TAG:-0}"
24
+
25
+ echo "Using refreshed ROCm base image for ci_base: ${BASE_IMAGE}"
26
+ echo "Push stable ci_base tag: ${CI_BASE_PUSH_STABLE_TAG}"
27
+ fi
28
+
29
+ bash .buildkite/scripts/ci-bake-rocm.sh ci-base-rocm-ci-with-deps
30
+}
31
+
32
+main "$@"
.buildkite/scripts/rocm/build-test-image.sh
new
+57
@@ -0,0 +1,57 @@
1
+#!/usr/bin/env bash
2
+# Build the ROCm CI test image or wheel artifact.
3
+#
4
+# When Dockerfile.rocm_base changes, always build the full image so downstream
5
+# ROCm tests can validate the freshly rebuilt base -> ci_base -> ci image chain.
6
+
7
+set -euo pipefail
8
+
9
+metadata_get() {
10
+ local key="$1"
11
+ if command -v buildkite-agent >/dev/null 2>&1; then
12
+ buildkite-agent meta-data get "${key}" 2>/dev/null || true
13
+ fi
14
+}
15
+
16
+use_refreshed_base_if_present() {
17
+ local base_refreshed=""
18
+
19
+ base_refreshed="$(metadata_get rocm-base-refresh)"
20
+ if [[ "${base_refreshed}" != "1" ]]; then
21
+ return 1
22
+ fi
23
+
24
+ export BASE_IMAGE
25
+ export CI_BASE_IMAGE
26
+ export IMAGE_TAG_LATEST
27
+
28
+ BASE_IMAGE="$(metadata_get rocm-base-image)"
29
+ CI_BASE_IMAGE="$(metadata_get rocm-ci-base-image)"
30
+ IMAGE_TAG_LATEST="$(metadata_get rocm-ci-image-descriptive)"
31
+
32
+ echo "Using refreshed ROCm base image for test image: ${BASE_IMAGE}"
33
+ echo "Using refreshed ROCm ci_base image for test image: ${CI_BASE_IMAGE}"
34
+ if [[ -n "${IMAGE_TAG_LATEST}" ]]; then
35
+ echo "Also tagging full ROCm CI image as: ${IMAGE_TAG_LATEST}"
36
+ fi
37
+
38
+ return 0
39
+}
40
+
41
+main() {
42
+ local base_refreshed=0
43
+
44
+ if use_refreshed_base_if_present; then
45
+ base_refreshed=1
46
+ fi
47
+
48
+ if [[ "${ROCM_CI_ARTIFACT_ONLY:-0}" == "1" && "${base_refreshed}" != "1" ]]; then
49
+ echo "ROCM_CI_ARTIFACT_ONLY=1; building ROCm wheel artifact only"
50
+ IMAGE_TAG="" bash .buildkite/scripts/ci-bake-rocm.sh test-rocm-ci-with-artifacts
51
+ return
52
+ fi
53
+
54
+ bash .buildkite/scripts/ci-bake-rocm.sh test-rocm-ci-with-wheel
55
+}
56
+
57
+main "$@"
.buildkite/scripts/rocm/refresh-base-image.sh
new
+513
@@ -0,0 +1,513 @@
1
+#!/usr/bin/env bash
2
+# Build and publish a fresh ROCm base image when Dockerfile.rocm_base changes.
3
+#
4
+# Normal AMD CI builds should not pay for this path. The script no-ops unless
5
+# docker/Dockerfile.rocm_base changed relative to the branch base, the previous
6
+# main commit, or ROCM_BASE_REFRESH_FORCE=1 is set.
7
+
8
+set -euo pipefail
9
+
10
+DOCKERFILE="${ROCM_BASE_DOCKERFILE:-docker/Dockerfile.rocm_base}"
11
+BASE_REPO="${ROCM_BASE_IMAGE_REPO:-rocm/vllm-dev}"
12
+CI_IMAGE_REPO="${ROCM_CI_IMAGE_REPO:-rocm/vllm-ci}"
13
+BUILDER_NAME="${ROCM_BASE_BUILDER_NAME:-vllm-rocm-base-builder}"
14
+DEFAULT_ROCM_BASE_METADATA_VERSION="1"
15
+DEFAULT_ROCM_BASE_CONTENT_FILES="${DOCKERFILE}"
16
+DEFAULT_ROCM_BASE_CONTENT_ARGS="BASE_IMAGE TRITON_BRANCH TRITON_REPO PYTORCH_BRANCH PYTORCH_REPO PYTORCH_VISION_BRANCH PYTORCH_VISION_REPO PYTORCH_AUDIO_BRANCH PYTORCH_AUDIO_REPO FA_BRANCH FA_REPO AITER_BRANCH AITER_REPO MORI_BRANCH MORI_REPO PYTORCH_ROCM_ARCH PYTHON_VERSION USE_SCCACHE"
17
+
18
+metadata_set() {
19
+ local key="$1"
20
+ local value="$2"
21
+
22
+ [[ -n "${value}" ]] || return 0
23
+ if command -v buildkite-agent >/dev/null 2>&1; then
24
+ buildkite-agent meta-data set "${key}" "${value}" || true
25
+ fi
26
+}
27
+
28
+compute_content_hash() {
29
+ local path=""
30
+ local file=""
31
+
32
+ for path in "$@"; do
33
+ if [[ -d "${path}" ]]; then
34
+ while IFS= read -r -d '' file; do
35
+ printf 'file:%s\n' "${file}"
36
+ sha256sum "${file}"
37
+ done < <(find "${path}" -type f -print0 | sort -z)
38
+ elif [[ -f "${path}" ]]; then
39
+ printf 'file:%s\n' "${path}"
40
+ sha256sum "${path}"
41
+ else
42
+ printf 'missing:%s\n' "${path}"
43
+ fi
44
+ done | sha256sum | cut -d' ' -f1
45
+}
46
+
47
+clean_docker_tag() {
48
+ local input="$1"
49
+ echo "${input}" | sed 's/[^a-zA-Z0-9._-]/_/g' | cut -c1-128
50
+}
51
+
52
+tag_component() {
53
+ local input="$1"
54
+ local max_chars="${2:-24}"
55
+
56
+ clean_docker_tag "${input:-unknown}" | cut -c1-"${max_chars}"
57
+}
58
+
59
+extract_arg_default() {
60
+ local arg_name="$1"
61
+
62
+ sed -n -E "s/^[[:space:]]*ARG[[:space:]]+${arg_name}=\"?([^\"[:space:]]+)\"?.*/\\1/p" \
63
+ "${DOCKERFILE}" | head -1
64
+}
65
+
66
+resolve_image_digest() {
67
+ local image_ref="$1"
68
+
69
+ docker buildx imagetools inspect "${image_ref}" 2>/dev/null \
70
+ | sed -n -E 's/^Digest:[[:space:]]+//p' \
71
+ | head -1 || true
72
+}
73
+
74
+resolve_rocm_base_arg_value() {
75
+ local arg_name="$1"
76
+ local use_sccache="$2"
77
+
78
+ case "${arg_name}" in
79
+ USE_SCCACHE)
80
+ printf '%s\n' "${use_sccache}"
81
+ ;;
82
+ *)
83
+ extract_arg_default "${arg_name}"
84
+ ;;
85
+ esac
86
+}
87
+
88
+hash_rocm_base_arg_values() {
89
+ local use_sccache="$1"
90
+ local base_image_digest="$2"
91
+ local arg_name=""
92
+ local arg_value=""
93
+ shift 2 || true
94
+
95
+ for arg_name in "$@"; do
96
+ [[ -n "${arg_name}" ]] || continue
97
+ arg_value=$(resolve_rocm_base_arg_value "${arg_name}" "${use_sccache}")
98
+ printf 'arg:%s=%s\n' "${arg_name}" "${arg_value:-<empty>}"
99
+ if [[ "${arg_name}" == "BASE_IMAGE" && -n "${arg_value}" ]]; then
100
+ printf 'arg:%s.digest=%s\n' "${arg_name}" "${base_image_digest:-unknown}"
101
+ fi
102
+ done
103
+}
104
+
105
+rocm_version_from_base_image() {
106
+ local base_image="$1"
107
+ local version=""
108
+
109
+ version="$(sed -n -E 's/.*:([0-9]+\.[0-9]+(\.[0-9]+)?)-.*/\1/p' <<<"${base_image}")"
110
+ tag_component "${version:-${base_image}}" 16
111
+}
112
+
113
+git_diff_changed_base() {
114
+ local range="$1"
115
+ [[ -n "$(git diff --name-only "${range}" -- "${DOCKERFILE}" 2>/dev/null)" ]]
116
+}
117
+
118
+short_git_ref() {
119
+ local ref="$1"
120
+
121
+ git rev-parse --short "${ref}" 2>/dev/null || printf '%s\n' "${ref}"
122
+}
123
+
124
+extract_arg_default_from_ref() {
125
+ local ref="$1"
126
+ local arg_name="$2"
127
+ local content=""
128
+
129
+ content="$(git show "${ref}:${DOCKERFILE}" 2>/dev/null || true)"
130
+ sed -n -E "s/^[[:space:]]*ARG[[:space:]]+${arg_name}=\"?([^\"[:space:]]+)\"?.*/\\1/p" \
131
+ <<<"${content}" | head -1
132
+}
133
+
134
+log_arg_default_changes() {
135
+ local old_ref="$1"
136
+ local new_ref="$2"
137
+ local content_args="${ROCM_BASE_CONTENT_ARGS:-${DEFAULT_ROCM_BASE_CONTENT_ARGS}}"
138
+ local arg_name=""
139
+ local old_value=""
140
+ local new_value=""
141
+ local changed=0
142
+
143
+ echo "Changed ROCm base ARG defaults:"
144
+ for arg_name in ${content_args}; do
145
+ old_value="$(extract_arg_default_from_ref "${old_ref}" "${arg_name}")"
146
+ new_value="$(extract_arg_default_from_ref "${new_ref}" "${arg_name}")"
147
+ if [[ "${old_value}" != "${new_value}" ]]; then
148
+ echo " - ${arg_name}: ${old_value:-<unset>} -> ${new_value:-<unset>}"
149
+ changed=1
150
+ fi
151
+ done
152
+
153
+ if [[ "${changed}" == "0" ]]; then
154
+ echo " - none detected; Dockerfile instructions changed outside tracked ARG defaults"
155
+ fi
156
+}
157
+
158
+log_arg_line_diff() {
159
+ local range="$1"
160
+ local arg_diff=""
161
+
162
+ arg_diff="$(
163
+ git diff --unified=0 "${range}" -- "${DOCKERFILE}" 2>/dev/null \
164
+ | awk '/^[+-][[:space:]]*ARG[[:space:]]/ && $0 !~ /^(---|\+\+\+)/ { print " " $0 }' \
165
+ || true
166
+ )"
167
+
168
+ if [[ -n "${arg_diff}" ]]; then
169
+ echo "Changed Dockerfile ARG lines:"
170
+ printf '%s\n' "${arg_diff}"
171
+ fi
172
+}
173
+
174
+log_rocm_base_change_check() {
175
+ local context="$1"
176
+ local range="$2"
177
+ local old_ref="$3"
178
+ local old_short=""
179
+ local head_short=""
180
+
181
+ old_short="$(short_git_ref "${old_ref}")"
182
+ head_short="$(short_git_ref HEAD)"
183
+
184
+ echo "--- :mag: ROCm base refresh check"
185
+ echo "Context: ${context}"
186
+ echo "Dockerfile: ${DOCKERFILE}"
187
+ echo "Base revision: ${old_short}"
188
+ echo "Head revision: ${head_short}"
189
+ echo "Git diff range: ${range}"
190
+}
191
+
192
+log_rocm_base_rebuild_reason() {
193
+ local context="$1"
194
+ local range="$2"
195
+ local old_ref="$3"
196
+ local changed_files=""
197
+
198
+ log_rocm_base_change_check "${context}" "${range}" "${old_ref}"
199
+
200
+ changed_files="$(git diff --name-only "${range}" -- "${DOCKERFILE}" 2>/dev/null || true)"
201
+ echo "Changed files:"
202
+ if [[ -n "${changed_files}" ]]; then
203
+ sed 's/^/ - /' <<<"${changed_files}"
204
+ else
205
+ echo " - ${DOCKERFILE}"
206
+ fi
207
+ log_arg_default_changes "${old_ref}" HEAD
208
+ log_arg_line_diff "${range}"
209
+ echo "Decision: rebuilding ROCm base image because ${DOCKERFILE} changed."
210
+}
211
+
212
+rocm_base_changed_in_range() {
213
+ local context="$1"
214
+ local range="$2"
215
+ local old_ref="$3"
216
+
217
+ if git_diff_changed_base "${range}"; then
218
+ log_rocm_base_rebuild_reason "${context}" "${range}" "${old_ref}"
219
+ return 0
220
+ fi
221
+
222
+ log_rocm_base_change_check "${context}" "${range}" "${old_ref}"
223
+ echo "Decision: ROCm base refresh not required; ${DOCKERFILE} is unchanged."
224
+ return 1
225
+}
226
+
227
+rocm_base_changed() {
228
+ local base_branch="${BUILDKITE_PULL_REQUEST_BASE_BRANCH:-main}"
229
+ local base_ref="refs/remotes/origin/${base_branch}"
230
+ local merge_base=""
231
+
232
+ if [[ "${ROCM_BASE_REFRESH_SKIP:-0}" == "1" ]]; then
233
+ echo "ROCM_BASE_REFRESH_SKIP=1 set; skipping ROCm base refresh"
234
+ return 1
235
+ fi
236
+
237
+ if [[ "${ROCM_BASE_REFRESH_FORCE:-0}" == "1" ]]; then
238
+ echo "ROCM_BASE_REFRESH_FORCE=1 set; refreshing ROCm base image"
239
+ return 0
240
+ fi
241
+
242
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
243
+ echo "Not in a git checkout; skipping ROCm base refresh unless forced"
244
+ return 1
245
+ fi
246
+
247
+ if [[ "${BUILDKITE_PULL_REQUEST:-false}" != "false" ]]; then
248
+ git fetch --no-tags --depth=200 origin \
249
+ "+refs/heads/${base_branch}:${base_ref}" >/dev/null 2>&1 || true
250
+ merge_base=$(git merge-base HEAD "${base_ref}" 2>/dev/null || true)
251
+ if [[ -z "${merge_base}" ]]; then
252
+ echo "Unable to determine merge base with PR base ${base_ref}; skipping ROCm base refresh unless forced"
253
+ return 1
254
+ fi
255
+ if rocm_base_changed_in_range \
256
+ "pull request build against ${base_ref}" \
257
+ "${merge_base}...HEAD" \
258
+ "${merge_base}"; then
259
+ return 0
260
+ fi
261
+ elif [[ "${BUILDKITE_BRANCH:-}" == "${ROCM_BASE_STABLE_BRANCH:-main}" ]] \
262
+ && git rev-parse --verify HEAD~1 >/dev/null 2>&1; then
263
+ if rocm_base_changed_in_range \
264
+ "stable branch build; comparing against previous ${ROCM_BASE_STABLE_BRANCH:-main} commit" \
265
+ "HEAD~1..HEAD" \
266
+ "HEAD~1"; then
267
+ return 0
268
+ fi
269
+ else
270
+ git fetch --no-tags --depth=200 origin \
271
+ "+refs/heads/${base_branch}:${base_ref}" >/dev/null 2>&1 || true
272
+ merge_base=$(git merge-base HEAD "${base_ref}" 2>/dev/null || true)
273
+ if [[ -z "${merge_base}" ]]; then
274
+ echo "Unable to determine merge base with branch base ${base_ref}; skipping ROCm base refresh unless forced"
275
+ return 1
276
+ fi
277
+ if rocm_base_changed_in_range \
278
+ "branch build against ${base_ref}" \
279
+ "${merge_base}...HEAD" \
280
+ "${merge_base}"; then
281
+ return 0
282
+ fi
283
+ fi
284
+
285
+ return 1
286
+}
287
+
288
+should_push_stable_tag() {
289
+ if [[ "${BUILDKITE_PULL_REQUEST:-false}" != "false" ]]; then
290
+ return 1
291
+ fi
292
+
293
+ if [[ "${ROCM_BASE_PUSH_STABLE_TAG:-}" == "1" ]]; then
294
+ return 0
295
+ fi
296
+ if [[ "${ROCM_BASE_PUSH_STABLE_TAG:-}" == "0" ]]; then
297
+ return 1
298
+ fi
299
+
300
+ [[ "${BUILDKITE_PULL_REQUEST:-false}" == "false" \
301
+ && "${BUILDKITE_BRANCH:-}" == "${ROCM_BASE_STABLE_BRANCH:-main}" ]]
302
+}
303
+
304
+setup_builder() {
305
+ echo "--- :buildkite: Setting up buildx builder for ROCm base"
306
+ if docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then
307
+ docker buildx use "${BUILDER_NAME}"
308
+ else
309
+ docker buildx create --name "${BUILDER_NAME}" --driver docker-container --use
310
+ fi
311
+ docker buildx inspect --bootstrap
312
+}
313
+
314
+compute_base_content_hash() {
315
+ local use_sccache="$1"
316
+ local base_image_digest="$2"
317
+ local content_files="${ROCM_BASE_CONTENT_FILES:-${DEFAULT_ROCM_BASE_CONTENT_FILES}}"
318
+ local content_args="${ROCM_BASE_CONTENT_ARGS:-${DEFAULT_ROCM_BASE_CONTENT_ARGS}}"
319
+ local -a content_paths=()
320
+ local -a content_arg_names=()
321
+
322
+ read -r -a content_paths <<< "${content_files}"
323
+ read -r -a content_arg_names <<< "${content_args}"
324
+
325
+ {
326
+ printf 'content-files-hash:%s\n' "$(compute_content_hash "${content_paths[@]}")"
327
+ printf 'dockerfile:%s\n' "${DOCKERFILE}"
328
+ printf 'resolved-build-args:\n'
329
+ hash_rocm_base_arg_values \
330
+ "${use_sccache}" "${base_image_digest}" "${content_arg_names[@]}"
331
+ } | sha256sum | cut -d' ' -f1
332
+}
333
+
334
+build_base_image() {
335
+ local use_sccache="${ROCM_BASE_USE_SCCACHE:-${USE_SCCACHE:-0}}"
336
+ local base_hash=""
337
+ local build_date=""
338
+ local build_suffix=""
339
+ local base_image_arg=""
340
+ local base_image_digest=""
341
+ local rocm_version=""
342
+ local triton_arg=""
343
+ local pytorch_arg=""
344
+ local pytorch_vision_arg=""
345
+ local pytorch_audio_arg=""
346
+ local fa_arg=""
347
+ local aiter_arg=""
348
+ local mori_arg=""
349
+ local python_version_arg=""
350
+ local pytorch_rocm_arch_arg=""
351
+ local pytorch_branch=""
352
+ local aiter_branch=""
353
+ local dependency_summary=""
354
+ local descriptor=""
355
+ local ci_descriptor=""
356
+ local descriptive_tag=""
357
+ local stable_tag="${BASE_REPO}:base"
358
+ local ci_descriptive_tag=""
359
+ local content_files="${ROCM_BASE_CONTENT_FILES:-${DEFAULT_ROCM_BASE_CONTENT_FILES}}"
360
+ local content_args="${ROCM_BASE_CONTENT_ARGS:-${DEFAULT_ROCM_BASE_CONTENT_ARGS}}"
361
+ local content_files_hash=""
362
+ local metadata_version="${ROCM_BASE_METADATA_VERSION:-${DEFAULT_ROCM_BASE_METADATA_VERSION}}"
363
+ local -a tags=()
364
+ local -a no_cache_args=()
365
+ local -a sccache_args=()
366
+ local -a content_paths=()
367
+
368
+ if [[ ! -f "${DOCKERFILE}" ]]; then
369
+ echo "Error: ROCm base Dockerfile not found: ${DOCKERFILE}" >&2
370
+ exit 1
371
+ fi
372
+
373
+ build_date="${ROCM_BASE_TAG_DATE:-$(date -u +%Y%m%d)}"
374
+ if [[ -n "${BUILDKITE_BUILD_NUMBER:-}" ]]; then
375
+ build_suffix="_bk_${BUILDKITE_BUILD_NUMBER}"
376
+ fi
377
+ base_image_arg="$(extract_arg_default BASE_IMAGE)"
378
+ base_image_digest="$(resolve_image_digest "${base_image_arg}")"
379
+ read -r -a content_paths <<< "${content_files}"
380
+ content_files_hash="$(compute_content_hash "${content_paths[@]}")"
381
+ base_hash=$(compute_base_content_hash "${use_sccache}" "${base_image_digest}")
382
+ rocm_version="$(rocm_version_from_base_image "${base_image_arg}")"
383
+ triton_arg="$(extract_arg_default TRITON_BRANCH)"
384
+ pytorch_arg="$(extract_arg_default PYTORCH_BRANCH)"
385
+ pytorch_vision_arg="$(extract_arg_default PYTORCH_VISION_BRANCH)"
386
+ pytorch_audio_arg="$(extract_arg_default PYTORCH_AUDIO_BRANCH)"
387
+ fa_arg="$(extract_arg_default FA_BRANCH)"
388
+ aiter_arg="$(extract_arg_default AITER_BRANCH)"
389
+ mori_arg="$(extract_arg_default MORI_BRANCH)"
390
+ python_version_arg="$(extract_arg_default PYTHON_VERSION)"
391
+ pytorch_rocm_arch_arg="$(extract_arg_default PYTORCH_ROCM_ARCH)"
392
+ pytorch_branch="$(tag_component "${pytorch_arg}" 16)"
393
+ aiter_branch="$(tag_component "${aiter_arg}" 24)"
394
+ dependency_summary="base=${base_image_arg},rocm=${rocm_version},python=${python_version_arg},pytorch=${pytorch_arg},torchvision=${pytorch_vision_arg},torchaudio=${pytorch_audio_arg},triton=${triton_arg},flash-attn=${fa_arg},aiter=${aiter_arg},mori=${mori_arg},pytorch-rocm-arch=${pytorch_rocm_arch_arg}"
395
+ descriptor="$(clean_docker_tag "base_custom_aiter_${aiter_branch}_torch_${pytorch_branch}_${build_date}${build_suffix}")"
396
+ ci_descriptor="$(clean_docker_tag "ci_custom_aiter_${aiter_branch}_torch_${pytorch_branch}_${build_date}${build_suffix}")"
397
+
398
+ descriptive_tag="${BASE_REPO}:${descriptor}"
399
+ ci_descriptive_tag="${CI_IMAGE_REPO}:${ci_descriptor}"
400
+
401
+ tags=(-t "${descriptive_tag}")
402
+ if should_push_stable_tag; then
403
+ tags+=(-t "${stable_tag}")
404
+ metadata_set "rocm-base-push-stable-tag" "1"
405
+ else
406
+ metadata_set "rocm-base-push-stable-tag" "0"
407
+ fi
408
+
409
+ if [[ "${ROCM_BASE_NO_CACHE:-1}" == "1" ]]; then
410
+ no_cache_args=(--no-cache)
411
+ fi
412
+
413
+ for env_name in \
414
+ SCCACHE_DOWNLOAD_URL \
415
+ SCCACHE_ENDPOINT \
416
+ SCCACHE_BUCKET_NAME \
417
+ SCCACHE_REGION_NAME \
418
+ SCCACHE_S3_NO_CREDENTIALS; do
419
+ if [[ -n "${!env_name:-}" ]]; then
420
+ sccache_args+=(--build-arg "${env_name}=${!env_name}")
421
+ fi
422
+ done
423
+
424
+ echo "--- :docker: Building ROCm base image"
425
+ echo "Dockerfile: ${DOCKERFILE}"
426
+ echo "Descriptive tag: ${descriptive_tag}"
427
+ echo "Stable tag: ${stable_tag} ($(should_push_stable_tag && echo enabled || echo disabled))"
428
+ echo "Content hash: ${base_hash}"
429
+ echo "Dependency summary: ${dependency_summary}"
430
+ echo "USE_SCCACHE: ${use_sccache}"
431
+
432
+ docker buildx build \
433
+ "${no_cache_args[@]}" \
434
+ --pull \
435
+ --progress "${BUILDKIT_PROGRESS:-plain}" \
436
+ --file "${DOCKERFILE}" \
437
+ --build-arg "USE_SCCACHE=${use_sccache}" \
438
+ "${sccache_args[@]}" \
439
+ --label "org.opencontainers.image.source=https://github.com/vllm-project/vllm" \
440
+ --label "org.opencontainers.image.vendor=vLLM" \
441
+ --label "org.opencontainers.image.title=vLLM ROCm base" \
442
+ --label "org.opencontainers.image.revision=${BUILDKITE_COMMIT:-}" \
443
+ --label "vllm.rocm_base.metadata_version=${metadata_version}" \
444
+ --label "vllm.rocm_base.content_hash=${base_hash}" \
445
+ --label "vllm.rocm_base.content_files_hash=${content_files_hash}" \
446
+ --label "vllm.rocm_base.dockerfile=${DOCKERFILE}" \
447
+ --label "vllm.rocm_base.image.descriptive=${descriptive_tag}" \
448
+ --label "vllm.rocm_base.image.stable=${stable_tag}" \
449
+ --label "vllm.rocm_base.git_commit=${BUILDKITE_COMMIT:-}" \
450
+ --label "vllm.rocm_base.stable_branch=${ROCM_BASE_STABLE_BRANCH:-main}" \
451
+ --label "vllm.rocm_base.descriptor=${descriptor}" \
452
+ --label "vllm.rocm_base.dependency_summary=${dependency_summary}" \
453
+ --label "vllm.rocm_base.base_image=${base_image_arg}" \
454
+ --label "vllm.rocm_base.base_image_digest=${base_image_digest}" \
455
+ --label "vllm.rocm_base.dependency.rocm=${rocm_version}" \
456
+ --label "vllm.rocm_base.dependency.python=${python_version_arg}" \
457
+ --label "vllm.rocm_base.dependency.pytorch=${pytorch_arg}" \
458
+ --label "vllm.rocm_base.dependency.torchvision=${pytorch_vision_arg}" \
459
+ --label "vllm.rocm_base.dependency.torchaudio=${pytorch_audio_arg}" \
460
+ --label "vllm.rocm_base.dependency.triton=${triton_arg}" \
461
+ --label "vllm.rocm_base.dependency.flash_attention=${fa_arg}" \
462
+ --label "vllm.rocm_base.dependency.aiter=${aiter_arg}" \
463
+ --label "vllm.rocm_base.dependency.mori=${mori_arg}" \
464
+ --label "vllm.rocm_base.pytorch_rocm_arch=${pytorch_rocm_arch_arg}" \
465
+ "${tags[@]}" \
466
+ --push \
467
+ .
468
+
469
+ docker buildx imagetools inspect "${descriptive_tag}" >/dev/null
470
+
471
+ metadata_set "rocm-base-refresh" "1"
472
+ metadata_set "rocm-base-image" "${descriptive_tag}"
473
+ metadata_set "rocm-base-image-descriptive" "${descriptive_tag}"
474
+ metadata_set "rocm-base-image-stable" "${stable_tag}"
475
+ metadata_set "rocm-base-image-ci-descriptive" "${ci_descriptive_tag}"
476
+ metadata_set "rocm-base-metadata-version" "${metadata_version}"
477
+ metadata_set "rocm-base-content-hash" "${base_hash}"
478
+ metadata_set "rocm-base-content-files-hash" "${content_files_hash}"
479
+ metadata_set "rocm-base-content-files" "${content_files}"
480
+ metadata_set "rocm-base-content-args" "${content_args}"
481
+ metadata_set "rocm-base-base-image-digest" "${base_image_digest}"
482
+ metadata_set "rocm-base-dockerfile" "${DOCKERFILE}"
483
+ metadata_set "rocm-base-descriptor" "${descriptor}"
484
+ metadata_set "rocm-base-dependency-summary" "${dependency_summary}"
485
+ metadata_set "rocm-base-dependency-rocm" "${rocm_version}"
486
+ metadata_set "rocm-base-dependency-python" "${python_version_arg}"
487
+ metadata_set "rocm-base-dependency-pytorch" "${pytorch_arg}"
488
+ metadata_set "rocm-base-dependency-torchvision" "${pytorch_vision_arg}"
489
+ metadata_set "rocm-base-dependency-torchaudio" "${pytorch_audio_arg}"
490
+ metadata_set "rocm-base-dependency-triton" "${triton_arg}"
491
+ metadata_set "rocm-base-dependency-flash-attention" "${fa_arg}"
492
+ metadata_set "rocm-base-dependency-aiter" "${aiter_arg}"
493
+ metadata_set "rocm-base-dependency-mori" "${mori_arg}"
494
+ metadata_set "rocm-base-pytorch-rocm-arch" "${pytorch_rocm_arch_arg}"
495
+ metadata_set "rocm-ci-image-descriptive" "${ci_descriptive_tag}"
496
+
497
+ echo "--- :white_check_mark: ROCm base image published"
498
+ echo "Use BASE_IMAGE=${descriptive_tag} for downstream ROCm CI builds"
499
+}
500
+
501
+main() {
502
+ metadata_set "rocm-base-refresh" "0"
503
+
504
+ if ! rocm_base_changed; then
505
+ echo "ROCm base Dockerfile did not change; skipping base image refresh"
506
+ return 0
507
+ fi
508
+
509
+ setup_builder
510
+ build_base_image
511
+}
512
+
513
+main "$@"
.buildkite/scripts/rocm/smoke-test-image.sh
new
+32
@@ -0,0 +1,32 @@
1
+#!/usr/bin/env bash
2
+# Fast structural smoke test for the full ROCm CI image.
3
+
4
+set -euo pipefail
5
+
6
+image_ref="${VLLM_CI_SMOKE_IMAGE:-rocm/vllm-ci:${BUILDKITE_COMMIT:?BUILDKITE_COMMIT is required}}"
7
+
8
+docker run --rm --network=none --entrypoint /bin/bash "${image_ref}" -ec '
9
+ if [ ! -d /vllm-workspace ]; then echo Missing directory: /vllm-workspace >&2; exit 1; fi
10
+ if [ ! -d /vllm-workspace/tests ]; then echo Missing directory: /vllm-workspace/tests >&2; exit 1; fi
11
+ if [ ! -d /vllm-workspace/src/vllm ]; then echo Missing directory: /vllm-workspace/src/vllm >&2; exit 1; fi
12
+ if [ ! -x /vllm-workspace/src/vllm/vllm-rs ]; then echo Missing executable: /vllm-workspace/src/vllm/vllm-rs >&2; exit 1; fi
13
+
14
+ command -v python3
15
+ command -v uv
16
+ command -v pytest
17
+
18
+ if ! command -v amd-smi >/dev/null 2>&1 && ! command -v rocminfo >/dev/null 2>&1; then
19
+ echo No ROCm CLI found in image >&2
20
+ exit 1
21
+ fi
22
+
23
+ python3 - <<PY
24
+import torch
25
+import vllm
26
+
27
+print(torch.__version__)
28
+print(vllm.__version__)
29
+PY
30
+
31
+ echo AMD image smoke OK
32
+'
docker/Dockerfile.rocm_base
+1
-1
@@ -9,7 +9,7 @@ ARG PYTORCH_AUDIO_BRANCH="v2.9.0"
9
ARG PYTORCH_AUDIO_REPO="https://github.com/pytorch/audio.git"
10
ARG FA_BRANCH="0e60e394"
11
ARG FA_REPO="https://github.com/Dao-AILab/flash-attention.git"
12
-ARG AITER_BRANCH="v0.1.16.post2"
12
+ARG AITER_BRANCH="v0.1.16.post3"
13
ARG AITER_REPO="https://github.com/ROCm/aiter.git"
14
ARG MORI_BRANCH="v1.1.0"
15
ARG MORI_REPO="https://github.com/ROCm/mori.git"
docs/design/attention_backends.md
+1
-1
@@ -170,7 +170,7 @@ Priority is **1 = highest** (tried first).
170
| `FLEX_ATTENTION` | | fp16, bf16, fp32 | `auto`, `float16`, `bfloat16` | %16 | Any | ❌ | ✅ | ✅ | ❌ | Decoder, Encoder Only | Any |
171
| `HPC_ATTN` | | fp16, bf16 | `auto`, `bfloat16`, `fp8_e4m3` | 64 | 128 | ❌ | ❌ | ❌ | ❌ | Decoder | ≥9.0 |
172
| `ROCM_AITER_FA` | | fp16, bf16 | `auto`, `float16`, `bfloat16`, `fp8`, `fp8_e4m3`, `fp8_e5m2` | 16, 32 | 64, 128, 256 | ✅ | ✅ | ❌ | ❌ | Decoder | N/A |
173
-| `ROCM_AITER_UNIFIED_ATTN` | | bf16 | `auto`, `bfloat16`, `fp8`, `fp8_e4m3` | %16 | Any | ✅ | ❌ | ✅ | ❌ | All | N/A |
173
+| `ROCM_AITER_UNIFIED_ATTN` | | fp16, bf16 | `auto`, `float16`, `bfloat16`, `fp8`, `fp8_e4m3`, `fp8_e5m2` | %16 | Any | ✅ | ❌ | ✅ | ❌ | All | N/A |
174
| `ROCM_ATTN` | | fp16, bf16, fp32 | `auto`, `float16`, `bfloat16`, `fp8`, `fp8_e4m3`, `fp8_e5m2` | %16 | 32, 64, 80, 96, 128, 160, 192, 224, 256 | ❌ | ✅ | ✅ | ❌ | Decoder, Encoder, Encoder Only | N/A |
175
| `TRITON_ATTN` | | fp16, bf16, fp32 | `auto`, `float16`, `bfloat16`, `fp8`, `fp8_e4m3`, `fp8_e5m2`, `int4_per_token_head`, `int8_per_token_head`, `fp8_per_token_head` | %16 | Any | ✅ | ✅ | ✅ | ❌ | All | Any |
176
| `TRITON_ATTN_DIFFKV` | | fp16, bf16 | `auto`, `bfloat16` | Any | Any | ❌ | ❌ | ❌ | ❌ | Decoder | Any |
tests/compile/passes/test_fusion_attn.py
-5
@@ -306,11 +306,6 @@ def test_attention_quant_pattern(
306
torch.manual_seed(42)
307
308
backend_cls = backend.get_class()
309
-
310
- # TODO: drop once AITER reenables fp16 unified attention.
311
- if dtype not in backend_cls.supported_dtypes:
312
- pytest.skip(f"{backend.name} does not support dtype {dtype}")
313
-
309
block_size = backend_cls.get_preferred_block_size(16)
310
311
model_config = ModelConfig(
tests/kernels/attention/test_rocm_aiter_unified_attn.py
+1
-2
@@ -30,8 +30,7 @@ NUM_Q_HEADS = 8
30
NUM_KV_HEADS = 8
31
HEAD_SIZES = [128, 256]
32
BLOCK_SIZES = [16, 64]
33
-# TODO: re-add torch.float16 once AITER reenables fp16 unified attention.
34
-DTYPES = [torch.bfloat16]
33
+DTYPES = [torch.bfloat16, torch.float16]
34
FP8_DTYPE = current_platform.fp8_dtype()
35
36
# (query_len, kv_len) per sequence
tests/v1/attention/test_rocm_attention_backends_selection.py
+1
-9
@@ -136,17 +136,9 @@ def test_standard_attention_backend_selection(
136
# Get the backend class path
137
from vllm.platforms.rocm import RocmPlatform
138
139
- # The AITER unified attention kernel only supports BF16/FP8 KV caches
140
- # (its 3D kernel asserts on fp16), so it must be selected with bf16.
141
- dtype = (
142
- torch.bfloat16
143
- if selected_backend == "ROCM_AITER_UNIFIED_ATTN"
144
- else torch.float16
145
- )
146
-
139
attn_selector_config = AttentionSelectorConfig(
140
head_size=128,
149
- dtype=dtype,
141
+ dtype=torch.float16,
142
kv_cache_dtype="auto",
143
block_size=16,
144
use_mla=False,
vllm/v1/attention/backends/rocm_aiter_unified_attn.py
+3
-1
@@ -27,12 +27,14 @@ logger = init_logger(__name__)
27
28
29
class RocmAiterUnifiedAttentionBackend(RocmAttentionBackend):
30
- supported_dtypes: ClassVar[list[torch.dtype]] = [torch.bfloat16]
30
+ supported_dtypes: ClassVar[list[torch.dtype]] = [torch.float16, torch.bfloat16]
31
supported_kv_cache_dtypes: ClassVar[list[CacheDType]] = [
32
"auto",
33
+ "float16",
34
"bfloat16",
35
"fp8",
36
"fp8_e4m3",
37
+ "fp8_e5m2",
38
]
39
40
@staticmethod