已合并
test: update AddV2 and TensorRedirect golden specs #4540
test: update AddV2 and TensorRedirect golden specs #4540
已合并
raoliang_sac创建于 14 天前
2 个文件变更+232-25
Aconversion/tensor_redirect/tests/assets/golden.py+121-0
@@ -0,0 +1,121 @@
1+#!/usr/bin/env python3
2+# -*- coding: UTF-8 -*-
3+# ----------------------------------------------------------------------------
4+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
5+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6+# CANN Open Software License Agreement Version 2.0 (the "License").
7+# Please refer to the License for details. You may not use this file except in compliance with the License.
8+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10+# See LICENSE in the root of the software repository for the full text of the License.
11+# ----------------------------------------------------------------------------
12+"""Bit-exact kernel/GEIR golden for TensorRedirect in TTK TestSpec format."""
13+ 
14+import numpy as np
15+import torch
16+ 
17+ 
18+__spec__ = {
19+ # Kernel and GEIR share the snake-case registration and the same TestSpec.
20+ "tensor_redirect": "TensorRedirectKernelSpec",
21+}
22+ 
23+# Retain the repository-facing legacy entry while consumers migrate to TestSpec.
24+__golden__ = {
25+ "kernel": {"tensor_redirect": "tensor_redirect_golden"},
26+}
27+ 
28+ 
29+_TOLERANCE = {
30+ "float16": {"standard": "binary_equal"},
31+ "float32": {"standard": "binary_equal"},
32+ "bfloat16": {"standard": "binary_equal"},
33+ "int8": {"standard": "binary_equal"},
34+ "uint8": {"standard": "binary_equal"},
35+ "int16": {"standard": "binary_equal"},
36+ "uint16": {"standard": "binary_equal"},
37+ "int32": {"standard": "binary_equal"},
38+ "uint32": {"standard": "binary_equal"},
39+ "int64": {"standard": "binary_equal"},
40+ "uint64": {"standard": "binary_equal"},
41+}
42+ 
43+ 
44+def _numpy_dtype(dtype):
45+ """Resolve TTK dtype values, including NumPy's optional bfloat16 dtype."""
46+ name = getattr(dtype, "name", str(dtype)).lower()
47+ if name in ("bf16", "bfloat16"):
48+ try:
49+ from ml_dtypes import bfloat16
50+ except ImportError as exc:
51+ raise RuntimeError(
52+ "TensorRedirect bfloat16 golden requires the optional ml-dtypes package"
53+ ) from exc
54+ return bfloat16
55+ return np.dtype(dtype)
56+ 
57+ 
58+def _output_dtypes(kwargs):
59+ values = kwargs.get("output_dtypes") or ()
60+ return [
61+ value[0] if isinstance(value, (list, tuple)) and value else value
62+ for value in values
63+ ]
64+ 
65+ 
66+def _to_torch_bit_exact(array):
67+ """Convert NumPy to torch without changing any payload bits."""
68+ array = np.asarray(array)
69+ if not array.flags.c_contiguous:
70+ array = np.ascontiguousarray(array)
71+ if array.dtype.name == "bfloat16":
72+ return torch.from_numpy(array.view(np.int16)).view(torch.bfloat16)
73+ return torch.from_numpy(array)
74+ 
75+ 
76+def _to_numpy_bit_exact(tensor):
77+ """Convert torch to NumPy while preserving BF16 payload bits."""
78+ tensor = tensor.detach().cpu().contiguous()
79+ if tensor.dtype == torch.bfloat16:
80+ return tensor.view(torch.int16).numpy().view(_numpy_dtype("bfloat16"))
81+ return tensor.numpy()
82+ 
83+ 
84+def _compute(x):
85+ """Copy through the independent PyTorch reference interface."""
86+ return [torch.clone(x)]
87+ 
88+ 
89+def _kernel_golden(x, **kwargs):
90+ outputs = [
91+ _to_numpy_bit_exact(output) for output in _compute(_to_torch_bit_exact(x))
92+ ]
93+ output_dtypes = _output_dtypes(kwargs)
94+ return [
95+ output.astype(_numpy_dtype(output_dtypes[index]), copy=False)
96+ if index < len(output_dtypes)
97+ else output
98+ for index, output in enumerate(outputs)
99+ ]
100+ 
101+ 
102+class TensorRedirectKernelSpec:
103+ """TestSpec shared by the TensorRedirect kernel and GEIR pathways."""
104+ 
105+ @staticmethod
106+ def golden(x, **kwargs):
107+ return _kernel_golden(x, **kwargs)
108+ 
109+ third_party = {"torch": "torch.clone"}
110+ tolerance = _TOLERANCE
111+ 
112+ 
113+def tensor_redirect_golden(x, **kwargs):
114+ """Legacy kernel entry backed by the same TestSpec computation."""
115+ if not kwargs.get("output_dtypes"):
116+ kwargs = {**kwargs, "output_dtypes": (x.dtype,)}
117+ return _kernel_golden(x, **kwargs)[0]
118+ 
119+ 
120+# 【不存在】ACLNN 通路:CMakeLists.txt 显式配置 ACLNNTYPE aclnn_exclude。
121+# 【不存在】e2e 通路:本算子不交付 ACLNN 符号,torch_npu 无对应绑定入口。
Mmath/add_v2/tests/assets/golden.py+111-25
@@ -9,36 +9,122 @@
9# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.9# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10# See LICENSE in the root of the software repository for the full text of the License.10# See LICENSE in the root of the software repository for the full text of the License.
11# ----------------------------------------------------------------------------11# ----------------------------------------------------------------------------
12+"""Kernel/GEIR golden for AddV2 using the TTK TestSpec format."""
13+ 
14+import numpy as np
12import torch15import torch
13 16 
17+ 
18+__spec__ = {
19+ # Kernel and GEIR share the snake-case registration and the same TestSpec.
20+ "add_v2": "AddV2KernelSpec",
21+}
22+ 
23+# Retain the repository-facing legacy entry while consumers migrate to TestSpec.
14__golden__ = {24__golden__ = {
15 "kernel": {"add_v2": "add_v2_golden"},25 "kernel": {"add_v2": "add_v2_golden"},
16}26}
17 27 
18 28 
19-def add_v2_golden(x1, x2, **kwargs):29+_TOLERANCE = {
20- """30+ "float16": {"standard": "cross_check", "level": "L1"},
21- Kernel golden for add_v2.31+ "float32": {"standard": "cross_check", "level": "L1"},
22- All the parameters follow @add_v2_def.cpp without outputs.32+ "bfloat16": {"standard": "cross_check", "level": "L1"},
23- All the input Tensors are numpy.ndarray.33+ "int8": {"standard": "binary_equal"},
24- kwargs may contain: short_soc_version, input_ori_shapes, output_ori_shapes,34+ "uint8": {"standard": "binary_equal"},
25- input_formats, output_formats, input_ori_formats, output_ori_formats,35+ "int16": {"standard": "binary_equal"},
26- input_dtypes, output_dtypes.36+ "int32": {"standard": "binary_equal"},
27- """37+ "int64": {"standard": "binary_equal"},
28- # 仅注册同 dtype 组合,x1/x2 dtype 恒等,输出 dtype 与 x1 一致38+ # TTK cross_check currently supports float16/bfloat16/float32 only.
29- dtype = x1.dtype39+ "complex64": {"standard": "stat_rel_err"},
30- if str(x2.dtype) != str(dtype):40+}
31- raise ValueError(
32- f"add_v2 only supports identical input dtypes, got x1={dtype}, x2={x2.dtype}"
33- )
34- # torch 无原生 bfloat16 numpy 视图,先升 float32 计算再还原
35- if "bfloat16" in str(dtype):
36- x1 = x1.astype("float32")
37- x2 = x2.astype("float32")
38- x = torch.from_numpy(x1)
39- y = torch.from_numpy(x2)
40- res = torch.add(x, y).numpy()
41- if "bfloat16" in str(dtype):
42- res = res.astype(dtype)
43 41 
44- return res42+ 
43+def _numpy_dtype(dtype):
44+ """Resolve TTK dtype values, including NumPy's optional bfloat16 dtype."""
45+ name = getattr(dtype, "name", str(dtype)).lower()
46+ if name in ("bf16", "bfloat16"):
47+ try:
48+ from ml_dtypes import bfloat16
49+ except ImportError as exc:
50+ raise RuntimeError(
51+ "AddV2 bfloat16 golden requires the optional ml-dtypes package"
52+ ) from exc
53+ return bfloat16
54+ return np.dtype(dtype)
55+ 
56+ 
57+def _output_dtypes(kwargs):
58+ values = kwargs.get("output_dtypes") or ()
59+ return [
60+ value[0] if isinstance(value, (list, tuple)) and value else value
61+ for value in values
62+ ]
63+ 
64+ 
65+def _to_torch(array):
66+ """Convert a contiguous NumPy tensor to torch without lowering precision."""
67+ array = np.asarray(array)
68+ if not array.flags.c_contiguous:
69+ array = np.ascontiguousarray(array)
70+ if array.dtype.name == "bfloat16":
71+ # CPU torch cannot consume an ml_dtypes array directly. Computing AddV2
72+ # in float32 and casting its output back is the established BF16 fallback.
73+ array = array.astype(np.float32)
74+ return torch.from_numpy(array)
75+ 
76+ 
77+def _to_numpy(tensor):
78+ tensor = tensor.detach().cpu().contiguous()
79+ if tensor.dtype == torch.bfloat16:
80+ return tensor.view(torch.int16).numpy().view(_numpy_dtype("bfloat16"))
81+ return tensor.numpy()
82+ 
83+ 
84+def _compute(x1, x2):
85+ """Compute AddV2 through the independent PyTorch reference interface."""
86+ if x1.dtype != x2.dtype:
87+ raise ValueError(
88+ f"add_v2 only supports identical input dtypes, got x1={x1.dtype}, "
89+ f"x2={x2.dtype}"
90+ )
91+ return [torch.add(x1, x2)]
92+ 
93+ 
94+def _kernel_golden(x1, x2, **kwargs):
95+ if x1.dtype.name != x2.dtype.name:
96+ raise ValueError(
97+ f"add_v2 only supports identical input dtypes, got x1={x1.dtype}, "
98+ f"x2={x2.dtype}"
99+ )
100+ 
101+ outputs = [_to_numpy(output) for output in _compute(_to_torch(x1), _to_torch(x2))]
102+ output_dtypes = _output_dtypes(kwargs)
103+ return [
104+ output.astype(_numpy_dtype(output_dtypes[index]), copy=False)
105+ if index < len(output_dtypes)
106+ else output
107+ for index, output in enumerate(outputs)
108+ ]
109+ 
110+ 
111+class AddV2KernelSpec:
112+ """TestSpec shared by the AddV2 kernel and GEIR pathways."""
113+ 
114+ @staticmethod
115+ def golden(x1, x2, **kwargs):
116+ return _kernel_golden(x1, x2, **kwargs)
117+ 
118+ third_party = {"torch": "torch.add"}
119+ tolerance = _TOLERANCE
120+ 
121+ 
122+def add_v2_golden(x1, x2, **kwargs):
123+ """Legacy kernel entry backed by the same TestSpec computation."""
124+ if not kwargs.get("output_dtypes"):
125+ kwargs = {**kwargs, "output_dtypes": (x1.dtype,)}
126+ return _kernel_golden(x1, x2, **kwargs)[0]
127+ 
128+ 
129+# 【不存在】ACLNN 通路:CMakeLists.txt 显式配置 ACLNNTYPE aclnn_exclude。
130+# 【不存在】e2e 通路:本算子不交付 ACLNN 符号,torch_npu 无对应绑定入口。