执行摘要
- 一句话:修复 ROCm 预编译 wheel variant 检测,安装时按环境解析校验
- 推荐动作:值得 ROCm 相关维护者和构建基础设施工程师精读。核心设计亮点是「环境检测 × 发布集合 × 用户 override」三方交叉校验的 variant 解析策略,以及从 review 讨论中催生的 torch ABI 警告 UX(给出可复制的 pip/uv 命令)。可以关注
resolve_rocm_wheel_variant 的拒绝策略与 warn_if_rocm_torch_version_mismatch 的消息构造方式,对同类安装器/依赖解析代码有借鉴意义。
功能与动机
PR body 明确指出:"Fixes AMD: Python-only Installation failing because ROCm precompiled wheels on wheels.vllm.ai use a different path layout than CUDA." 旧代码中 determine_wheel_url_rocm 只有一条 TODO("When we have ROCm nightly wheels, we can update this logic.")并回退到 AMD PyPI;如今 wheels.vllm.ai 已发布 ROCm nightly wheels(目录为 /rocm/{commit}/{variant}/,且 torch、triton、aiter、flash-attn 等多个包并列存放),原安装逻辑无法解析该布局,导致 AMD Python-only 安装失败。
实现拆解
- 扩展 metadata 拉取逻辑:
setup.py 中 precompiled_wheel_utils.fetch_metadata_for_variant 新增 rocm: bool = False 关键字参数。CUDA 路径保持原行为;ROCm 路径下用新增的 LinkParser(HTMLParser 子类)抓取 https://wheels.vllm.ai/rocm/{commit}/{variant_dir} 页面中所有一级包目录(vllm、torch、triton、aiter 等),逐个拉取 metadata.json 并合并成单一列表,适配 ROCm 多包并存的布局。
- 新增 variant 检测与解析函数族:
rocm_version_to_variant(如 7.2.3 -> rocm723)、detect_system_rocm_variant(优先 get_rocm_version(),回退 torch.version.hip)、fetch_available_rocm_variants(正则 rocm\d+ 抓取发布集合)、resolve_rocm_wheel_variant(环境 variant 与用户 override、发布集合三方交叉校验,不匹配即返回 None)。
- 重构
determine_wheel_url_rocm:在本地 wheel 查找之后,新增从 wheels.vllm.ai 的 ROCm 布局解析 wheel 的路径:判断 commit 有效性、解析 variant、拉取合并 metadata,并在 metadata 中按 package_name == "vllm" 与架构匹配选取 wheel URL。variant 解析失败时不再依赖 AMD PyPI 的旧路径行为(原 AMD PyPI fallback 逻辑保留与否存在不确定性)。
- 新增
warn_if_rocm_torch_version_mismatch:对比当前安装的 torch 版本与 wheels.vllm.ai 发布的自定义 torch 构建版本,不一致时打印包含 torch 与 triton 精确版本的 pip/uv 安装命令,提示 ABI 可能不匹配。该逻辑源自 review 中 tjtanaa 的反馈,并由后续 commit 补全。
- 同步更新
tests/standalone_tests/python_only_compile.sh:预检脚本在 ROCm 环境(VLLM_TARGET_DEVICE=rocm 或存在 /opt/rocm 或 rocminfo)下,通过内嵌 Python 用 ctypes 读取 librocm-core.so 的 getROCmVersion 得到系统 ROCm 版本,与 wheels.vllm.ai 该 commit 的发布 variant 集合比对,构造正确的 metadata.json URL;环境 variant 无法检测或不匹配时直接报错退出。
- 测试配套:未新增独立单元测试,验证依赖 ROCm CI 中的 standalone 预检脚本(python_only_compile.sh)在真实构建环境下的执行,属于 CI 集成验证而非单测覆盖。
关键文件:
setup.py(模块 安装配置;类别 source;类型 dependency-wiring;符号 LinkParser, init, handle_starttag, rocm_version_to_variant): 核心变更文件:为 ROCm 预编译 wheel 新增运行时 variant 检测、发布校验与 torch ABI 警告逻辑,并扩展 metadata 拉取以适配 wheels.vllm.ai 的 ROCm 多包目录布局。
tests/standalone_tests/python_only_compile.sh(模块 安装测试;类别 test;类型 test-coverage;符号 get_rocm_version): CI 预检脚本同步实现 ROCm variant 解析,确保 Python-only 安装测试在 ROCm 环境下检查正确的 metadata.json URL;无编译器环境下通过 ctypes 读取 librocm-core.so 获取系统 ROCm 版本。
关键符号:rocm_version_to_variant, detect_system_rocm_variant, fetch_available_rocm_variants, resolve_rocm_wheel_variant, warn_if_rocm_torch_version_mismatch, fetch_metadata_for_variant, determine_wheel_url_rocm, get_rocm_version
关键源码片段
tests/standalone_tests/python_only_compile.sh
CI 预检脚本同步实现 ROCm variant 解析,确保 Python-only 安装测试在 ROCm 环境下检查正确的 metadata.json URL;无编译器环境下通过 ctypes 读取 librocm-core.so 获取系统 ROCm 版本。
# 仅在 ROCm 环境(目标设备或本机 ROCm 安装)下执行 variant 解析预检
if [[ "${_vllm_target_lower}" == "rocm" ]] || [[ -d /opt/rocm ]] || command -v rocminfo >/dev/null 2>&1; then
# 内嵌 Python:通过 ctypes 读取 librocm-core.so 的 getROCmVersion,
# 在无编译器、无 torch 的环境中也能拿到系统 ROCm 版本
_rocm_env_variant="$(python3 - <<'PY'
import ctypes
import os
from pathlib import Path
def get_rocm_version() -> str | None:
# 依次尝试 ROCM_HOME / ROCM_PATH / 默认安装路径 /opt/rocm
rocm_home = os.environ.get("ROCM_HOME") or os.environ.get("ROCM_PATH") or "/opt/rocm"
try:
librocm_core = Path(rocm_home) / "lib" / "librocm-core.so"
if not librocm_core.is_file():
return None
librocm = ctypes.CDLL(str(librocm_core))
get_rocm_core_version = librocm.getROCmVersion
major = ctypes.c_uint32()
minor = ctypes.c_uint32()
patch = ctypes.c_uint32()
if get_rocm_core_version(
ctypes.byref(major), ctypes.byref(minor), ctypes.byref(patch)
) == 0:
return f"{major.value}.{minor.value}.{patch.value}"
except Exception:
return None
return None
version = get_rocm_version()
if version:
# 输出形如 rocm723 的 variant 名
print(f"rocm{version.replace('.', '')}", end="")
PY
)"
# 从 wheels.vllm.ai 拉取该 commit 已发布的 ROCm variant 集合
_available_variants="$(curl -sf "https://wheels.vllm.ai/rocm/${merge_base_commit}/" \
| grep -oP 'rocm\d+' | sort -u | tr '\n' ' ' || true)"
# 用户显式指定的 variant 必须与系统环境一致,否则直接报错退出
if [[ -n "${VLLM_PRECOMPILED_WHEEL_VARIANT:-}" ]]; then
_rocm_variant="${VLLM_PRECOMPILED_WHEEL_VARIANT}"
if [[ -n "${_rocm_env_variant}" && "${_rocm_variant}" != "${_rocm_env_variant}" ]]; then
echo "ERROR: VLLM_PRECOMPILED_WHEEL_VARIANT=${_rocm_variant} does not match detected environment ROCm variant ${_rocm_env_variant}" >&2
exit 1
fi
else
_rocm_variant="${_rocm_env_variant}"
fi
# 环境 variant 必须存在于发布集合,否则预检失败
if [[ -z "${_available_variants}" ]] \
|| [[ " ${_available_variants} " != *" ${_rocm_variant} "* ]]; then
echo "ERROR: Environment ROCm variant '${_rocm_variant}' is not published for commit ${merge_base_commit} (available:${_available_variants:-none})" >&2
exit 1
fi
# 构造正确的 metadata.json URL,注意 ROCm 的路径布局与 CUDA 不同
meta_json_url="https://wheels.vllm.ai/rocm/${merge_base_commit}/${_rocm_variant}/vllm/metadata.json"
else
# CUDA 及默认路径保持原布局
meta_json_url="https://wheels.vllm.ai/${merge_base_commit}/vllm/metadata.json"
fi
评论区精华
核心讨论发生在 tjtanaa 对 setup.py 的 review 评论(line 840):他指出 wheels.vllm.ai 自定义的 PyPI endpoint 中存放了 torch、triton、aiter、flash-attn、vllm 等所有自定义包,而 "we are using a custom pytorch build. The torch-ABI might not match any official release even if we claim that we are at torch 2.11 here",因此要求增加检查:确保用户 torch 版本与 wheels.vllm.ai 发布版本一致,否则在警告信息中给出完整的 pip/uv 安装命令让用户从 vLLM 索引安装 torch 与 triton。aarushjain29 回复 "Fixed!",随后 tjtanaa 自己提交了 950d4d("complete the torch abi check logic")并合并进本 PR,最终 APPROVE。没有遗留未解决疑虑,但安装时仅警告不阻断的取舍值得注意。
- wheels.vllm.ai 自定义 torch 构建的 ABI 兼容性检查 (correctness): 已实现 warn_if_rocm_torch_version_mismatch,并在后续 commit 950d4d(tjtanaa 的 "complete the torch abi check logic")中补全;aarushjain29 回复 "Fixed!",tjtanaa 最终 APPROVE。
风险与影响
关联脉络
- PR #50620 [Bugfix][NIXL] Include transfer mode (push/pull) in the compatibility hash: 同为围绕 wheels.vllm.ai precompiled wheel 与 metadata 机制的构建基础设施变更,涉及 wheels.vllm.ai 上 metadata 的生成与消费,与本 PR 共用同一发布基础设施,体现 ROCm/NIXL wheel 发布链路的持续演进。
- PR #51280 [ROCm][CI] Solidify entrypoint LLM lifecycle: 同为 ROCm CI 稳定性改进(修复显存回收与测试生命周期),与本 PR 的 python_only_compile.sh 预检脚本同属 ROCm CI 基础设施加固方向。
参与讨论