| @@ -0,0 +1,33 @@ | |||
| 1 | +import torch | ||
| 2 | +from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests | ||
| 3 | +from testutils import TestUtils | ||
| 4 | +import torch_npu | ||
| 5 | +import torch_npu._inductor | ||
🔵 Low Priority
建议:确认 ![]() ![]() | |||
| 6 | +from torch._inductor.utils import run_and_get_code | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +class TestNanquantileDefault(TestUtils): | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + def test_nanquantile(self, shape, dtype, dynamic): | ||
| 15 | + a = torch.randn(shape, dtype=torch.float32, device="npu") | ||
| 16 | + a[0, 0] = float('nan') | ||
| 17 | + q = torch.tensor([0.25, 0.5, 0.75], dtype=torch.float32, device="npu") | ||
🔵 Low Priority 第 14 行通过 同时第 18 行的 建议:将硬编码的 ![]() ![]() | |||
| 18 | + | ||
| 19 | + def fn(a, q): | ||
| 20 | + return torch.ops.aten.nanquantile.default(a, q, dim=0, keepdim=False) | ||
| 21 | + | ||
| 22 | + r1 = fn(a, q) | ||
| 23 | + func = torch.compile(fn, backend="inductor", dynamic=dynamic) | ||
| 24 | + r, codes = run_and_get_code(func, a, q) | ||
| 25 | + self.assertEqual(r, r1, atol=1e-3, rtol=1e-3) | ||
| 26 | + self.assertTrue('nanquantile' in codes[0]) | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +instantiate_parametrized_tests(TestNanquantileDefault) | ||
| 30 | + | ||
| 31 | + | ||
| 32 | +if __name__ == "__main__": | ||
| 33 | + run_tests() | ||
| @@ -85,6 +85,9 @@ def _load_triton_backend(): | |||
| 85 | disable_foreach, | 85 | disable_foreach, |
| 86 | get_current_raw_stream, | 86 | get_current_raw_stream, |
| 87 | ) | 87 | ) |
| 88 | + from ._npu_meta_registration import npu_patch_meta | ||
| 89 | + | ||
| 90 | + npu_patch_meta() | ||
| 88 | 91 | ||
| 89 | def _inductor_register_backend_for_device(): | 92 | def _inductor_register_backend_for_device(): |
| 90 | from .codegen.cpp_wrapper import CppWrapperNpu | 93 | from .codegen.cpp_wrapper import CppWrapperNpu |
| @@ -19,6 +19,7 @@ from torch._dynamo.exc import Unsupported | |||
| 19 | from torch._dynamo.variables.lists import TupleVariable | 19 | from torch._dynamo.variables.lists import TupleVariable |
| 20 | from torch._dynamo.variables.nn_module import NNModuleVariable | 20 | from torch._dynamo.variables.nn_module import NNModuleVariable |
| 21 | from torch._decomp import meta_table | 21 | from torch._decomp import meta_table |
| 22 | +from torch._meta_registrations import device_hint | ||
| 22 | import torch_npu | 23 | import torch_npu |
| 23 | 24 | ||
| 24 | aten = torch.ops.aten | 25 | aten = torch.ops.aten |
| @@ -109,7 +110,9 @@ def patch_torch_decomp_decompositions(): | |||
| 109 | 110 | ||
| 110 | def register_meta_npu(op, avoid_fallback_flag=False, inductor_decomp=False): | 111 | def register_meta_npu(op, avoid_fallback_flag=False, inductor_decomp=False): |
| 111 | def meta_decorator(fn: Callable): | 112 | def meta_decorator(fn: Callable): |
| 112 | - _add_op_to_meta_table(op, fn, avoid_fallback_flag, inductor_decomp) | 113 | + ops = op if isinstance(op, list) else [op] |
| 114 | + for single_op in ops: | ||
| 115 | + _add_op_to_meta_table(single_op, fn, avoid_fallback_flag, inductor_decomp) | ||
| 113 | return fn | 116 | return fn |
| 114 | 117 | ||
| 115 | return meta_decorator | 118 | return meta_decorator |
| @@ -148,6 +151,26 @@ def npu_patch_meta(): | |||
| 148 | patch_torch_inductor_decompositions() | 151 | patch_torch_inductor_decompositions() |
| 149 | 152 | ||
| 150 | 153 | ||
| 154 | + | ||
| 155 | + [ | ||
| 156 | + aten.sort.default, | ||
| 157 | + aten.sort.stable, | ||
| 158 | + aten.sort.values, | ||
| 159 | + aten.sort.values_stable, | ||
| 160 | + ] | ||
| 161 | + , avoid_fallback_flag=True | ||
| 162 | +) | ||
| 163 | +def meta_sort(self, stable=None, dim=-1, descending=False, values=None, indices=None): | ||
| 164 | + if device_hint(self) == "npu": | ||
| 165 | + v = torch.empty(self.shape, dtype=self.dtype, device=self.device) | ||
| 166 | + i = torch.empty(self.shape, dtype=torch.int64, device=self.device) | ||
| 167 | + | ||
| 168 | + return v, i | ||
| 169 | + else: | ||
| 170 | + from torch._meta_registrations import meta_sort | ||
| 171 | + meta_sort(self, stable=stable, dim=dim, descending=descending, values=values, indices=indices) | ||
| 172 | + | ||
| 173 | + | ||
| 151 | 174 | ||
| 152 | def meta_index_put_patch(self, indices, values, accumulate=False): | 175 | def meta_index_put_patch(self, indices, values, accumulate=False): |
| 153 | return self.new_empty(self.shape) | 176 | return self.new_empty(self.shape) |
| @@ -13,10 +13,3 @@ def apply_npu_format_patch(): | |||
| 13 | from torch_npu.npu._format import _apply_npu_format_patch | 13 | from torch_npu.npu._format import _apply_npu_format_patch |
| 14 | 14 | ||
| 15 | _apply_npu_format_patch() | 15 | _apply_npu_format_patch() |
| 16 | - | ||
| 17 | - | ||
| 18 | - | ||
| 19 | -def apply_npu_meta_patch(): | ||
| 20 | - from torch_npu.utils._npu_meta_registration import npu_patch_meta | ||
| 21 | - | ||
| 22 | - npu_patch_meta() | ||


🔵 Low Priority
新文件
test_nanquantile_defaul.py的文件名中 "defaul" 缺少末尾字母 "t",应为 "default"。该测试测试的是torch.ops.aten.nanquantile.default,文件名意图明显是test_nanquantile_default。同目录下没有其他类似拼写错误的文件。虽然这只是文件名问题,不影响 Python 运行,但会误导其他开发者,且与项目命名规范不一致。建议:将文件名改为
test_nanquantile_default.py。