已合并
chore(docker): 评测镜像默认升到 CANN 9.1.0, 并让报告的 docker 字段属实 #270
Xinxian Chen创建于 8月17日
chore(docker): 评测镜像默认升到 CANN 9.1.0, 并让报告的 docker 字段属实 #270
已合并
Xinxian Chen创建于 8月17日
共 22 个文件变更+357-147
@@ -3,7 +3,10 @@
3# WHY toolkit-only (no ops/nnal): direct-launch (bisheng-compiled AscendC/CCE kernels launched3# WHY toolkit-only (no ops/nnal): direct-launch (bisheng-compiled AscendC/CCE kernels launched
4# via `<<<>>>`) never calls aclnn, so ops (libopapi + kernel binaries) and nnal (ATB/SiP) are dead4# via `<<<>>>`) never calls aclnn, so ops (libopapi + kernel binaries) and nnal (ATB/SiP) are dead
5# weight. Verified on 910b: torch_npu imports + npu memcpy works with libopapi absent.5# weight. Verified on 910b: torch_npu imports + npu memcpy works with libopapi absent.
6-# Pairing (Ascend/pytorch compat table): torch_npu 2.10.0.post2 <-> torch 2.10 <-> CANN 9.0.x, py3.13 cp313.6+# Pairing (Ascend/pytorch COMPATIBILITY.md): torch_npu 2.10.0.post4 <-> torch 2.10.0 <-> CANN 9.1.0, py3.13.
7+# The torch_npu 2.10 line pairs ONLY with 9.1.0 -- that table has no 9.0.1 row at all, and the
8+# 2.10.0.post2 this image used to pin appears under no CANN version. Move the two together or you
9+# land off-table again.
7 10 
8# ----------------------------------------------------------------------------------------------------------11# ----------------------------------------------------------------------------------------------------------
9# Mirror / version knobs -- every one DEFAULTS to the official/global source; pass --build-arg to swap to an12# Mirror / version knobs -- every one DEFAULTS to the official/global source; pass --build-arg to swap to an
@@ -26,7 +29,7 @@ ARG APT_MIRROR=
26ARG UV_PYTHON_INSTALL_MIRROR=29ARG UV_PYTHON_INSTALL_MIRROR=
27ARG PYPI_MIRROR=30ARG PYPI_MIRROR=
28ARG TORCH_MIRROR=31ARG TORCH_MIRROR=
29-ARG CANN_VERSION=9.0.132+ARG CANN_VERSION=9.1.0
30# CANN_VERSION alone is enough to move versions -- the toolkit .run and its <arch> variants follow one33# CANN_VERSION alone is enough to move versions -- the toolkit .run and its <arch> variants follow one
31# naming scheme on ascend-repo, verified present for 9.1.0 in both architectures. CANN_TOOLKIT_URL is34# naming scheme on ascend-repo, verified present for 9.1.0 in both architectures. CANN_TOOLKIT_URL is
32# the escape hatch for the releases that do not: some land on the ascend-cann-open bucket instead35# the escape hatch for the releases that do not: some land on the ascend-cann-open bucket instead
@@ -26,7 +26,7 @@ AscendHub per-device 镜像)。
26 26 
27```bash27```bash
28cd docker/base/28cd docker/base/
29-docker build --build-arg ARCH=$(uname -m) -t cann-toolkit-base:9.0.1-py3.13 .29+docker build --build-arg ARCH=$(uname -m) -t cann-toolkit-base:9.1.0-py3.13 .
30```30```
31 31 
32镜像架构由 **`ARCH` build-arg** 决定(`aarch64` / `x86_64`,默认 `aarch64`),**必须在目标架构的32镜像架构由 **`ARCH` build-arg** 决定(`aarch64` / `x86_64`,默认 `aarch64`),**必须在目标架构的
@@ -48,38 +48,49 @@ python 依赖由
48| `UV_PYTHON_INSTALL_MIRROR` | (空 = github releases) | `https://mirror.nju.edu.cn/github-release/astral-sh/python-build-standalone` |48| `UV_PYTHON_INSTALL_MIRROR` | (空 = github releases) | `https://mirror.nju.edu.cn/github-release/astral-sh/python-build-standalone` |
49| `PYPI_MIRROR` | (空 = `files.pythonhosted.org`) | `https://mirrors.huaweicloud.com/repository/pypi` |49| `PYPI_MIRROR` | (空 = `files.pythonhosted.org`) | `https://mirrors.huaweicloud.com/repository/pypi` |
50| `TORCH_MIRROR` | (空 = `download.pytorch.org`) | `https://mirror.nju.edu.cn/pytorch/whl/cpu` |50| `TORCH_MIRROR` | (空 = `download.pytorch.org`) | `https://mirror.nju.edu.cn/pytorch/whl/cpu` |
51-| `CANN_VERSION` | `9.0.1` | toolkit `.run` 版本(从 OBS 拉取);落到 `ENV CANN_VERSION` 供 `docker/eval` 继承 |51+| `CANN_VERSION` | `9.1.0` | toolkit `.run` 版本(从 OBS 拉取);落到 `ENV CANN_VERSION` 供 `docker/eval` 继承 |
52| `CANN_TOOLKIT_URL` | 空(由 `CANN_VERSION` + `ARCH` 推导) | 只在该版本不按常规命名/不在常规 bucket 时设,见下 |52| `CANN_TOOLKIT_URL` | 空(由 `CANN_VERSION` + `ARCH` 推导) | 只在该版本不按常规命名/不在常规 bucket 时设,见下 |
53| `ARCH` | `aarch64` | `aarch64` / `x86_64`;决定 toolkit `.run`、`<arch>-linux/` 路径,并落到 `ENV CANN_ARCH` |53| `ARCH` | `aarch64` | `aarch64` / `x86_64`;决定 toolkit `.run`、`<arch>-linux/` 路径,并落到 `ENV CANN_ARCH` |
54 54 
55### 换 CANN 版本55### 换 CANN 版本
56 56 
57正常只需 `--build-arg CANN_VERSION=<版本>` —— toolkit 和 ops 两个包在57正常只需 `--build-arg CANN_VERSION=<版本>` —— toolkit 和 ops 两个包在
58-`ascend-repo.obs.cn-east-2` 上的命名跨版本一致(9.1.0 的 toolkit/ops × aarch64/x86_64 四个包58+`ascend-repo.obs.cn-east-2` 上的命名跨版本一致,`docker/eval` 会继承 `ENV CANN_VERSION`
59-均已核实存在),`docker/eval` 会继承 `ENV CANN_VERSION` 去推导同版本的 ops:59+去推导同版本的 ops:
60 60 
61```bash61```bash
62# base62# base
63-docker build --build-arg CANN_VERSION=9.1.0 --build-arg ARCH=$(uname -m) \63+docker build --build-arg CANN_VERSION=<版本> --build-arg ARCH=$(uname -m) \
64- -t cann-toolkit-base:9.1.0-py3.13 .64+ -t cann-toolkit-base:<版本>-py3.13 .
65# eval (build.sh 用 CANN_VERSION 只是为了拼 BASE_IMAGE 的 tag)65# eval (build.sh 用 CANN_VERSION 只是为了拼 BASE_IMAGE 的 tag)
66-CANN_VERSION=9.1.0 NPU_ARCH=ascend950 bash ../eval/build.sh66+CANN_VERSION=<版本> NPU_ARCH=ascend950 bash ../eval/build.sh
67```67```
68 68 
69+**换版本时 `torch_npu` 要按[官方配套表](https://gitcode.com/Ascend/pytorch/blob/master/COMPATIBILITY.md)
70+重新选**:把 `docker/base/pyproject.toml` 与 `docker/eval/pyproject.toml` 的 `torch-npu` 改成
71+新 CANN 版本在表里对应的串号,再重新 `uv lock`。表里没有对应行的 CANN 版本不要用 —— 那样钉出来
72+的组合官方没有验证过,理由见下一节。
73+ 
69`CANN_TOOLKIT_URL` 是给例外准备的:部分版本发在 `ascend-cann-open.obs.cn-north-4` 上,74`CANN_TOOLKIT_URL` 是给例外准备的:部分版本发在 `ascend-cann-open.obs.cn-north-4` 上,
70或以合并包 `Ascend-cann_<版本>_linux-<arch>.run` 的形式发布(而非 `Ascend-cann-toolkit_...`)。75或以合并包 `Ascend-cann_<版本>_linux-<arch>.run` 的形式发布(而非 `Ascend-cann-toolkit_...`)。
71 76 
72-**9.1.0 实测过**(q7 / 910B2 / aarch64):只加 `--build-arg CANN_VERSION=9.1.0`,base + eval77+### 为什么是 9.1.0 + torch_npu 2.10.0.post4
73-(`OPS_MODE=refonly`,顺带验了 9.1.0 的 ops 包)全部建成,`--self-test` 全绿、内置算子仍被挡住,78+ 
74-一次真实三阶段评测 4/4 通过、得分 74.10(9.0.1 同一提交同一算子是 73.00)。安装布局也没变79+[官方配套表](https://gitcode.com/Ascend/pytorch/blob/master/COMPATIBILITY.md)里 torch_npu
75-(`cann-9.1.0/` + `latest` 符号链接 + `ascend-toolkit/set_env.sh`),`torch_npu 2.10.0.post2`80+2.10 这条线**只配 CANN 9.1.0**(`2.10.0.post4` ↔ torch `2.10.0` ↔ CANN `9.1.0`),表里没有
76-虽然官方对表写的是 CANN 9.0.x,在 9.1.0 上导入、认卡、H2D、编译提交都正常。81+9.0.1 这一行,`2.10.0.post2` 也不在表内。所以本镜像此前的 `9.0.1 + 2.10.0.post2` 是表外组合;
82+现在这一档是第一次落在表内。Python 3.13 在该行的支持范围内。
83+ 
84+9.1.0 的 toolkit/ops × aarch64/x86_64 四个包均已核实存在。实测(q7 / 910B2 / aarch64):
85+base + eval(`OPS_MODE=refonly`,顺带验了 9.1.0 的 ops 包)全部建成,`--self-test` 全绿、
86+内置算子仍被挡住,一次真实三阶段评测 4/4 通过、得分 74.10(9.0.1 同一提交同一算子是 73.00)。
87+安装布局也没变(`cann-9.1.0/` + `latest` 符号链接 + `ascend-toolkit/set_env.sh`)。
77 88 
78`PYPI_MIRROR`/`TORCH_MIRROR` 就地改写 `uv.lock` 里的 canonical wheel URL(**同 hash**,`--frozen` 仍校验),89`PYPI_MIRROR`/`TORCH_MIRROR` 就地改写 `uv.lock` 里的 canonical wheel URL(**同 hash**,`--frozen` 仍校验),
79换源不破坏可复现性。CN 全量示例:90换源不破坏可复现性。CN 全量示例:
80 91 
81```bash92```bash
82-docker build -t cann-toolkit-base:9.0.1-py3.13 \93+docker build -t cann-toolkit-base:9.1.0-py3.13 \
83 --build-arg BASE_OS=docker.m.daocloud.io/library/debian:12-slim \94 --build-arg BASE_OS=docker.m.daocloud.io/library/debian:12-slim \
84 --build-arg APT_MIRROR=mirrors.huaweicloud.com \95 --build-arg APT_MIRROR=mirrors.huaweicloud.com \
85 --build-arg UV_IMAGE=ghcr.m.daocloud.io/astral-sh/uv:0.11.29 \96 --build-arg UV_IMAGE=ghcr.m.daocloud.io/astral-sh/uv:0.11.29 \
@@ -11,7 +11,7 @@ version = "0"
11requires-python = "==3.13.*"11requires-python = "==3.13.*"
12dependencies = [12dependencies = [
13 "torch==2.10.0",13 "torch==2.10.0",
14- "torch-npu==2.10.0.post2",14+ "torch-npu==2.10.0.post4",
15 "numpy", "pyyaml", "decorator", "attrs", "scipy", "cloudpickle", "ml-dtypes", "psutil",15 "numpy", "pyyaml", "decorator", "attrs", "scipy", "cloudpickle", "ml-dtypes", "psutil",
16 "filelock", "typing-extensions", "sympy", "networkx", "jinja2", "fsspec", "mpmath", "markupsafe",16 "filelock", "typing-extensions", "sympy", "networkx", "jinja2", "fsspec", "mpmath", "markupsafe",
17 "pip", "setuptools", "wheel", "build",17 "pip", "setuptools", "wheel", "build",
@@ -15,7 +15,7 @@
15set -euo pipefail15set -euo pipefail
16cd "$(dirname "$0")"16cd "$(dirname "$0")"
17 17 
18-IMAGE="${IMAGE:-cann-toolkit-base:9.0.1-py3.13}"18+IMAGE="${IMAGE:-cann-toolkit-base:9.1.0-py3.13}"
19MODE="${1:-smoke}"19MODE="${1:-smoke}"
20 20 
21DRV=/usr/local/Ascend/driver/lib64/driver:/usr/local/Ascend/driver/lib6421DRV=/usr/local/Ascend/driver/lib64/driver:/usr/local/Ascend/driver/lib64
@@ -80,7 +80,7 @@ requires-dist = [
80 { name = "setuptools" },80 { name = "setuptools" },
81 { name = "sympy" },81 { name = "sympy" },
82 { name = "torch", specifier = "==2.10.0", index = "https://download.pytorch.org/whl/cpu" },82 { name = "torch", specifier = "==2.10.0", index = "https://download.pytorch.org/whl/cpu" },
83- { name = "torch-npu", specifier = "==2.10.0.post2" },83+ { name = "torch-npu", specifier = "==2.10.0.post4" },
84 { name = "typing-extensions" },84 { name = "typing-extensions" },
85 { name = "wheel" },85 { name = "wheel" },
86]86]
@@ -314,14 +314,14 @@ wheels = [
314 314 
315[[package]]315[[package]]
316name = "torch-npu"316name = "torch-npu"
317-version = "2.10.0.post2"317+version = "2.10.0.post4"
318source = { registry = "https://pypi.org/simple" }318source = { registry = "https://pypi.org/simple" }
319dependencies = [319dependencies = [
320 { name = "torch" },320 { name = "torch" },
321]321]
322wheels = [322wheels = [
323- { url = "https://files.pythonhosted.org/packages/9c/67/438d901072bb339c8c732e3635c49dcc8489d695aa59c78945001b057aa2/torch_npu-2.10.0.post2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:157c2c7b59497dd70846b5e8038e142bcea6fd13a9072159732e3b8004593d48", size = 32522503, upload-time = "2026-07-02T02:24:00.506Z" },323+ { url = "https://files.pythonhosted.org/packages/aa/8a/525206571e3a0f9a36363ae55a424b34bac790c8ce10129051e7e8336be6/torch_npu-2.10.0.post4-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2d88ce46c69cfa562453925865805ca8c358cea31176ff9b284e7851eda213d0", size = 36258846, upload-time = "2026-07-27T07:30:49.174Z" },
324- { url = "https://files.pythonhosted.org/packages/92/ff/80eb5e6b8788dd8e5d0c9c75b780a176f1a32e49e4ba90889584877c3446/torch_npu-2.10.0.post2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:8f6eac66b9db2d956b5136f5e072d5fb7c0524bcaa90d6a3ac71a044705d475b", size = 35881624, upload-time = "2026-07-02T02:24:17.603Z" },324+ { url = "https://files.pythonhosted.org/packages/48/a5/c7c2fc0139c55393d9ff3116b0c6ec62bf5ea6257f1a64515927e31dcd27/torch_npu-2.10.0.post4-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e6ac70748c9d03312afb1fc5cf84b69d1b955a59555116e286cf7a10a302be9e", size = 39987520, upload-time = "2026-07-27T07:31:25.567Z" },
325]325]
326 326 
327[[package]]327[[package]]
@@ -3,21 +3,34 @@
3# 多平台支持:通过 --build-arg 切换 CANN 版本和硬件型号。3# 多平台支持:通过 --build-arg 切换 CANN 版本和硬件型号。
4#4#
5# 示例:5# 示例:
6-# docker build --network=host -t cann-bench:cann9.0.0-910b-latest \6+# docker build --network=host -t cann-bench:cann9.1.0-910b-latest \
7-# --build-arg CANN_VERSION=9.0.0 --build-arg DEVICE=910b .7+# --build-arg CANN_VERSION=9.1.0 --build-arg DEVICE=910b .
8#8#
9-# docker build --network=host -t cann-bench:cann9.0.0-950-latest \9+# docker build --network=host -t cann-bench:cann9.1.0-950-latest \
10-# --build-arg CANN_VERSION=9.0.0 --build-arg DEVICE=950 .10+# --build-arg CANN_VERSION=9.1.0 --build-arg DEVICE=950 .
11#11#
12-# 可用 DEVICE 值:910b / 910c / 950 等(对应 AscendHub 镜像 tag 中的硬件段)12+# 完整镜像 tag 格式:cann:<CANN_VERSION>-<DEVICE>-ubuntu22.04-py3.12-<VARIANT>
13-# 完整镜像 tag 格式:cann:<CANN_VERSION>-<DEVICE>-ubuntu22.04-py3.1213+# 2026-08-17 在 AscendHub 上核实过的取值:
14+# CANN_VERSION 9.0.1 / 9.1.0(9.0.0 的 tag 已下架 —— 本文件此前的默认值就指向它,
15+# 也就是说这个镜像已经建不出来了;9.2.0 尚未发布)
16+# DEVICE 910 / 910b / 950 / a3 / 310p(910c 不存在,旧注释里写错了)
17+# VARIANT devel(含编译工具链,评测要编提交,选它)/ runtime 系列
18+# 9.1.0-910b 与 9.1.0-950 的 -devel 均为 arm64 + amd64 双架构。
19+#
20+# 版本配套:CANN 9.1.0 这一行是 torch 2.10.0 <-> torch_npu 2.10.0.post4(另有 2.11 / 2.12
21+# 两条线),见 https://gitcode.com/Ascend/pytorch/blob/master/COMPATIBILITY.md
22+# torch/torch_npu 由下面显式安装并钉版本,不依赖基础镜像自带的串号;换 CANN_VERSION 时
23+# 必须按配套表同步改 TORCH_VERSION / TORCH_NPU_VERSION,否则 ABI 不配套。
24+# 两者落到 ENV,由 test_env.py 回读实际装到的版本校验,文本改错会在 smoke 阶段红。
14 25 
15-ARG CANN_VERSION=9.0.026+ARG CANN_VERSION=9.1.0
16ARG DEVICE=910b27ARG DEVICE=910b
28+# devel 才带编译工具链;AscendHub 从某个版本起把它拆成了单独的 tag 后缀。
29+ARG VARIANT=devel
17ARG TRITON_ASCEND_VERSION=30ARG TRITON_ASCEND_VERSION=
18ARG TRITON_ASCEND_INDEX_URL=https://triton-ascend.osinfra.cn/pypi/simple31ARG TRITON_ASCEND_INDEX_URL=https://triton-ascend.osinfra.cn/pypi/simple
19 32 
20-FROM swr.cn-south-1.myhuaweicloud.com/ascendhub/cann:${CANN_VERSION}-${DEVICE}-ubuntu22.04-py3.1233+FROM swr.cn-south-1.myhuaweicloud.com/ascendhub/cann:${CANN_VERSION}-${DEVICE}-ubuntu22.04-py3.12-${VARIANT}
21 34 
22ARG TRITON_ASCEND_VERSION35ARG TRITON_ASCEND_VERSION
23ARG TRITON_ASCEND_INDEX_URL36ARG TRITON_ASCEND_INDEX_URL
@@ -45,6 +58,12 @@ RUN curl -LSf https://astral.sh/uv/install.sh | sh && \
45ARG PYPI_INDEX_URL=58ARG PYPI_INDEX_URL=
46ENV UV_INDEX_URL=${PYPI_INDEX_URL}59ENV UV_INDEX_URL=${PYPI_INDEX_URL}
47 60 
61+# 与 CANN_VERSION 配套的 torch 栈,见文件头的配套表链接。
62+ARG TORCH_VERSION=2.10.0
63+ARG TORCH_NPU_VERSION=2.10.0.post4
64+ENV CANN_BENCH_TORCH_VERSION=${TORCH_VERSION}
65+ENV CANN_BENCH_TORCH_NPU_VERSION=${TORCH_NPU_VERSION}
66+ 
48# torch_npu install needs these at build time to locate driver libs.67# torch_npu install needs these at build time to locate driver libs.
49ENV ASCEND_HOME_PATH=/usr/local/Ascend/ascend-toolkit/latest68ENV ASCEND_HOME_PATH=/usr/local/Ascend/ascend-toolkit/latest
50ENV LD_LIBRARY_PATH=/usr/local/Ascend/driver/lib64/common/:/usr/local/Ascend/driver/lib64/driver/:${ASCEND_HOME_PATH}/aarch64-linux/lib6469ENV LD_LIBRARY_PATH=/usr/local/Ascend/driver/lib64/common/:/usr/local/Ascend/driver/lib64/driver/:${ASCEND_HOME_PATH}/aarch64-linux/lib64
@@ -55,8 +74,8 @@ RUN uv pip install --system --index-url ${PYPI_INDEX_URL:-https://mirrors.huawei
55 numpy pyyaml decorator scipy attrs cloudpickle \74 numpy pyyaml decorator scipy attrs cloudpickle \
56 ml-dtypes psutil tornado pandas expecttest protobuf \75 ml-dtypes psutil tornado pandas expecttest protobuf \
57 pytest pytest-timeout 'ruamel.yaml>=0.18' build setuptools wheel76 pytest pytest-timeout 'ruamel.yaml>=0.18' build setuptools wheel
58-RUN uv pip install --system --no-deps --index-url https://download.pytorch.org/whl/cpu torch==2.10.077+RUN uv pip install --system --no-deps --index-url https://download.pytorch.org/whl/cpu torch==${TORCH_VERSION}
59-RUN uv pip install --system --no-deps --index-url ${PYPI_INDEX_URL:-https://mirrors.huaweicloud.com/repository/pypi/simple/} torch_npu==2.10.078+RUN uv pip install --system --no-deps --index-url ${PYPI_INDEX_URL:-https://mirrors.huaweicloud.com/repository/pypi/simple/} torch_npu==${TORCH_NPU_VERSION}
60 79 
61# Triton-Ascend is optional because its compiler runtime is large. The wheel80# Triton-Ascend is optional because its compiler runtime is large. The wheel
62# owns the top-level `triton` package, so install it and its pinned dependencies81# owns the top-level `triton` package, so install it and its pinned dependencies
@@ -4,16 +4,30 @@
4> 本镜像基于 AscendHub 完整 CANN(含 ops/nnal),定位是**需要内置算子的交互调试**、4> 本镜像基于 AscendHub 完整 CANN(含 ops/nnal),定位是**需要内置算子的交互调试**、
5> Triton-Ascend smoke,以及历史 CI。它不自带 harness,仍需挂一棵 cann-bench 工作树进来。5> Triton-Ascend smoke,以及历史 CI。它不自带 harness,仍需挂一棵 cann-bench 工作树进来。
6 6 
7-CANN-BENCH 参考执行镜像。torch 2.10.0 + torch\_npu 2.10.0 + 相关科学计算栈。7+CANN-BENCH 参考执行镜像。torch 2.10.0 + torch\_npu 2.10.0.post4 + 相关科学计算栈。
8通过 `--build-arg` 参数化 CANN 版本和硬件型号,同一 Dockerfile 适配不同设备。8通过 `--build-arg` 参数化 CANN 版本和硬件型号,同一 Dockerfile 适配不同设备。
9 9 
10| 参数 | 默认值 | 说明 |10| 参数 | 默认值 | 说明 |
11|------|--------|------|11|------|--------|------|
12-| `CANN_VERSION` | `9.0.0` | CANN toolkit 版本 |12+| `CANN_VERSION` | `9.1.0` | CANN toolkit 版本 |
13-| `DEVICE` | `910b` | 硬件型号(910b / 910c / 950 等,对应 AscendHub 镜像 tag) |13+| `DEVICE` | `910b` | 硬件型号(910 / 910b / 950 / a3 / 310p,对应 AscendHub 镜像 tag 的硬件段) |
14| `TRITON_ASCEND_VERSION` | 空 | 可选 Triton-Ascend 版本;当前验证版本为 `3.2.1` |14| `TRITON_ASCEND_VERSION` | 空 | 可选 Triton-Ascend 版本;当前验证版本为 `3.2.1` |
15+| `VARIANT` | `devel` | AscendHub tag 的末段;`devel` 才带编译工具链,评测要编提交 |
16+| `TORCH_VERSION` | `2.10.0` | 与 `CANN_VERSION` 配套,见下 |
17+| `TORCH_NPU_VERSION` | `2.10.0.post4` | 同上 |
15 18 
16-默认 tag `cann-bench:cann9.0.0-910b-latest`。19+torch 栈**不**取基础镜像自带的串号,由 Dockerfile 显式安装并钉死。改 `CANN_VERSION` 时这两个
20+要一起按[官方配套表](https://gitcode.com/Ascend/pytorch/blob/master/COMPATIBILITY.md)改
21+(9.1.0 这一行是 torch `2.10.0` <-> torch_npu `2.10.0.post4`)。两个值会落到镜像的
22+`CANN_BENCH_TORCH_VERSION` / `CANN_BENCH_TORCH_NPU_VERSION`,`test_env.py` 的 [1] 会回读
23+实际装到的版本比对 —— 钉错或被上游覆盖,`run.sh smoke` 就红。
24+ 
25+默认 tag `cann-bench:cann9.1.0-910b-latest`,基础镜像是
26+`ascendhub/cann:9.1.0-910b-ubuntu22.04-py3.12-devel`(arm64 + amd64 双架构)。
27+ 
28+> 上游 tag 会下架:`9.0.0-910b-ubuntu22.04-py3.12`(本文件此前的默认)在 2026-08-17
29+> 核查时已不存在,即那个默认值已经建不出镜像。换版本前先 `docker manifest inspect`
30+> 确认 tag 还在。
17 31 
18- `Dockerfile` — 镜像定义(ARG 参数化)32- `Dockerfile` — 镜像定义(ARG 参数化)
19- `entrypoint.sh` — 容器入口 (source CANN env, 转交 CMD)33- `entrypoint.sh` — 容器入口 (source CANN env, 转交 CMD)
@@ -33,25 +47,25 @@ cd /path/to/repo/docker/dev/
33### 910B(默认)47### 910B(默认)
34 48 
35```bash49```bash
36-docker build --network=host -t cann-bench:cann9.0.0-910b-latest .50+docker build --network=host -t cann-bench:cann9.1.0-910b-latest .
37```51```
38 52 
39### 950PR53### 950PR
40 54 
41```bash55```bash
42docker build --network=host \56docker build --network=host \
43- --build-arg CANN_VERSION=9.0.0 --build-arg DEVICE=950 \57+ --build-arg CANN_VERSION=9.1.0 --build-arg DEVICE=950 \
44- -t cann-bench:cann9.0.0-950-latest .58+ -t cann-bench:cann9.1.0-950-latest .
45```59```
46 60 
47### Triton-Ascend(910B / 950PR)61### Triton-Ascend(910B / 950PR)
48 62 
49```bash63```bash
50docker build --network=host \64docker build --network=host \
51- --build-arg CANN_VERSION=9.0.0 \65+ --build-arg CANN_VERSION=9.1.0 \
52 --build-arg DEVICE=950 \66 --build-arg DEVICE=950 \
53 --build-arg TRITON_ASCEND_VERSION=3.2.1 \67 --build-arg TRITON_ASCEND_VERSION=3.2.1 \
54- -t cann-bench:cann9.0.0-950-triton3.2.1 .68+ -t cann-bench:cann9.1.0-950-triton3.2.1 .
55```69```
56 70 
57设置该参数后,镜像 smoke 会实际 JIT 编译并运行 Triton vector add,而不只是检查 import。71设置该参数后,镜像 smoke 会实际 JIT 编译并运行 Triton vector add,而不只是检查 import。
@@ -60,7 +74,7 @@ docker build --network=host \
60```bash74```bash
61docker build --network=host \75docker build --network=host \
62 --build-arg HTTP_PROXY --build-arg HTTPS_PROXY \76 --build-arg HTTP_PROXY --build-arg HTTPS_PROXY \
63- -t cann-bench:cann9.0.0-910b-latest .77+ -t cann-bench:cann9.1.0-910b-latest .
64```78```
65 79 
66也可配置 pypi 镜像源: `--build-arg PYPI_INDEX_URL`。80也可配置 pypi 镜像源: `--build-arg PYPI_INDEX_URL`。
@@ -72,9 +86,9 @@ docker build --network=host \
72```bash86```bash
73bash run.sh smoke87bash run.sh smoke
74# 或指定 950PR 镜像:88# 或指定 950PR 镜像:
75-IMAGE=cann-bench:cann9.0.0-950-latest bash run.sh smoke89+IMAGE=cann-bench:cann9.1.0-950-latest bash run.sh smoke
76# Triton-Ascend image:90# Triton-Ascend image:
77-IMAGE=cann-bench:cann9.0.0-950-triton3.2.1 bash run.sh smoke91+IMAGE=cann-bench:cann9.1.0-950-triton3.2.1 bash run.sh smoke
78```92```
79 93 
80期望 `ALL CHECKS PASSED`。94期望 `ALL CHECKS PASSED`。
@@ -103,6 +117,6 @@ Override: `CONTAINER=<name> WORKSPACE=<host-path> bash run.sh dev`。
103 117 
104| 变量 | 默认 |118| 变量 | 默认 |
105|-------------|-----------------------------------|119|-------------|-----------------------------------|
106-| `IMAGE` | `cann-bench:cann9.0.0-910b-latest` |120+| `IMAGE` | `cann-bench:cann9.1.0-910b-latest` |
107| `CONTAINER` | `cann-bench` (仅 dev) |121| `CONTAINER` | `cann-bench` (仅 dev) |
108| `WORKSPACE` | `$(pwd)/workspace` (仅 dev) |122| `WORKSPACE` | `$(pwd)/workspace` (仅 dev) |
@@ -7,7 +7,7 @@ source /usr/local/Ascend/ascend-toolkit/set_env.sh 2>/dev/null || true
7 7 
8if [[ $# -eq 0 ]]; then8if [[ $# -eq 0 ]]; then
9 cat <<EOF9 cat <<EOF
10-Usage: docker run --rm cann-bench:cann9.0.0-* <command> [args...]10+Usage: docker run --rm cann-bench:cann9.1.0-* <command> [args...]
11 python3 /test_env.py # post-build smoke11 python3 /test_env.py # post-build smoke
12 bash # interactive shell12 bash # interactive shell
13EOF13EOF
@@ -4,12 +4,12 @@
4# bash run.sh shell # one-shot interactive shell with NPU bound in4# bash run.sh shell # one-shot interactive shell with NPU bound in
5# bash run.sh dev # detached sleep infinity for docker exec debugging5# bash run.sh dev # detached sleep infinity for docker exec debugging
6#6#
7-# 指定镜像: IMAGE=cann-bench:cann9.0.0-950-latest bash run.sh smoke7+# 指定镜像: IMAGE=cann-bench:cann9.1.0-950-latest bash run.sh smoke
8 8 
9set -euo pipefail9set -euo pipefail
10cd "$(dirname "$0")"10cd "$(dirname "$0")"
11 11 
12-IMAGE="${IMAGE:-cann-bench:cann9.0.0-910b-latest}"12+IMAGE="${IMAGE:-cann-bench:cann9.1.0-910b-latest}"
13MODE="${1:-smoke}"13MODE="${1:-smoke}"
14 14 
15NPU_FLAGS=(15NPU_FLAGS=(
@@ -1,8 +1,9 @@
1#!/usr/bin/env python31#!/usr/bin/env python3
2-"""Post-build smoke for cann-bench:cann9.0.0-* execution image.2+"""Post-build smoke for cann-bench:cann9.1.0-* execution image.
3 3 
4Verifies in order:4Verifies in order:
5- [1] python / torch / torch_npu importable, log versions5+ [1] python / torch / torch_npu importable, and the installed torch stack
6+ matches the CANN-matched pins the image was built with
6 [2] torch_npu can see at least one NPU device7 [2] torch_npu can see at least one NPU device
7 [3] npu-smi info works (driver/runtime loaded)8 [3] npu-smi info works (driver/runtime loaded)
8 [4] CANN compiler version.info readable (proves CANN install intact)9 [4] CANN compiler version.info readable (proves CANN install intact)
@@ -17,12 +18,26 @@ import sys
17 18 
18failed = []19failed = []
19 20 
20-# [1] python/torch/torch_npu versions21+# [1] python/torch/torch_npu versions. The Dockerfile pins torch and torch_npu
22+# to the row the base CANN version occupies in the official compatibility table
23+# and echoes those pins into CANN_BENCH_TORCH*_VERSION. Comparing the installed
24+# distributions against them catches a build that silently resolved to a
25+# different build number — the ABI mismatch that table exists to prevent. The
26+# distribution version is what the pin acts on, so read it rather than
27+# __version__; its local label ("+cpu") is not part of the pairing.
21try:28try:
29+ import importlib.metadata
30+ 
22 import torch31 import torch
23 import torch_npu32 import torch_npu
24 33 
25 py = ".".join(str(v) for v in sys.version_info[:3])34 py = ".".join(str(v) for v in sys.version_info[:3])
35+ for dist, want in (
36+ ("torch", os.environ.get("CANN_BENCH_TORCH_VERSION", "")),
37+ ("torch-npu", os.environ.get("CANN_BENCH_TORCH_NPU_VERSION", "")),
38+ ):
39+ installed = importlib.metadata.version(dist).split("+")[0]
40+ assert not want or installed == want, f"{dist} {installed}, image pins {want}"
26 print(f"[OK] [1] python {py}, torch {torch.__version__}, torch_npu {torch_npu.__version__}")41 print(f"[OK] [1] python {py}, torch {torch.__version__}, torch_npu {torch_npu.__version__}")
27except Exception as e:42except Exception as e:
28 print(f"[FAIL] [1] import/version: {e}")43 print(f"[FAIL] [1] import/version: {e}")
@@ -15,7 +15,7 @@
15# Knobs. Every mirror arg defaults to the official/global source, exactly like docker/base; pass15# Knobs. Every mirror arg defaults to the official/global source, exactly like docker/base; pass
16# --build-arg to swap to an in-region mirror on network-restricted hosts (see README).16# --build-arg to swap to an in-region mirror on network-restricted hosts (see README).
17# ----------------------------------------------------------------------------------------------------------17# ----------------------------------------------------------------------------------------------------------
18-ARG BASE_IMAGE=cann-toolkit-base:9.0.1-py3.1318+ARG BASE_IMAGE=cann-toolkit-base:9.1.0-py3.13
19 19 
20FROM ${BASE_IMAGE}20FROM ${BASE_IMAGE}
21 21 
@@ -123,6 +123,13 @@ RUN . /usr/local/Ascend/ascend-toolkit/set_env.sh 2>/dev/null || true; \
123 && /opt/venv/bin/python3 -c 'from cann_bench_utils import cann_bench_warmup, cann_bench_cache_clean'123 && /opt/venv/bin/python3 -c 'from cann_bench_utils import cann_bench_warmup, cann_bench_cache_clean'
124ENV NPU_ARCH=${NPU_ARCH}124ENV NPU_ARCH=${NPU_ARCH}
125 125 
126+# Which image produced a report. docker/eval/build.sh passes its own tag here and setup_info reads it
127+# for the report's "docker" field -- that field used to be the hardcoded string "cake-ci / CANN 9.0.0",
128+# which kept appearing long after both the image and the CANN version had moved on. Empty on a
129+# hand-rolled `docker build`; setup_info then says "container" rather than inventing a name.
130+ARG CANN_BENCH_IMAGE=
131+ENV CANN_BENCH_IMAGE=${CANN_BENCH_IMAGE}
132+ 
126# Optional Triton-Ascend runtime (large); same semantics as the dev image's build-arg.133# Optional Triton-Ascend runtime (large); same semantics as the dev image's build-arg.
127ARG TRITON_ASCEND_VERSION=134ARG TRITON_ASCEND_VERSION=
128ARG TRITON_ASCEND_INDEX_URL=https://triton-ascend.osinfra.cn/pypi/simple135ARG TRITON_ASCEND_INDEX_URL=https://triton-ascend.osinfra.cn/pypi/simple
@@ -30,7 +30,7 @@ harness 冻结在镜像里(`src/kernel_eval` + `tasks/` + `cann_bench_utils` 全
30这是原生构建,不是交叉编译):30这是原生构建,不是交叉编译):
31 31 
32```bash32```bash
33-cd docker/base && docker build --build-arg ARCH=$(uname -m) -t cann-toolkit-base:9.0.1-py3.13 .33+cd docker/base && docker build --build-arg ARCH=$(uname -m) -t cann-toolkit-base:9.1.0-py3.13 .
34```34```
35 35 
36然后(**build context 必须是仓库根**,`build.sh` 已经处理好):36然后(**build context 必须是仓库根**,`build.sh` 已经处理好):
@@ -162,8 +162,6 @@ docker run ... -v "$PWD:/opt/cann-bench" cann-bench-eval:... /submission --opera
162 162 
163## 已知取舍163## 已知取舍
164 164 
165-- 底座的 `torch_npu==2.10.0.post2` 与仓库 `pyproject.toml` 钉的 `2.10.0` 不是同一串号(同属 2.10
166- 系)。沿用底座的 post2,避免为了对齐版本号把整个 torch 栈重装一遍。
167- `tasks/` 烘进镜像,所以镜像 tag 即 benchmark 版本;开发期用上面的 `-v` 覆盖回工作树。165- `tasks/` 烘进镜像,所以镜像 tag 即 benchmark 版本;开发期用上面的 `-v` 覆盖回工作树。
168- `cann_bench_utils` 在 build 期就编好装好(只要 bisheng,不需要 NPU),容器起来直接开跑,166- `cann_bench_utils` 在 build 期就编好装好(只要 bisheng,不需要 NPU),容器起来直接开跑,
169 `ensure_cann_bench_utils()` 短路返回。它含 SoC 相关 kernel,所以本镜像 per-SoC。167 `ensure_cann_bench_utils()` 短路返回。它含 SoC 相关 kernel,所以本镜像 per-SoC。
@@ -25,7 +25,7 @@ case "${ARCH}" in
25 *) echo "unsupported ARCH=${ARCH} (expected aarch64 | x86_64)" >&2; exit 1 ;;25 *) echo "unsupported ARCH=${ARCH} (expected aarch64 | x86_64)" >&2; exit 1 ;;
26esac26esac
27NPU_ARCH="${NPU_ARCH:-ascend910b}"27NPU_ARCH="${NPU_ARCH:-ascend910b}"
28-CANN_VERSION="${CANN_VERSION:-9.0.1}"28+CANN_VERSION="${CANN_VERSION:-9.1.0}"
29BASE_IMAGE="${BASE_IMAGE:-cann-toolkit-base:${CANN_VERSION}-py3.13}"29BASE_IMAGE="${BASE_IMAGE:-cann-toolkit-base:${CANN_VERSION}-py3.13}"
30TRITON_ASCEND_VERSION="${TRITON_ASCEND_VERSION:-}"30TRITON_ASCEND_VERSION="${TRITON_ASCEND_VERSION:-}"
31 31 
@@ -52,6 +52,9 @@ ARGS=(
52 --build-arg "OPS_PKG=${OPS_PKG}"52 --build-arg "OPS_PKG=${OPS_PKG}"
53 --build-arg "NPU_ARCH=${NPU_ARCH}"53 --build-arg "NPU_ARCH=${NPU_ARCH}"
54 --build-arg "TRITON_ASCEND_VERSION=${TRITON_ASCEND_VERSION}"54 --build-arg "TRITON_ASCEND_VERSION=${TRITON_ASCEND_VERSION}"
55+ # The tag is the only thing that knows which image a report came from; hand it to the image so
56+ # setup_info prints it instead of the hardcoded string the report used to carry.
57+ --build-arg "CANN_BENCH_IMAGE=${IMAGE}"
55)58)
56 59 
57# One switch for the whole in-region mirror set, rather than five build-args at every call site.60# One switch for the whole in-region mirror set, rather than five build-args at every call site.
@@ -20,7 +20,7 @@ requires-python = "==3.13.*"
20dependencies = [20dependencies = [
21 # ---- identical to docker/base/pyproject.toml ----21 # ---- identical to docker/base/pyproject.toml ----
22 "torch==2.10.0",22 "torch==2.10.0",
23- "torch-npu==2.10.0.post2",23+ "torch-npu==2.10.0.post4",
24 "numpy", "pyyaml", "decorator", "attrs", "scipy", "cloudpickle", "ml-dtypes", "psutil",24 "numpy", "pyyaml", "decorator", "attrs", "scipy", "cloudpickle", "ml-dtypes", "psutil",
25 "filelock", "typing-extensions", "sympy", "networkx", "jinja2", "fsspec", "mpmath", "markupsafe",25 "filelock", "typing-extensions", "sympy", "networkx", "jinja2", "fsspec", "mpmath", "markupsafe",
26 "pip", "setuptools", "wheel", "build",26 "pip", "setuptools", "wheel", "build",
@@ -92,7 +92,7 @@ requires-dist = [
92 { name = "setuptools" },92 { name = "setuptools" },
93 { name = "sympy" },93 { name = "sympy" },
94 { name = "torch", specifier = "==2.10.0", index = "https://download.pytorch.org/whl/cpu" },94 { name = "torch", specifier = "==2.10.0", index = "https://download.pytorch.org/whl/cpu" },
95- { name = "torch-npu", specifier = "==2.10.0.post2" },95+ { name = "torch-npu", specifier = "==2.10.0.post4" },
96 { name = "torchvision", index = "https://download.pytorch.org/whl/cpu" },96 { name = "torchvision", index = "https://download.pytorch.org/whl/cpu" },
97 { name = "tornado" },97 { name = "tornado" },
98 { name = "typing-extensions" },98 { name = "typing-extensions" },
@@ -419,14 +419,14 @@ wheels = [
419 419 
420[[package]]420[[package]]
421name = "torch-npu"421name = "torch-npu"
422-version = "2.10.0.post2"422+version = "2.10.0.post4"
423source = { registry = "https://pypi.org/simple" }423source = { registry = "https://pypi.org/simple" }
424dependencies = [424dependencies = [
425 { name = "torch" },425 { name = "torch" },
426]426]
427wheels = [427wheels = [
428- { url = "https://files.pythonhosted.org/packages/9c/67/438d901072bb339c8c732e3635c49dcc8489d695aa59c78945001b057aa2/torch_npu-2.10.0.post2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:157c2c7b59497dd70846b5e8038e142bcea6fd13a9072159732e3b8004593d48", size = 32522503, upload-time = "2026-07-02T02:24:00.506Z" },428+ { url = "https://files.pythonhosted.org/packages/aa/8a/525206571e3a0f9a36363ae55a424b34bac790c8ce10129051e7e8336be6/torch_npu-2.10.0.post4-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2d88ce46c69cfa562453925865805ca8c358cea31176ff9b284e7851eda213d0", size = 36258846, upload-time = "2026-07-27T07:30:49.174Z" },
429- { url = "https://files.pythonhosted.org/packages/92/ff/80eb5e6b8788dd8e5d0c9c75b780a176f1a32e49e4ba90889584877c3446/torch_npu-2.10.0.post2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:8f6eac66b9db2d956b5136f5e072d5fb7c0524bcaa90d6a3ac71a044705d475b", size = 35881624, upload-time = "2026-07-02T02:24:17.603Z" },429+ { url = "https://files.pythonhosted.org/packages/48/a5/c7c2fc0139c55393d9ff3116b0c6ec62bf5ea6257f1a64515927e31dcd27/torch_npu-2.10.0.post4-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e6ac70748c9d03312afb1fc5cf84b69d1b955a59555116e286cf7a10a302be9e", size = 39987520, upload-time = "2026-07-27T07:31:25.567Z" },
430]430]
431 431 
432[[package]]432[[package]]
@@ -966,7 +966,7 @@ setup = collect_setup_info(config)
966# "pytorch_npu": "2.1.0.post3",966# "pytorch_npu": "2.1.0.post3",
967# "python": "3.10.12",967# "python": "3.10.12",
968# "os": "Linux-5.10.0...",968# "os": "Linux-5.10.0...",
969-# "docker": "cake-ci / CANN 9.0.0",969+# "docker": "cann-bench-eval:1.0.0-ascend910b-aarch64-opsnone / CANN 9.1.0",
970# },970# },
971# }971# }
972```972```
@@ -166,7 +166,7 @@ eval_YYYYMMDD_HHMMSS.html ← 完整 HTML 报告
166 "torchvision": "0.22.1+cpu",166 "torchvision": "0.22.1+cpu",
167 "python": "3.12.9",167 "python": "3.12.9",
168 "os": "Linux-6.6.0-132.0.0.111.oe2403sp3.x86_64",168 "os": "Linux-6.6.0-132.0.0.111.oe2403sp3.x86_64",
169- "docker": "cake-ci / CANN 9.0.0"169+ "docker": "cann-bench-eval:1.0.0-ascend910b-aarch64-opsnone / CANN 9.1.0"
170 }170 }
171 },171 },
172 "operators": [172 "operators": [
@@ -214,12 +214,12 @@ eval_YYYYMMDD_HHMMSS.html ← 完整 HTML 报告
214├─────────────────────────────────────────┤214├─────────────────────────────────────────┤
215│ │215│ │
216│ metadata: │216│ metadata: │
217-│ framework ← "CANN-Bench V0.1.0" │217+│ framework ← "CANN-Bench V0.1.0" │
218│ date ← datetime.now() │218│ date ← datetime.now() │
219│ agent_skill← config.agent_skill │219│ agent_skill← config.agent_skill │
220│ base_model ← config.base_model │220│ base_model ← config.base_model │
221│ benchmark ← "CANN-Bench tasks" │221│ benchmark ← "CANN-Bench tasks" │
222-│ license ← 固定 │222+│ license ← 固定 │
223│ │223│ │
224│ environment: │224│ environment: │
225│ npu ← torch_npu.get_device_ │225│ npu ← torch_npu.get_device_ │
@@ -233,8 +233,8 @@ eval_YYYYMMDD_HHMMSS.html ← 完整 HTML 报告
233│ torchvision← torchvision.__version__ │233│ torchvision← torchvision.__version__ │
234│ python ← sys.version │234│ python ← sys.version │
235│ os ← platform.platform() │235│ os ← platform.platform() │
236-│ docker ← "cake-ci / CANN 9.0.0" │236+│ docker ← $CANN_BENCH_IMAGE │
237-│ (硬编码,后续改软编码) │237+│ + 实测 CANN 版本 │
238└─────────────────────────────────────────┘238└─────────────────────────────────────────┘
239```239```
240 240 
@@ -21,7 +21,7 @@ dependencies = [
21 "expecttest",21 "expecttest",
22 "protobuf",22 "protobuf",
23 "ruamel.yaml>=0.18",23 "ruamel.yaml>=0.18",
24- "torch_npu==2.10.0",24+ "torch_npu==2.10.0.post4",
25]25]
26 26 
27[project.optional-dependencies]27[project.optional-dependencies]
@@ -584,7 +584,7 @@ body{
584 <tr><td class="kv-k">PyTorch NPU</td><td>2.7.1.post5</td></tr>584 <tr><td class="kv-k">PyTorch NPU</td><td>2.7.1.post5</td></tr>
585 <tr><td class="kv-k">Python</td><td>3.12.9</td></tr>585 <tr><td class="kv-k">Python</td><td>3.12.9</td></tr>
586 <tr><td class="kv-k">OS</td><td>Linux 5.10.0 hce2 aarch64</td></tr>586 <tr><td class="kv-k">OS</td><td>Linux 5.10.0 hce2 aarch64</td></tr>
587- <tr><td class="kv-k">Docker</td><td>cake-ci / CANN 9.0.0</td></tr>587+ <tr><td class="kv-k">Docker</td><td>cann-bench-eval:1.0.0-ascend910b-aarch64-opsnone / CANN 9.1.0</td></tr>
588 </tbody>588 </tbody>
589 </table>589 </table>
590 </div>590 </div>
@@ -135,10 +135,40 @@ def _get_os_info() -> str:
135 return "unknown"135 return "unknown"
136 136 
137 137 
138+def _in_container() -> bool:
139+ """是否跑在容器里。/.dockerenv 覆盖 docker,cgroup 里的 docker/containerd/kubepods
140+ 覆盖 k8s(CI 的评测 pod 就是这一支)。两者都读不到就当作裸机。"""
141+ if os.path.exists("/.dockerenv"):
142+ return True
143+ try:
144+ with open("/proc/1/cgroup") as f:
145+ blob = f.read()
146+ return any(k in blob for k in ("docker", "containerd", "kubepods"))
147+ except Exception:
148+ return False
149+ 
150+ 
138def _detect_docker() -> Optional[str]:151def _detect_docker() -> Optional[str]:
139- """检测是否运行在 Docker 容器中 (硬编码占位,后续改为软编码)"""152+ """报告里的 "docker" 字段:镜像标识 + 其 CANN 版本。
140- # TODO: 后续改为从环境变量或 Dockerfile 注入153+ 
141- return "cake-ci / CANN 9.0.0"154+ Why not 硬编码: 这里原本写死 "cake-ci / CANN 9.0.0"。镜像早已换代、CANN 也升到
155+ 9.1.0 之后,那行字仍原样出现在每一份报告里 —— 同一份报告的 environment.cann 显示
156+ 9.1.0、docker 显示 9.0.0,自相矛盾,且读报告的人无从知道哪个可信。
157+ 
158+ 取值顺序:
159+ 1. CANN_BENCH_IMAGE —— 镜像自己注入的标识(docker/eval 会写成 <name>:<tag>),
160+ 最准确,因为只有构建镜像的人知道它叫什么。
161+ 2. 容器内但没注入 —— 回退成 "container",至少不谎报具体镜像。
162+ 3. 不在容器里 —— None(报告里显示为空),而不是编一个。
163+ CANN 版本一律取实际探测到的那个,与 environment.cann 同源,不会再对不上。
164+ """
165+ image = (os.environ.get("CANN_BENCH_IMAGE") or "").strip()
166+ if not image:
167+ if not _in_container():
168+ return None
169+ image = "container"
170+ cann = _get_cann_version()
171+ return f"{image} / CANN {cann}" if cann else image
142 172 
143 173 
144# ---------------------------------------------------------------------------174# ---------------------------------------------------------------------------
@@ -0,0 +1,63 @@
1+#!/usr/bin/python3
2+# coding=utf-8
3+ 
4+"""setup_info 的 docker 字段测试。
5+ 
6+Why this file exists: 该字段此前硬编码为 "cake-ci / CANN 9.0.0",镜像换代、CANN 升到
7+9.1.0 之后仍原样出现在每一份报告里 —— 同一份报告 environment.cann 写 9.1.0、docker 写
8+9.0.0,自相矛盾。没有任何测试兜着它,所以谁也没发现。这里把三条取值路径都钉住。
9+"""
10+ 
11+import pytest
12+ 
13+from kernel_eval.report import setup_info
14+ 
15+ 
16+@pytest.fixture
17+def no_container(monkeypatch):
18+ """默认按"不在容器里"跑,单个用例再按需打开。"""
19+ monkeypatch.setattr(setup_info, "_in_container", lambda: False)
20+ monkeypatch.delenv("CANN_BENCH_IMAGE", raising=False)
21+ 
22+ 
23+class TestDetectDocker:
24+ def test_image_env_wins(self, monkeypatch, no_container):
25+ """镜像注入了标识就用它,且带上实际探测到的 CANN 版本。"""
26+ monkeypatch.setenv("CANN_BENCH_IMAGE", "cann-bench-eval:1.0.0-ascend910b-aarch64-opsnone")
27+ monkeypatch.setattr(setup_info, "_get_cann_version", lambda: "9.1.0")
28+ assert setup_info._detect_docker() == (
29+ "cann-bench-eval:1.0.0-ascend910b-aarch64-opsnone / CANN 9.1.0"
30+ )
31+ 
32+ def test_container_without_image_env_does_not_invent_a_name(self, monkeypatch):
33+ """在容器里但没注入标识 -> 只说 container,不编具体镜像名。"""
34+ monkeypatch.delenv("CANN_BENCH_IMAGE", raising=False)
35+ monkeypatch.setattr(setup_info, "_in_container", lambda: True)
36+ monkeypatch.setattr(setup_info, "_get_cann_version", lambda: "9.1.0")
37+ assert setup_info._detect_docker() == "container / CANN 9.1.0"
38+ 
39+ def test_bare_metal_returns_none(self, monkeypatch, no_container):
40+ """不在容器里就如实返回 None,而不是给个假值。"""
41+ monkeypatch.setattr(setup_info, "_get_cann_version", lambda: "9.1.0")
42+ assert setup_info._detect_docker() is None
43+ 
44+ def test_no_cann_detected_still_reports_the_image(self, monkeypatch, no_container):
45+ monkeypatch.setenv("CANN_BENCH_IMAGE", "some-image:tag")
46+ monkeypatch.setattr(setup_info, "_get_cann_version", lambda: None)
47+ assert setup_info._detect_docker() == "some-image:tag"
48+ 
49+ def test_blank_image_env_is_treated_as_unset(self, monkeypatch):
50+ """Dockerfile 的 ARG 留空时 ENV 会是空串,不能当成镜像名用。"""
51+ monkeypatch.setenv("CANN_BENCH_IMAGE", " ")
52+ monkeypatch.setattr(setup_info, "_in_container", lambda: True)
53+ monkeypatch.setattr(setup_info, "_get_cann_version", lambda: "9.1.0")
54+ assert setup_info._detect_docker() == "container / CANN 9.1.0"
55+ 
56+ def test_never_reports_a_cann_version_that_contradicts_environment(self, monkeypatch):
57+ """docker 字段里的 CANN 与 environment.cann 必须同源 —— 这正是旧硬编码的病。"""
58+ monkeypatch.setenv("CANN_BENCH_IMAGE", "img:tag")
59+ monkeypatch.setattr(setup_info, "_get_cann_version", lambda: "9.1.0")
60+ info = setup_info.collect_setup_info()
61+ env = info["environment"]
62+ assert env["cann"] == "9.1.0"
63+ assert env["docker"] == "img:tag / CANN 9.1.0"
Muv.lock+123-76
@@ -26,62 +26,79 @@ name = "black"
26version = "26.5.1"26version = "26.5.1"
27source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }27source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
28dependencies = [28dependencies = [
29- { name = "click", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },29+ { name = "click" },
30- { name = "mypy-extensions", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },30+ { name = "mypy-extensions" },
31- { name = "packaging", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },31+ { name = "packaging" },
32- { name = "pathspec", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },32+ { name = "pathspec" },
33- { name = "platformdirs", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },33+ { name = "platformdirs" },
34- { name = "pytokens", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },34+ { name = "pytokens" },
35- { name = "tomli", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },35+ { name = "tomli", marker = "python_full_version < '3.11'" },
36- { name = "typing-extensions", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },36+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
37]37]
38sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73" }38sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73" }
39wheels = [39wheels = [
40 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2" },40 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2" },
41]41]
42 42 
43+[[package]]
44+name = "build"
45+version = "1.5.1"
46+source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
47+dependencies = [
48+ { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" },
49+ { name = "packaging" },
50+ { name = "pyproject-hooks" },
51+ { name = "tomli", marker = "python_full_version < '3.11'" },
52+]
53+sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/2d/21/6ec54248b4d0d51f12f3ca4aa77a128077d747a5db86cb5a2fcd9aedecbd/build-1.5.1.tar.gz", hash = "sha256:94e17f1db803ab22f46049376c44c8437c52090f0dfdf1adc43df56542d644fb" }
54+wheels = [
55+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/c7/f7/2c3f99ff9282f1c1ec9f6298f2c03034658a0901eeacb3b3501cb488574c/build-1.5.1-py3-none-any.whl", hash = "sha256:f1a58fe2e5af5b0238a07b9e70207492c79ddebbdb1ad954fc86d62a56be3e0d" },
56+]
57+ 
43[[package]]58[[package]]
44name = "cann-bench"59name = "cann-bench"
45-version = "0.4.0"60+version = "1.0.0"
46source = { virtual = "." }61source = { virtual = "." }
47dependencies = [62dependencies = [
48- { name = "attrs", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },63+ { name = "attrs" },
49- { name = "cloudpickle", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },64+ { name = "build" },
50- { name = "decorator", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },65+ { name = "cloudpickle" },
51- { name = "expecttest", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },66+ { name = "decorator" },
52- { name = "ml-dtypes", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },67+ { name = "expecttest" },
53- { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },68+ { name = "ml-dtypes" },
54- { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },69+ { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11'" },
55- { name = "pandas", version = "2.3.3", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },70+ { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11'" },
56- { name = "pandas", version = "3.0.3", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },71+ { name = "pandas", version = "2.3.3", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11'" },
57- { name = "protobuf", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },72+ { name = "pandas", version = "3.0.3", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11'" },
58- { name = "psutil", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },73+ { name = "protobuf" },
59- { name = "pyyaml", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },74+ { name = "psutil" },
60- { name = "ruamel-yaml", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },75+ { name = "pyyaml" },
61- { name = "scipy", version = "1.15.3", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },76+ { name = "ruamel-yaml" },
62- { name = "scipy", version = "1.17.1", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },77+ { name = "scipy", version = "1.15.3", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11'" },
63- { name = "torch", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },78+ { name = "scipy", version = "1.17.1", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11'" },
64- { name = "torch-npu", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },79+ { name = "torch" },
65- { name = "tornado", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },80+ { name = "torch-npu" },
81+ { name = "tornado" },
66]82]
67 83 
68[package.optional-dependencies]84[package.optional-dependencies]
69vision = [85vision = [
70- { name = "torchvision", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },86+ { name = "torchvision" },
71]87]
72 88 
73[package.dev-dependencies]89[package.dev-dependencies]
74dev = [90dev = [
75- { name = "black", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },91+ { name = "black" },
76- { name = "flake8", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },92+ { name = "flake8" },
77- { name = "isort", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },93+ { name = "isort" },
78- { name = "pytest", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },94+ { name = "pytest" },
79- { name = "pytest-timeout", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },95+ { name = "pytest-timeout" },
80]96]
81 97 
82[package.metadata]98[package.metadata]
83requires-dist = [99requires-dist = [
84 { name = "attrs" },100 { name = "attrs" },
101+ { name = "build" },
85 { name = "cloudpickle" },102 { name = "cloudpickle" },
86 { name = "decorator" },103 { name = "decorator" },
87 { name = "expecttest" },104 { name = "expecttest" },
@@ -94,7 +111,7 @@ requires-dist = [
94 { name = "ruamel-yaml", specifier = ">=0.18" },111 { name = "ruamel-yaml", specifier = ">=0.18" },
95 { name = "scipy" },112 { name = "scipy" },
96 { name = "torch", specifier = "==2.10.0" },113 { name = "torch", specifier = "==2.10.0" },
97- { name = "torch-npu", specifier = "==2.10.0" },114+ { name = "torch-npu", specifier = "==2.10.0.post4" },
98 { name = "torchvision", marker = "extra == 'vision'", specifier = ">=0.18.0" },115 { name = "torchvision", marker = "extra == 'vision'", specifier = ">=0.18.0" },
99 { name = "tornado" },116 { name = "tornado" },
100]117]
@@ -141,7 +158,7 @@ name = "exceptiongroup"
141version = "1.3.1"158version = "1.3.1"
142source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }159source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
143dependencies = [160dependencies = [
144- { name = "typing-extensions", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },161+ { name = "typing-extensions" },
145]162]
146sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219" }163sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219" }
147wheels = [164wheels = [
@@ -171,9 +188,9 @@ name = "flake8"
171version = "7.3.0"188version = "7.3.0"
172source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }189source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
173dependencies = [190dependencies = [
174- { name = "mccabe", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },191+ { name = "mccabe" },
175- { name = "pycodestyle", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },192+ { name = "pycodestyle" },
176- { name = "pyflakes", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },193+ { name = "pyflakes" },
177]194]
178sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872" }195sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872" }
179wheels = [196wheels = [
@@ -189,6 +206,18 @@ wheels = [
189 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2" },206 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2" },
190]207]
191 208 
209+[[package]]
210+name = "importlib-metadata"
211+version = "9.0.0"
212+source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
213+dependencies = [
214+ { name = "zipp" },
215+]
216+sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc" }
217+wheels = [
218+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl", hash = "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7" },
219+]
220+ 
192[[package]]221[[package]]
193name = "iniconfig"222name = "iniconfig"
194version = "2.3.0"223version = "2.3.0"
@@ -212,7 +241,7 @@ name = "jinja2"
212version = "3.1.6"241version = "3.1.6"
213source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }242source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
214dependencies = [243dependencies = [
215- { name = "markupsafe", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },244+ { name = "markupsafe" },
216]245]
217sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" }246sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" }
218wheels = [247wheels = [
@@ -255,8 +284,8 @@ name = "ml-dtypes"
255version = "0.5.4"284version = "0.5.4"
256source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }285source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
257dependencies = [286dependencies = [
258- { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },287+ { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11'" },
259- { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },288+ { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11'" },
260]289]
261sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453" }290sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453" }
262wheels = [291wheels = [
@@ -379,10 +408,10 @@ resolution-markers = [
379 "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'",408 "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'",
380]409]
381dependencies = [410dependencies = [
382- { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },411+ { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" } },
383- { name = "python-dateutil", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },412+ { name = "python-dateutil" },
384- { name = "pytz", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },413+ { name = "pytz" },
385- { name = "tzdata", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },414+ { name = "tzdata" },
386]415]
387sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b" }416sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b" }
388wheels = [417wheels = [
@@ -413,8 +442,8 @@ resolution-markers = [
413 "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux'",442 "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux'",
414]443]
415dependencies = [444dependencies = [
416- { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },445+ { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" } },
417- { name = "python-dateutil", marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },446+ { name = "python-dateutil" },
418]447]
419sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/f8/87/4341c6252d1c47b08768c3d25ac487362bf403f0313ddae4a2a26c9b1b4c/pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc" }448sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/f8/87/4341c6252d1c47b08768c3d25ac487362bf403f0313ddae4a2a26c9b1b4c/pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc" }
420wheels = [449wheels = [
@@ -543,17 +572,26 @@ wheels = [
543 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" },572 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" },
544]573]
545 574 
575+[[package]]
576+name = "pyproject-hooks"
577+version = "1.2.0"
578+source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
579+sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8" }
580+wheels = [
581+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913" },
582+]
583+ 
546[[package]]584[[package]]
547name = "pytest"585name = "pytest"
548version = "9.0.3"586version = "9.0.3"
549source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }587source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
550dependencies = [588dependencies = [
551- { name = "exceptiongroup", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },589+ { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
552- { name = "iniconfig", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },590+ { name = "iniconfig" },
553- { name = "packaging", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },591+ { name = "packaging" },
554- { name = "pluggy", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },592+ { name = "pluggy" },
555- { name = "pygments", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },593+ { name = "pygments" },
556- { name = "tomli", marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },594+ { name = "tomli", marker = "python_full_version < '3.11'" },
557]595]
558sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c" }596sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c" }
559wheels = [597wheels = [
@@ -565,7 +603,7 @@ name = "pytest-timeout"
565version = "2.4.0"603version = "2.4.0"
566source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }604source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
567dependencies = [605dependencies = [
568- { name = "pytest", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },606+ { name = "pytest" },
569]607]
570sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/ac/82/4c9ecabab13363e72d880f2fb504c5f750433b2b6f16e99f4ec21ada284c/pytest_timeout-2.4.0.tar.gz", hash = "sha256:7e68e90b01f9eff71332b25001f85c75495fc4e3a836701876183c4bcfd0540a" }608sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/ac/82/4c9ecabab13363e72d880f2fb504c5f750433b2b6f16e99f4ec21ada284c/pytest_timeout-2.4.0.tar.gz", hash = "sha256:7e68e90b01f9eff71332b25001f85c75495fc4e3a836701876183c4bcfd0540a" }
571wheels = [609wheels = [
@@ -577,7 +615,7 @@ name = "python-dateutil"
577version = "2.9.0.post0"615version = "2.9.0.post0"
578source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }616source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
579dependencies = [617dependencies = [
580- { name = "six", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },618+ { name = "six" },
581]619]
582sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3" }620sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3" }
583wheels = [621wheels = [
@@ -645,7 +683,7 @@ resolution-markers = [
645 "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'",683 "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'",
646]684]
647dependencies = [685dependencies = [
648- { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },686+ { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" } },
649]687]
650sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf" }688sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf" }
651wheels = [689wheels = [
@@ -672,7 +710,7 @@ resolution-markers = [
672 "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux'",710 "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux'",
673]711]
674dependencies = [712dependencies = [
675- { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },713+ { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" } },
676]714]
677sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0" }715sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0" }
678wheels = [716wheels = [
@@ -713,7 +751,7 @@ name = "sympy"
713version = "1.14.0"751version = "1.14.0"
714source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }752source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
715dependencies = [753dependencies = [
716- { name = "mpmath", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },754+ { name = "mpmath" },
717]755]
718sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517" }756sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517" }
719wheels = [757wheels = [
@@ -744,14 +782,14 @@ name = "torch"
744version = "2.10.0"782version = "2.10.0"
745source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }783source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
746dependencies = [784dependencies = [
747- { name = "filelock", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },785+ { name = "filelock" },
748- { name = "fsspec", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },786+ { name = "fsspec" },
749- { name = "jinja2", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },787+ { name = "jinja2" },
750- { name = "networkx", version = "3.4.2", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },788+ { name = "networkx", version = "3.4.2", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11'" },
751- { name = "networkx", version = "3.6.1", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },789+ { name = "networkx", version = "3.6.1", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11'" },
752- { name = "setuptools", marker = "python_full_version >= '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'" },790+ { name = "setuptools", marker = "python_full_version >= '3.12'" },
753- { name = "sympy", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },791+ { name = "sympy" },
754- { name = "typing-extensions", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },792+ { name = "typing-extensions" },
755]793]
756wheels = [794wheels = [
757 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/0c/1a/c61f36cfd446170ec27b3a4984f072fd06dab6b5d7ce27e11adb35d6c838/torch-2.10.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d" },795 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/0c/1a/c61f36cfd446170ec27b3a4984f072fd06dab6b5d7ce27e11adb35d6c838/torch-2.10.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d" },
@@ -765,16 +803,16 @@ wheels = [
765 803 
766[[package]]804[[package]]
767name = "torch-npu"805name = "torch-npu"
768-version = "2.10.0"806+version = "2.10.0.post4"
769source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }807source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
770dependencies = [808dependencies = [
771- { name = "torch", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },809+ { name = "torch" },
772]810]
773wheels = [811wheels = [
774- { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/f5/2d/b688ca03ea2ba7472b61178bef96288d78be316d0b644037c735fb7eb82c/torch_npu-2.10.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:274f22a3000c89cad0e83ac487158104a51f26c422a296a3b29601747af40674" },812+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/ab/c8/630dbe2af14d469aab781a62a1ebb6944b11309b79ed0788a08b0f2a2541/torch_npu-2.10.0.post4-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8196169412a7f7be6926a765e0f70e2e633d7791d0ccad94a96bd3d314409eec" },
775- { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/6d/d8/482baf4f6e02264333d033b32702e41d5f4f88a538cc882fe53535e6ef43/torch_npu-2.10.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:07e9d39a77577873c8a1a2d6741129d15d6b7a54d2c07a1cc3a294242689fea7" },813+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/f0/0f/f43a0847950643357a181097c9c2a06af5ac56eb694bd0e4415c3013e3ec/torch_npu-2.10.0.post4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:624ba08fb0259fcb8315a4b5bb5d7edd2d2ca927ba368c800b7f18771564e153" },
776- { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/b5/03/1160d86b8db5e4d548fd3b84494e1b85cde839b40cd50479bd37fda88bca/torch_npu-2.10.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93eef95dea5c089b6c59f30d680689b936ee8b6d7a2a73575abcb66764866b52" },814+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/64/8d/3d10b7852b4e7f1392d6b68457537d3e4cdd8be04dcdaae83c14344b571b/torch_npu-2.10.0.post4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5cee8b07d98b2188297916342fc587228bfca5703ffa8f48be1a69373414aa44" },
777- { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/bc/bd/d10e3b74e35e0b6a20f97d886d8d520a0f7f8f136f38b3c48d738696fda9/torch_npu-2.10.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:81610da863aa80b1ccb3cece8fc6c0e85f5ea772ca7ffea5878bc5884e3cfaec" },815+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/aa/8a/525206571e3a0f9a36363ae55a424b34bac790c8ce10129051e7e8336be6/torch_npu-2.10.0.post4-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2d88ce46c69cfa562453925865805ca8c358cea31176ff9b284e7851eda213d0" },
778]816]
779 817 
780[[package]]818[[package]]
@@ -782,10 +820,10 @@ name = "torchvision"
782version = "0.25.0"820version = "0.25.0"
783source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }821source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
784dependencies = [822dependencies = [
785- { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },823+ { name = "numpy", version = "2.2.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version < '3.11'" },
786- { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'" },824+ { name = "numpy", version = "2.4.6", source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }, marker = "python_full_version >= '3.11'" },
787- { name = "pillow", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },825+ { name = "pillow" },
788- { name = "torch", marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },826+ { name = "torch" },
789]827]
790wheels = [828wheels = [
791 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/64/68/dc7a224f606d53ea09f9a85196a3921ec3a801b0b1d17e84c73392f0c029/torchvision-0.25.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:acc339aba4a858192998c2b91f635827e40d9c469d9cf1455bafdda6e4c28ea4" },829 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/64/68/dc7a224f606d53ea09f9a85196a3921ec3a801b0b1d17e84c73392f0c029/torchvision-0.25.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:acc339aba4a858192998c2b91f635827e40d9c469d9cf1455bafdda6e4c28ea4" },
@@ -824,3 +862,12 @@ sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/ba/19/
824wheels = [862wheels = [
825 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7" },863 { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7" },
826]864]
865+ 
866+[[package]]
867+name = "zipp"
868+version = "4.1.0"
869+source = { registry = "https://mirrors.huaweicloud.com/repository/pypi/simple" }
870+sdist = { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602" }
871+wheels = [
872+ { url = "https://mirrors.huaweicloud.com/repository/pypi/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f" },
873+]