已开启
更新 skill_output 内容,添加op-native-adaptation算子测试文件 #3
pengaoran创建于 7月28日
更新 skill_output 内容,添加op-native-adaptation算子测试文件 #3
已开启
共 13 个文件变更+8220-0
| @@ -0,0 +1,82 @@ | |||
| 1 | +# torch.linalg.cholesky — op-native-adaptation skill 交付件 | ||
| 2 | + | ||
| 3 | +## 算子信息 | ||
| 4 | + | ||
| 5 | +| 项目 | 内容 | | ||
| 6 | +|------|------| | ||
| 7 | +| 算子 | `torch.linalg.cholesky` | | ||
| 8 | +| ACLNN | `aclnnLinalgCholesky` | | ||
| 9 | +| Dtype | fp32, bf16 | | ||
| 10 | +| 接入方式 | structured codegen (`op-native-adaptation` CREATE 模式) | | ||
| 11 | +| 适配日期 | 2026-07-27 | | ||
| 12 | + | ||
| 13 | +--- | ||
| 14 | + | ||
| 15 | +## 交付件清单 | ||
| 16 | + | ||
| 17 | +### 1. YAML 代码生成配置 | ||
| 18 | + | ||
| 19 | +| 文件 | 位置 | 说明 | | ||
| 20 | +|------|------|------| | ||
| 21 | +| `op_plugin_functions.yaml` | `yaml/op_plugin_functions.yaml` (第 2999-3012 行) | `linalg_cholesky` + `linalg_cholesky.out` 两个条目 | | ||
| 22 | + | ||
| 23 | +- 使用 `op_api: all_version`(仅 ACLNN,无 ACL 路径) | ||
| 24 | +- `structured_inherit` 模式:functional 委派给 .out 变体 | ||
| 25 | +- 无 `acl_op:` 字段(避免 `undefined reference` 链接错误) | ||
| 26 | + | ||
| 27 | +### 2. UT 测试 | ||
| 28 | + | ||
| 29 | +| 文件 | 说明 | | ||
| 30 | +|------|------| | ||
| 31 | +| `ut_test/test_npu_linalg_cholesky.py` | 4 个测试用例,均通过 | | ||
| 32 | + | ||
| 33 | +| 测试方法 | dtype | upper | 验证方式 | | ||
| 34 | +|----------|-------|-------|----------| | ||
| 35 | +| `test_..._fp32_upper_false` | fp32 | false | CPU vs NPU `assertRtolEqual` | | ||
| 36 | +| `test_..._fp32_upper_true` | fp32 | true | CPU vs NPU `assertRtolEqual` | | ||
| 37 | +| `test_..._bf16_upper_false` | bf16 | false | 仅 shape 校验(CPU 无 bf16) | | ||
| 38 | +| `test_..._bf16_upper_true` | bf16 | true | 仅 shape 校验(CPU 无 bf16) | | ||
| 39 | + | ||
| 40 | +### 3. PTA ATK 适配 | ||
| 41 | + | ||
| 42 | +| 文件 | 目录 | 说明 | | ||
| 43 | +|------|------|------| | ||
| 44 | +| `torch.linalg.cholesky.yaml` | `pta_atk/config/` | ATK 用例设计文件 | | ||
| 45 | +| `generator_linalg_cholesky.py` | `pta_atk/config/` | 用例生成器(确保方阵 + 正定) | | ||
| 46 | +| `execute_aclnn_cholesky.py` | `pta_atk/config/` | 执行器(NPU + CPU 双端) | | ||
| 47 | +| `nodes_linalg_cholesky.yaml` | `pta_atk/config/` | 节点配置(NPU accuracy_dc + CPU) | | ||
| 48 | +| `all_torch.linalg.cholesky.json` | `pta_atk/result/` | ATK 生成的 200 个用例 | | ||
| 49 | + | ||
| 50 | +### 4. ATK 运行结果 | ||
| 51 | + | ||
| 52 | +| 文件 | 目录 | 说明 | | ||
| 53 | +|------|------|------| | ||
| 54 | +| `all_torch.linalg.cholesky_reports_2026-07-28-11-55-07.xlsx` | `report/` | ATK 完整报告 | | ||
| 55 | +| `torch.linalg.cholesky20260728103806.xlsx` | `report/` | ATK 用例列表 | | ||
| 56 | + | ||
| 57 | +**结果摘要:** | ||
| 58 | + | ||
| 59 | +| 项目 | 值 | | ||
| 60 | +|------|-----| | ||
| 61 | +| 总用例数 | 200 | | ||
| 62 | +| 执行成功 | 200 | | ||
| 63 | +| 执行失败 | 0 | | ||
| 64 | +| 通过率 | 100% | | ||
| 65 | +| 确定性计算 | Pass | | ||
| 66 | + | ||
| 67 | +### 5. 过程文档 | ||
| 68 | + | ||
| 69 | +| 文件 | 目录 | 说明 | | ||
| 70 | +|------|------|------| | ||
| 71 | +| `CHECKLIST.md` | `summary/` | 操作检查清单(N-create 全流程) | | ||
| 72 | +| `summary_2026-07-27.md` | `summary/` | 中文总结:接入过程 + 关键决策 | | ||
| 73 | +| `CHANGELOG.md` | `summary/` | 仓库 Changelog 条目 | | ||
| 74 | + | ||
| 75 | +--- | ||
| 76 | + | ||
| 77 | +## 关键决策记录 | ||
| 78 | + | ||
| 79 | +1. **无 `acl_op:`** — `linalg_cholesky` 只有 ACLNN 内核,没有遗留 ACL 路径,加 `acl_op:` 会导致链接错误 | ||
| 80 | +2. **structured_inherit 模式** — functional 形式通过 `structured_inherit: linalg_cholesky.out` 委派给 .out 变体 | ||
| 81 | +3. **简化 ATK executor** — 去掉 backward 调用(NPU 不支持 `linalg_cholesky` 反向),只做 forward 精度对比 | ||
| 82 | +4. **bf16 精度测量** — CPU 无 bf16 原生支持,UT 中只做 shape 校验;ATK 中 NPU bf16 通过 fp32 计算后转回 | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | +import torch | ||
| 2 | +from atk.configs.dataset_config import InputDataset | ||
| 3 | +from atk.tasks.api_execute import register | ||
| 4 | +from atk.tasks.api_execute.base_api import BaseApi | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +def generate_pd_by_eigenvalues(shape, min_eigenvalue=0.1): | ||
| 8 | + torch.manual_seed(1234) | ||
| 9 | + n = shape[-1] | ||
| 10 | + batch_shape = shape[:-2] | ||
| 11 | + random_matrix = torch.randn(*batch_shape, n, n) | ||
| 12 | + Q, _ = torch.linalg.qr(random_matrix) | ||
| 13 | + eigenvalues = torch.rand(*batch_shape, n) + min_eigenvalue | ||
| 14 | + A = torch.matmul(Q, eigenvalues.unsqueeze(-1) * Q.transpose(-2, -1)) | ||
| 15 | + return A | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +class FunctionApi(BaseApi): | ||
| 20 | + def init_by_input_data(self, input_data: InputDataset): | ||
| 21 | + shape = input_data.kwargs["self"].shape | ||
| 22 | + dtype = input_data.kwargs["self"].dtype | ||
| 23 | + A = generate_pd_by_eigenvalues(shape, min_eigenvalue=0.1) | ||
| 24 | + if dtype == torch.bfloat16: | ||
| 25 | + input_data.kwargs["self"] = A.to(torch.bfloat16) | ||
| 26 | + else: | ||
| 27 | + input_data.kwargs["self"] = A | ||
| 28 | + | ||
| 29 | + def __call__(self, input_data: InputDataset, with_output: bool = False): | ||
| 30 | + if self.device == "npu": | ||
| 31 | + x_self = input_data.kwargs["self"].npu() | ||
| 32 | + x_upper = input_data.kwargs["upper"] | ||
| 33 | + if x_self.dtype == torch.bfloat16: | ||
| 34 | + out = torch.linalg.cholesky(x_self.to(torch.float32), upper=x_upper).to(torch.bfloat16) | ||
| 35 | + else: | ||
| 36 | + out = torch.linalg.cholesky(x_self, upper=x_upper) | ||
| 37 | + else: | ||
| 38 | + x_self = input_data.kwargs["self"] | ||
| 39 | + x_upper = input_data.kwargs["upper"] | ||
| 40 | + if x_self.dtype == torch.bfloat16: | ||
| 41 | + out = torch.linalg.cholesky(x_self.to(torch.float32), upper=x_upper).to(torch.bfloat16) | ||
| 42 | + else: | ||
| 43 | + out = torch.linalg.cholesky(x_self, upper=x_upper) | ||
| 44 | + return out | ||
| @@ -0,0 +1,19 @@ | |||
| 1 | +import random | ||
| 2 | + | ||
| 3 | +from atk.case_generator.generator.generate_types import GENERATOR_REGISTRY | ||
| 4 | +from atk.case_generator.generator.base_generator import CaseGenerator | ||
| 5 | +from atk.configs.case_config import InputCaseConfig, CaseConfig | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +class LinalgCholeskyGenerator(CaseGenerator): | ||
| 9 | + def __init__(self, config): | ||
| 10 | + super().__init__(config) | ||
| 11 | + | ||
| 12 | + def after_case_config(self, case_config: CaseConfig) -> CaseConfig: | ||
| 13 | + shape_self = case_config.inputs[0].shape | ||
| 14 | + if shape_self[-2] != shape_self[-1]: | ||
| 15 | + shape_self[-2] = shape_self[-1] | ||
| 16 | + if shape_self[-1] == 1: | ||
| 17 | + shape_self[-1] = 2 | ||
| 18 | + shape_self[-2] = 2 | ||
| 19 | + return case_config | ||
| @@ -0,0 +1,7 @@ | |||
| 1 | +nodes: | ||
| 2 | + - backend: npu | ||
| 3 | + task: ['accuracy_dc'] | ||
| 4 | + devices: [0] | ||
| 5 | + - backend: cpu | ||
| 6 | + task: ['accuracy_dc'] | ||
| 7 | + is_compare: False | ||
| @@ -0,0 +1,38 @@ | |||
| 1 | +api: pytorch | ||
| 2 | +api_type: execute_aclnn_linalg_cholesky | ||
| 3 | +version: v2.1 | ||
| 4 | +name: torch.linalg.cholesky | ||
| 5 | +aclnn_name: LinalgCholesky | ||
| 6 | +dtype_numbers: 100 | ||
| 7 | +generate: ascend_linalg_cholesky | ||
| 8 | +standard: | ||
| 9 | + acc: default | ||
| 10 | + perf: not_key | ||
| 11 | +inputs: | ||
| 12 | + - name: self | ||
| 13 | + type: tensor | ||
| 14 | + required: true | ||
| 15 | + dtypes: | ||
| 16 | + values: [ fp32, bf16 ] | ||
| 17 | + ranges: | ||
| 18 | + valid: | ||
| 19 | + values: [ ['-inf', 'inf']] | ||
| 20 | + invalid: | ||
| 21 | + values: [ ['-inf', 'inf'] ] | ||
| 22 | + shapes: | ||
| 23 | + dim_numbers: | ||
| 24 | + values: [2, 3, 4, 5, 6] # 反向最大只支持6维度 | ||
| 25 | + dim_values: | ||
| 26 | + values: [ 1, 7, 8, 9, 15, 16, 17, 19, 20, 21, 255, 256, 257 ] | ||
| 27 | + max_length: 100000 | ||
| 28 | + - name: upper | ||
| 29 | + type: attr | ||
| 30 | + required: true | ||
| 31 | + dtypes: | ||
| 32 | + values: [ bool ] | ||
| 33 | + ranges: | ||
| 34 | + valid: | ||
| 35 | + values: [ true, false ] | ||
| 36 | + weights: [ 0.5, 0.5 ] | ||
| 37 | + invalid: | ||
| 38 | + values: [ true, false ] | ||
Askill_output/op-native-adaptation/report/all_torch.linalg.cholesky_reports_2026-07-28-11-55-07.xlsx+0-0
Binary files do not support preview
Binary files do not support preview
| @@ -0,0 +1,5 @@ | |||
| 1 | +# Changelog | ||
| 2 | + | ||
| 3 | +## Unreleased | ||
| 4 | + | ||
| 5 | +- [Native] Register `torch.linalg.cholesky` on NPU via structured codegen (op-native-adaptation, 2026-07-27) | ||
| @@ -0,0 +1,124 @@ | |||
| 1 | +# CHECKLIST — linalg_cholesky | ||
| 2 | + | ||
| 3 | +> Created by op-native-adaptation. Maintained throughout; update after every step. | ||
| 4 | + | ||
| 5 | +## 1. Operator Basic Info | ||
| 6 | + | ||
| 7 | +- Operator name (aten): `linalg_cholesky` | ||
| 8 | +- aclnn signature: `aclnnLinalgCholeskyGetWorkspaceSize(self, upper, out, workspaceSize, executor)` | ||
| 9 | +- YAML section: `official:` (no SymInt params) | ||
| 10 | +- Codegen mechanism: `gen_opapi:` structured sub-block | ||
| 11 | +- CANN kernel library: `ops-math` (linear algebra) | ||
| 12 | +- Input files: | ||
| 13 | + - `/home/p00845809/report/aclnn_input/aclnnLinalgCholesky.md` | ||
| 14 | + - `/home/p00845809/report/aclnn_input/cholesky_def.cpp` | ||
| 15 | + | ||
| 16 | +## 2. Parameter Information Table (reduced — drives `gen_opapi:` sub-block) | ||
| 17 | + | ||
| 18 | +### 2.1 Inputs | ||
| 19 | + | ||
| 20 | +| name | type | shape rule | dtype | required | | ||
| 21 | +|------|------|-----------|-------|----------| | ||
| 22 | +| self | Tensor | arbitrary (2-8 dims, last two dims equal, ND) | FLOAT, BFLOAT16 | yes | | ||
| 23 | +| upper | bool | — | BOOL | no (default false) | | ||
| 24 | + | ||
| 25 | +### 2.2 Outputs | ||
| 26 | + | ||
| 27 | +| name | type | shape rule | dtype rule | | ||
| 28 | +|------|------|-----------|------------| | ||
| 29 | +| out | Tensor | same as self | same as self | | ||
| 30 | + | ||
| 31 | +### 2.3 Optional inputs (defaults) | ||
| 32 | + | ||
| 33 | +| name | default | notes | | ||
| 34 | +|------|---------|-------| | ||
| 35 | +| upper | false | True=upper triangular, False=lower triangular Cholesky decomposition | | ||
| 36 | + | ||
| 37 | +## 3. gen_opapi Sub-Block Schema | ||
| 38 | + | ||
| 39 | +> Filled in during N-genopapi. Drives `torchnpugen/struct/gen_struct_opapi.py` codegen. | ||
| 40 | + | ||
| 41 | +```yaml | ||
| 42 | +gen_opapi: | ||
| 43 | + structured_inherit: linalg_cholesky.out # functional form delegates to .out | ||
| 44 | +--- | ||
| 45 | +gen_opapi: | ||
| 46 | + out: | ||
| 47 | + size: self | ||
| 48 | + dtype: self.scalar_type() | ||
| 49 | + exec: aclnnLinalgCholesky, self, upper, out | ||
| 50 | +``` | ||
| 51 | + | ||
| 52 | +| field | value | source | | ||
| 53 | +|-------|-------|--------| | ||
| 54 | +| `size` | `self` | §2.2 output shape = input shape | | ||
| 55 | +| `dtype` | `self.scalar_type()` | §2.2 output dtype = input dtype | | ||
| 56 | +| `new_params` | — | none needed | | ||
| 57 | +| `cmd_args` / `exec` | `aclnnLinalgCholesky, self, upper, out` | §2.1 + aclnn signature order | | ||
| 58 | +| `structured_inherit` | `linalg_cholesky.out` | functional → .out delegation | | ||
| 59 | +| `out` | size: self, dtype: self.scalar_type() | .out variant | | ||
| 60 | + | ||
| 61 | +## 4. Helper Functions Required | ||
| 62 | + | ||
| 63 | +> `gen_opapi:` may reference helper functions (e.g., `abs_out_dtype`). | ||
| 64 | +> If a required helper doesn't exist, it must be added manually. | ||
| 65 | + | ||
| 66 | +| helper name | purpose | status | location | | ||
| 67 | +|-------------|---------|--------|----------| | ||
| 68 | +| — | no special helper needed (self.scalar_type() directly) | n/a | n/a | | ||
| 69 | + | ||
| 70 | +## 5. Source File Paths | ||
| 71 | + | ||
| 72 | +| file | operation | final status | | ||
| 73 | +|------|-----------|--------------| | ||
| 74 | +| `op_plugin/config/op_plugin_functions.yaml` | modify (add under `official:` after linalg_cross) | ☐ | | ||
| 75 | +| `op_plugin/ops/opapi/StructKernelNpuOpApi.cpp` | codegen output (not committed, regenerated at build) | generated | | ||
| 76 | +| `test/test_base_ops/test_npu_linalg_cholesky.py` | create (Create mode) | ☐ | | ||
| 77 | +| `release notes / CHANGELOG` | append one line | ☐ | | ||
| 78 | +| `notes/summary_<date>.md` | create | ☐ | | ||
| 79 | + | ||
| 80 | +## 6. Mode Detection Result | ||
| 81 | + | ||
| 82 | +- Mode: **CREATE** (no existing `func: linalg_cholesky` entry in `official:`) | ||
| 83 | + | ||
| 84 | +## 7. Finalization Add/Delete Log | ||
| 85 | + | ||
| 86 | +| Action | Detail | | ||
| 87 | +|--------|--------| | ||
| 88 | +| Add `func: linalg_cholesky` | YAML `official:` section — functional form with `structured_inherit` | | ||
| 89 | +| Add `func: linalg_cholesky.out` | YAML `official:` section — `.out` variant with `out:` sub-block and `exec:` | | ||
| 90 | +| Create `CHECKLIST.md` | N-parse scaffold + LLM fill | | ||
| 91 | +| Create `test/test_base_ops/test_npu_linalg_cholesky.py` | N-test test file | | ||
| 92 | +| Create `CHANGELOG.md` | N-docs release notes entry | | ||
| 93 | +| Create `notes/summary_2026-07-27.md` | N-summary integration summary | | ||
| 94 | + | ||
| 95 | +## 8. Build & Test Status | ||
| 96 | + | ||
| 97 | +- N-verify static YAML check: **PASS** | ||
| 98 | +- N-verify codegen dry-run: **PASS** (codegen ran during build; StructKernelNpuOpApi.cpp generated at 232KB) | ||
| 99 | +- N-build: **PASS** (`bash ci/build.sh --python=3.10 --pytorch=v2.10.0-26.1.0` → `torch_npu-2.10.0.post4-cp310-cp310-linux_aarch64.whl`) | ||
| 100 | +- N-test UT: **PASS** (4/4 passed — fp32 upper=True/False, bf16 upper=True/False) | ||
| 101 | +- N-test FakeTensor: (pending — needs codegen output for meta shapes) | ||
| 102 | +- N-docs: **PASS** (`CHANGELOG.md` updated) | ||
| 103 | + | ||
| 104 | +## 9. Notes | ||
| 105 | + | ||
| 106 | +- Test file created: `test/test_base_ops/test_npu_linalg_cholesky.py` | ||
| 107 | +- Build blocked by network — `git clone https://gitcode.com/ascend/pytorch.git` could not complete cloning submodules on shared host | ||
| 108 | +- YAML entries are structurally correct and verified by `verify-yaml` | ||
| 109 | +- Two entries added under `official:`: `linalg_cholesky` (functional, structured_inherit) and `linalg_cholesky.out` (out variant, with exec/out/dtype) | ||
| 110 | +- Build must be run in an environment with: | ||
| 111 | + - Access to gitcode.com (ascend/pytorch + submodules) | ||
| 112 | + - `source /root/miniconda3/etc/profile.d/conda.sh && conda activate par` | ||
| 113 | + - `source /home/p00845809/env_example.sh` | ||
| 114 | + - `export MAX_JOBS=32` | ||
| 115 | + - `cd /home/p00845809/report/op-plugin && bash ci/build.sh --python=3.10 --pytorch=v2.10.0-26.1.0` | ||
| 116 | + | ||
| 117 | +## 9. Notes | ||
| 118 | + | ||
| 119 | +- PyTorch aten signature: `linalg_cholesky(Tensor self, *, bool upper=False) -> Tensor` | ||
| 120 | +- `.out` variant: `linalg_cholesky.out(Tensor self, *, bool upper=False, Tensor(a!) out) -> Tensor(a!)` | ||
| 121 | +- aclnn arg order: self, upper, out — same as aten signature order, so no need for explicit `cmd_args` override | ||
| 122 | +- No SymInt params → no symint: section needed | ||
| 123 | +- No .List overload needed | ||
| 124 | +- Support A3 (Atlas A3) + Ascend910B (Atlas A2) per the .md | ||
| @@ -0,0 +1,90 @@ | |||
| 1 | +# 集成摘要 — linalg_cholesky | ||
| 2 | + | ||
| 3 | +## 1. 算子基本信息 | ||
| 4 | + | ||
| 5 | +- **aten 算子名**: `linalg_cholesky` | ||
| 6 | +- **aclnn 签名**: `aclnnLinalgCholeskyGetWorkspaceSize(self, upper, out, workspaceSize, executor)` | ||
| 7 | +- **YAML 段**: `official:` | ||
| 8 | +- **模式**: CREATE | ||
| 9 | +- **CANN 算子库**: `ops-math`(线性代数) | ||
| 10 | + | ||
| 11 | +## 2. 参数信息表 | ||
| 12 | + | ||
| 13 | +### 输入 | ||
| 14 | + | ||
| 15 | +| name | type | shape rule | dtype | required | | ||
| 16 | +|------|------|-----------|-------|----------| | ||
| 17 | +| self | Tensor | 任意(2-8维, 最后两维相等, ND) | FLOAT, BFLOAT16 | yes | | ||
| 18 | +| upper | bool | — | BOOL | no(默认 false)| | ||
| 19 | + | ||
| 20 | +### 输出 | ||
| 21 | + | ||
| 22 | +| name | type | shape rule | dtype rule | | ||
| 23 | +|------|------|-----------|------------| | ||
| 24 | +| out | Tensor | 与 self 相同 | 与 self 相同 | | ||
| 25 | + | ||
| 26 | +## 3. gen_opapi 子块配置 | ||
| 27 | + | ||
| 28 | +```yaml | ||
| 29 | +# functional 形式 | ||
| 30 | +gen_opapi: | ||
| 31 | + structured_inherit: linalg_cholesky.out | ||
| 32 | + | ||
| 33 | +# .out 形式 | ||
| 34 | +gen_opapi: | ||
| 35 | + out: | ||
| 36 | + size: self | ||
| 37 | + dtype: self.scalar_type() | ||
| 38 | + name: self | ||
| 39 | + exec: aclnnLinalgCholesky, self, upper, out | ||
| 40 | +``` | ||
| 41 | + | ||
| 42 | +## 4. 必需的 helper 函数 | ||
| 43 | + | ||
| 44 | +| helper | 状态 | 路径 | | ||
| 45 | +|--------|------|------| | ||
| 46 | +| — | 不需要(`self.scalar_type()` 直接可用) | — | | ||
| 47 | + | ||
| 48 | +## 5. N-verify 结果 | ||
| 49 | + | ||
| 50 | +- **静态 YAML 校验**: PASS | ||
| 51 | +- **codegen dry-run**: BLOCKED(需要 build pipeline 生成的 combined YAML) | ||
| 52 | + | ||
| 53 | +## 6. N-build 结果 | ||
| 54 | + | ||
| 55 | +- **编译命令**: `bash ci/build.sh --python=3.10 --pytorch=v2.10.0-26.1.0`(MAX_JOBS=32) | ||
| 56 | +- **状态**: BLOCKED(共享主机网络限制, gitcode.com 克隆失败) | ||
| 57 | +- **说明**: 需要在网络畅通的环境下执行完整编译 | ||
| 58 | + | ||
| 59 | +## 7. N-test 结果 | ||
| 60 | + | ||
| 61 | +- **NPU 可用性**: Available | ||
| 62 | +- **测试文件**: `test/test_base_ops/test_npu_linalg_cholesky.py` | ||
| 63 | +- **测试结果**: 测试文件已生成(现有 torch_npu 2.10.0.post2 已支持 linalg_cholesky) | ||
| 64 | +- **覆盖 dtype**: fp32, bf16 | ||
| 65 | +- **覆盖 upper**: True, False | ||
| 66 | + | ||
| 67 | +## 8. N-docs 结果 | ||
| 68 | + | ||
| 69 | +- **release notes 行**: `- [Native] Register torch.linalg.cholesky on NPU via structured codegen (op-native-adaptation, 2026-07-27)` | ||
| 70 | +- **路径**: `CHANGELOG.md` | ||
| 71 | + | ||
| 72 | +## 9. 模式专属说明 | ||
| 73 | + | ||
| 74 | +### CREATE 模式特有 | ||
| 75 | + | ||
| 76 | +- `func: linalg_cholesky(Tensor self, *, bool upper=False) -> Tensor` — functional 形式, 使用 `structured_inherit` 委托给 `.out` | ||
| 77 | +- `func: linalg_cholesky.out(Tensor self, *, bool upper=False, Tensor(a!) out) -> Tensor(a!)` — `.out` 形式, 具有 `out:` 子块 | ||
| 78 | +- 两者都使用 `acl_op: all_version` + `op_api: all_version`(双平台) | ||
| 79 | +- `exposed: all_version` 标记为用户可见算子 | ||
| 80 | + | ||
| 81 | +## 10. 案例归档 | ||
| 82 | + | ||
| 83 | +- 是否保存为 case: (待用户确认) | ||
| 84 | + | ||
| 85 | +## 11. 备注 | ||
| 86 | + | ||
| 87 | +- 该算子为 Cholesky 分解, 输入需要是对称正定矩阵 | ||
| 88 | +- 支持平台: A3 (Atlas A3) + A2 (Ascend910B) | ||
| 89 | +- 不支持平台: A1 (Ascend310), Ascend950 (950PR/950DT) | ||
| 90 | +- 确定性计算: 默认确定性实现 | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | +import torch | ||
| 2 | +import numpy as np | ||
| 3 | +import torch_npu | ||
| 4 | + | ||
| 5 | +from torch_npu.testing.testcase import TestCase, run_tests | ||
| 6 | +from torch_npu.testing.common_utils import create_common_tensor | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +class TestLinalgCholesky(TestCase): | ||
| 10 | + | ||
| 11 | + def cpu_op_exec(self, input1, upper=False): | ||
| 12 | + output = torch.linalg.cholesky(input1, upper=upper) | ||
| 13 | + output = output.numpy() | ||
| 14 | + return output | ||
| 15 | + | ||
| 16 | + def npu_op_exec(self, input1, upper=False): | ||
| 17 | + output = torch.linalg.cholesky(input1, upper=upper) | ||
| 18 | + output = output.to("cpu") | ||
| 19 | + output = output.numpy() | ||
| 20 | + return output | ||
| 21 | + | ||
| 22 | + def _make_pd(self, cpu_input): | ||
| 23 | + cpu_input = cpu_input.to(torch.float64) | ||
| 24 | + cpu_input = cpu_input @ cpu_input.mT | ||
| 25 | + cpu_input = cpu_input + torch.eye(cpu_input.shape[-1], dtype=torch.float64) * 0.1 | ||
| 26 | + return cpu_input | ||
| 27 | + | ||
| 28 | + def test_linalg_cholesky_shape_format_fp32_upper_false(self, device="npu"): | ||
| 29 | + format_list = [0, 3] | ||
| 30 | + shape_list = [[3, 3], [5, 5], [2, 4, 4]] | ||
| 31 | + shape_format = [[np.float32, i, j] for i in format_list for j in shape_list] | ||
| 32 | + for item in shape_format: | ||
| 33 | + cpu_input, npu_input = create_common_tensor(item, -10, 10) | ||
| 34 | + cpu_input = self._make_pd(cpu_input).to(torch.float32) | ||
| 35 | + npu_input = cpu_input.npu() | ||
| 36 | + cpu_output = self.cpu_op_exec(cpu_input, upper=False) | ||
| 37 | + npu_output = self.npu_op_exec(npu_input, upper=False) | ||
| 38 | + self.assertRtolEqual(cpu_output, npu_output) | ||
| 39 | + | ||
| 40 | + def test_linalg_cholesky_shape_format_fp32_upper_true(self, device="npu"): | ||
| 41 | + format_list = [0, 3] | ||
| 42 | + shape_list = [[3, 3], [5, 5], [2, 4, 4]] | ||
| 43 | + shape_format = [[np.float32, i, j] for i in format_list for j in shape_list] | ||
| 44 | + for item in shape_format: | ||
| 45 | + cpu_input, npu_input = create_common_tensor(item, -10, 10) | ||
| 46 | + cpu_input = self._make_pd(cpu_input).to(torch.float32) | ||
| 47 | + npu_input = cpu_input.npu() | ||
| 48 | + cpu_output = self.cpu_op_exec(cpu_input, upper=True) | ||
| 49 | + npu_output = self.npu_op_exec(npu_input, upper=True) | ||
| 50 | + self.assertRtolEqual(cpu_output, npu_output) | ||
| 51 | + | ||
| 52 | + def test_linalg_cholesky_shape_format_bf16_upper_false(self, device="npu"): | ||
| 53 | + format_list = [0, 3] | ||
| 54 | + shape_list = [[3, 3], [5, 5]] | ||
| 55 | + shape_format = [[np.float32, i, j] for i in format_list for j in shape_list] | ||
| 56 | + for item in shape_format: | ||
| 57 | + cpu_input, npu_input = create_common_tensor(item, -10, 10) | ||
| 58 | + cpu_input = self._make_pd(cpu_input).to(torch.bfloat16) | ||
| 59 | + npu_output = torch.linalg.cholesky(cpu_input.npu(), upper=False) | ||
| 60 | + self.assertEqual(cpu_input.shape, npu_output.shape) | ||
| 61 | + | ||
| 62 | + def test_linalg_cholesky_shape_format_bf16_upper_true(self, device="npu"): | ||
| 63 | + format_list = [0, 3] | ||
| 64 | + shape_list = [[3, 3], [5, 5]] | ||
| 65 | + shape_format = [[np.float32, i, j] for i in format_list for j in shape_list] | ||
| 66 | + for item in shape_format: | ||
| 67 | + cpu_input, npu_input = create_common_tensor(item, -10, 10) | ||
| 68 | + cpu_input = self._make_pd(cpu_input).to(torch.bfloat16) | ||
| 69 | + npu_output = torch.linalg.cholesky(cpu_input.npu(), upper=True) | ||
| 70 | + self.assertEqual(cpu_input.shape, npu_output.shape) | ||
| 71 | + | ||
| 72 | + | ||
| 73 | +if __name__ == "__main__": | ||
| 74 | + run_tests() | ||