执行摘要
- 一句话:稳定 ROCm CI Docker 构建上下文与源码缓存
- 推荐动作:值得 ROCm 构建维护者和 CI 基建负责人精读,尤其是
validate_ci_build_context_source() 的物化上下文契约、Triton kernels 单一来源 stage 与 cache 刷新策略三处设计;对一般模型/推理开发者价值有限。建议关注后续 ROCm CI 实际命中率与失败的观测结果,并留意对非 pinned Triton 版本构建路径的兼容性。
功能与动机
ROCm CI 的 Docker 构建长期受两类问题困扰:一是 Buildkite 共享工作区是混合 UID 环境,直接修改 checkout 的文件模式(chmod)既不稳定也污染内容哈希与 Docker context;二是源码缓存命中率低、失配后需要日志解析再加一次修复 solve,步骤脆弱且耗时。PR body 明确说明目标:materialize the pinned Git revision into an owned, canonical Docker context instead of mutating the mixed-UID Buildkite checkout or copying its Git history;并 fetch ROCm Triton kernels once from a commit-pinned, SHA-256-verified archive,reuse the extracted package in both ROCm wheel paths,fail if the Docker/CMake pins drift;同时 remove the log parser and second repair solve。
实现拆解
实现按如下步骤拆解:
- 物化独立构建上下文:在
.buildkite/scripts/ci-bake-rocm.sh 中新增 validate_ci_build_context_source(),利用 git read-tree 将 pinned revision 的 tree 写入独立 index(docker-context.index),并拒绝 worktree 脏改动、staged 改动和仓库级 info/attributes(避免干扰内容哈希),要求 BUILDKITE_COMMIT 与 checkout HEAD 一致;随后所有 list_content_files/hash_content_file/compute_content_hash 都改为从该独立 index 和物化树读取,不再依赖可变 checkout,同时保留旧路径作为非 CI 回退(ROCM_BUILD_CONTEXT_ROOT 为空时行为不变)。
- 稳定的版本元数据:新增
describe_ci_revision() 与 write_ci_git_archival_metadata(),用 git describe --tags --long --abbrev=10 生成确定性版本串,替代复制整份 Git 历史来满足 setuptools_scm 的做法;docker/Dockerfile.rocm 中 setuptools_scm 版本检测改为依赖这些元数据。
- ROCm Triton kernels 单一来源:
docker/Dockerfile.rocm 新增 rocm-triton-kernels stage(ARG ROCM_TRITON_KERNELS_COMMIT=0f380657...),ADD 拉取 commit-pinned tar.gz,解包到 /opt/rocm-triton-kernels 后供 csrc-build 与 build_vllm_wheel_release 两个 stage 复用,并以 ENV TRITON_KERNELS_SRC_DIR 注入;两处构建前都会 grep -Fq "set(TRITON_KERNELS_TAG \"${ROCM_TRITON_KERNELS_COMMIT}\")" cmake/external_projects/triton_kernels.cmake,Docker 与 CMake 固定版本漂移时立即失败。
- 构建过程与缓存配套调整:csrc-build 和 final wheel 打包均加
PYTHONDONTWRITEBYTECODE=1 避免字节码污染;脚本内新增 ROCM_BUILD_CONTEXT_ROOT/ROCM_BUILD_CONTEXT_INDEX/ROCM_BUILD_CONTEXT_COMMIT/BAKE_ALLOW_ARGS/BUILD_CONTEXT_OVERRIDE_PATH 等变量;DEFAULT_ROCM_CSRC_DOCKERFILE_STAGES 加入 rocm-triton-kernels;缓存探测改用 Buildx imagetools 处理 cache-only refs;Rust cache 在原始 bake solve 内以 mode=min 直接刷新,删除日志解析段和第二次 repair solve;ROCm base 阶段保留紧凑 TTY、长源码构建用 plain progress 使 cache-import/fetch 失败可见。
- 测试配套:中途提交曾新增约 542 行单元测试,但最终提交
65ecd72 已撤销,恢复共享 Docker 元数据测试模块到 base 分支内容,PR 无最终测试文件变更。
关键文件:
.buildkite/scripts/ci-bake-rocm.sh(模块 CI 脚本;类别 other;类型 core-logic;符号 validate_ci_build_context_source, describe_ci_revision, write_ci_git_archival_metadata, git_fetch_with_timeout): ROCm CI bake 脚本主体改造:物化 canonical build context、基于 Git archive 元数据做版本管理、缓存探测与 Rust cache mode=min 刷新、删除日志解析与 repair solve,是本 PR 的核心逻辑所在(+313/-57)。
docker/Dockerfile.rocm(模块 Docker 构建;类别 infra;类型 infrastructure;符号 rocm-triton-kernels): 新增 rocm-triton-kernels 单一来源 stage、TRITON_KERNELS_SRC_DIR 注入、CMake/Docker pin 一致性 grep 校验,以及 PYTHONDONTWRITEBYTECODE 与 setuptools_scm 版本元数据配套,直接影响 ROCm wheel 构建行为。
关键符号:validate_ci_build_context_source, describe_ci_revision, write_ci_git_archival_metadata, git_fetch_with_timeout, list_content_files, hash_content_file, compute_content_hash
关键源码片段
docker/Dockerfile.rocm
新增 rocm-triton-kernels 单一来源 stage、TRITON_KERNELS_SRC_DIR 注入、CMake/Docker pin 一致性 grep 校验,以及 PYTHONDONTWRITEBYTECODE 与 setuptools_scm 版本元数据配套,直接影响 ROCm wheel 构建行为。
# 只拉取固定 commit 的 ROCm Triton kernels 包。放在 vLLM 源码 COPY 之前,
# 使原生源码变化时该下载层仍可复用;commit-pinned URL 本身是内容寻址。
FROM base AS rocm-triton-kernels
ARG ROCM_TRITON_KERNELS_COMMIT
ADD https://codeload.github.com/ROCm/triton/tar.gz/${ROCM_TRITON_KERNELS_COMMIT} \
/tmp/rocm-triton.tar.gz
RUN mkdir -p /opt/rocm-triton-kernels \
&& tar --extract --gzip --file /tmp/rocm-triton.tar.gz \
--directory /opt/rocm-triton-kernels --strip-components=4 \
--no-same-owner \
"triton-${ROCM_TRITON_KERNELS_COMMIT}/python/triton_kernels/triton_kernels" \
&& test -f /opt/rocm-triton-kernels/__init__.py \
&& rm /tmp/rocm-triton.tar.gz
# csrc-build 只复制影响 ROCm 原生扩展编译的文件,让无关的 CI/test/docs 改动
# 不 invalidate 昂贵的 HIP/C++ 构建层。Triton 源码目录作为构建输入注入。
FROM build_vllm_dependencies AS csrc-build
ARG ROCM_TRITON_KERNELS_COMMIT
COPY --from=rocm-triton-kernels \
/opt/rocm-triton-kernels /opt/rocm-triton-kernels
ENV TRITON_KERNELS_SRC_DIR=/opt/rocm-triton-kernels
# 构建前先校验 Docker 与 CMake 的 Triton pin 一致:grep 失败即整体构建失败,
# 避免两个 pin 漂移后产出的 wheel 携带不一致的 Triton 内核
RUN --mount=type=bind,source=pyproject.toml,target=${COMMON_WORKDIR}/vllm/pyproject.toml \
--mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
grep -Fq "set(TRITON_KERNELS_TAG \"${ROCM_TRITON_KERNELS_COMMIT}\")" \
cmake/external_projects/triton_kernels.cmake \
&& export CCACHE_BASEDIR="$PWD" \
&& echo "=== ccache stats before ROCm native build ===" \
&& (ccache --show-stats || true) \
&& (ccache --zero-stats || true) \
&& EFFECTIVE_MAX_JOBS="${MAX_JOBS:-$(nproc)}" \
&& echo "Building ROCm native extension wheel with MAX_JOBS=${EFFECTIVE_MAX_JOBS}" \
&& PYTHONDONTWRITEBYTECODE=1 LDFLAGS="-fuse-ld=mold" \
MAX_JOBS="${EFFECTIVE_MAX_JOBS}" python3 setup.py bdist_wheel --dist-dir=dist
评论区精华
review 评论区没有实质讨论:claude[bot] 仅提示仓库配置了手动 review 命令;shen-shanshan 直接 APPROVED,无评论文本。唯一可提炼的演进来自提交历史:0d42f3e 明确 Drop Triton archive checksum,PR body 中宣称的 SHA-256 校验最终以 commit-pinned URL 替代显式 checksum 校验,属于对可靠性与实现简洁性的权衡。
- Triton archive 的 SHA-256 校验被移除 (design): 以 commit-pinned URL 的内容寻址替代显式 checksum;PR body 与最终实现存在表述偏差,可能降低供应链防篡改强度。
- 新增 ROCm CI 单元测试被整体移除 (testing): PR 以缩小改动面、优先人工审核为准;ci-bake-rocm.sh 的核心逻辑(+313)最终没有任何自动化测试覆盖。
风险与影响
- 风险:主要风险如下:
1) .buildkite/scripts/ci-bake-rocm.sh 大改(+313/-57)且无最终单元测试覆盖,validate_ci_build_context_source() 的提交一致性/脏树/attributes 硬校验一旦误判,会导致整个 ROCm CI 在构建前失败;
2) docker/Dockerfile.rocm 新增 rocm-triton-kernels stage 与 TRITON_KERNELS_SRC_DIR 环境变量,若本地构建(非 CI)的 CMake 固定版本与默认 ARG 0f380657... 不一致,grep 校验会让构建直接失败;
3) 显式 checksum 被移除后,Triton archive 的完整性依赖 codeload 端 commit 寻址,若上游历史改写或网络中间人篡改,无额外校验兜底;
4) 物化 build context 依赖 git read-tree 与独立 index,若 source_root 与 BUILDKITE_COMMIT 因 merge commit 或 shallow clone 出现偏差,会立即 fail;
5) mode=min Rust cache 刷新路径改变后,cache 身份与回放逻辑是否完全等价依赖 Bake 行为,需要 ROCm CI 持续观测。
- 影响:影响范围限定在 ROCm CI/Docker 构建链:涉及
.buildkite/scripts/ci-bake-rocm.sh 与 docker/Dockerfile.rocm 两个文件,不影响运行时推理路径、模型代码或用户 API。对团队而言,收益是构建上下文规范化、源码缓存命中率提高、删除日志解析和二次修复 solve 后构建步骤更短更稳;对维护者,TRITON_KERNELS_SRC_DIR 环境变量会成为后续 ROCm 构建的隐藏依赖,且新增的 rocm-triton-kernels stage 会影响所有使用 Dockerfile.rocm 的镜像构建(CI 与非 CI)。
- 风险标记:基础设施核心路径变更, 无自动化测试覆盖, 构建配置强校验可能导致 CI 失败, 供应链校验被削弱(checksum 移除)
关联脉络
- PR #51735 [CI] Parallelize release image publishing: 同属 CI 构建链优化:该 PR 将 DockerHub 发布拆成并行矩阵,与本 PR 共用 bake/发布基础设施,共同构成 CI 链路稳定性与速度改进方向。
- PR #51184 [Docker] Cache test dependencies before vLLM install: 同为 Docker 构建缓存层优化(分层缓存、避免源码变更重装依赖),与本 PR 的源码 cache 复用主题一致。
- PR #51424 [Build] Skip precompiled wheel fetch during metadata hooks: 同属构建系统性能/缓存优化,处理 setup.py 元数据阶段的预编译 wheel 拉取问题,与本 PR 的 wheel 版本元数据改造相邻。
- PR #47030 [ROCm][DistInf] Enable vLLM DI CI with buildkite/slurm: ROCm CI 基础设施的既有奠基 PR,建立了 buildkite/slurm 测试套件,本 PR 在其上继续稳定 ROCm 构建路径。
参与讨论