已合并
Enable deterministic computation for MaxUnpool1d, 2d, 3d in Inductor #29874
yvjc创建于 1月21日
Enable deterministic computation for MaxUnpool1d, 2d, 3d in Inductor #29874
已合并
yvjc创建于 1月21日
已删除 :deter280合入到Ascend/pytorchv2.8.0
2 个文件变更+125-0
@@ -0,0 +1,98 @@
1+import torch
2+import torch.nn as nn
3+from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests
4+from testutils import TestUtils
5+import torch_npu
6+ 
7+ 
8+class TestMaxUnpool1d(TestUtils):
9+ @parametrize('shape', [(1, 2, 500)])
10+ @parametrize('dtype', ['float16', 'float32'])
11+ @parametrize('kernel_size', [2])
12+ @parametrize('stride', [2])
13+ def test_maxunpool1d(self, shape, dtype, kernel_size, stride):
14+ torch.use_deterministic_algorithms(True)
15+ 
16+ input_tensor = self._generate_tensor(shape, dtype)
17+ 
18+ pool = nn.MaxPool1d(kernel_size=kernel_size, stride=stride, return_indices=True)
19+ x_cpu, indices_cpu = pool(input_tensor.cpu())
20+ 
21+ x = x_cpu.npu()
22+ indices = indices_cpu.npu()
23+ 
24+ unpool = nn.MaxUnpool1d(kernel_size=kernel_size, stride=stride).npu()
25+ 
26+ def unpool_forward(x, indices):
27+ return unpool(x, indices)
28+ 
29+ maxunpool_res = unpool_forward(x, indices)
30+ unpool_compiled = torch.compile(unpool_forward, backend="inductor")
31+ inductor_res = unpool_compiled(x, indices)
32+ 
33+ self.assertEqual(maxunpool_res, inductor_res, atol=1e-3, rtol=1e-3)
34+ 
35+ 
36+class TestMaxUnpool2d(TestUtils):
37+ @parametrize('shape', [(2, 8, 64, 128)])
38+ @parametrize('dtype', ['float16', 'float32'])
39+ @parametrize('kernel_size', [2])
40+ @parametrize('stride', [2])
41+ def test_maxunpool2d(self, shape, dtype, kernel_size, stride):
42+ torch.use_deterministic_algorithms(True)
43+ 
44+ input_tensor = self._generate_tensor(shape, dtype)
45+ 
46+ pool = nn.MaxPool2d(kernel_size=kernel_size, stride=stride, return_indices=True)
47+ x_cpu, indices_cpu = pool(input_tensor.cpu())
48+ 
49+ x = x_cpu.npu()
50+ indices = indices_cpu.npu()
51+ 
52+ unpool = nn.MaxUnpool2d(kernel_size=kernel_size, stride=stride).npu()
53+ 
54+ def unpool_forward(x, indices):
55+ return unpool(x, indices)
56+ 
57+ maxunpool_res = unpool_forward(x, indices)
58+ unpool_compiled = torch.compile(unpool_forward, backend="inductor")
59+ inductor_res = unpool_compiled(x, indices)
60+ 
61+ self.assertEqual(maxunpool_res, inductor_res, atol=1e-3, rtol=1e-3)
62+ 
63+ 
64+class TestMaxUnpool3d(TestUtils):
65+ @parametrize('shape', [(20, 16, 51, 33)])
66+ @parametrize('dtype', ['float16', 'float32'])
67+ @parametrize('kernel_size', [3])
68+ @parametrize('stride', [2])
69+ def test_maxunpool3d(self, shape, dtype, kernel_size, stride):
70+ torch.use_deterministic_algorithms(True)
71+ 
72+ input_tensor = self._generate_tensor(shape, dtype)
73+ 
74+ pool = nn.MaxPool3d(kernel_size=kernel_size, stride=stride, return_indices=True)
75+ x_cpu, indices_cpu = pool(input_tensor.cpu())
76+ 
77+ x = x_cpu.npu()
78+ indices = indices_cpu.npu()
79+ 
80+ unpool = nn.MaxUnpool3d(kernel_size=kernel_size, stride=stride).npu()
81+ 
82+ def unpool_forward(x, indices):
83+ return unpool(x, indices)
84+ 
85+ maxunpool_res = unpool_forward(x, indices)
86+ unpool_compiled = torch.compile(unpool_forward, backend="inductor")
87+ inductor_res = unpool_compiled(x, indices)
88+ 
89+ self.assertEqual(maxunpool_res, inductor_res, atol=1e-3, rtol=1e-3)
90+ 
91+ 
92+instantiate_parametrized_tests(TestMaxUnpool1d)
93+instantiate_parametrized_tests(TestMaxUnpool2d)
94+instantiate_parametrized_tests(TestMaxUnpool3d)
95+ 
96+ 
97+if __name__ == "__main__":
98+ run_tests()
@@ -1,3 +1,8 @@
1+import operator
2+from functools import reduce
3+ 
4+import torch
5+from torch._prims_common import TensorLike
1from torch._inductor.codegen.common import DeviceOpOverrides, register_device_op_overrides6from torch._inductor.codegen.common import DeviceOpOverrides, register_device_op_overrides
2 7 
3 8 
@@ -17,3 +22,25 @@ class NPUDeviceOpOverrides(DeviceOpOverrides):
17 22 
18def _inductor_register_device_op_overrides():23def _inductor_register_device_op_overrides():
19 register_device_op_overrides('npu', NPUDeviceOpOverrides())24 register_device_op_overrides('npu', NPUDeviceOpOverrides())
25+ 
26+ 
27+aten = torch.ops.aten
28+ 
29+ 
30+def _max_unpoolnd_patch(
31+ self: TensorLike, indices: TensorLike, output_size: list[int], dim: int
32+):
33+ nc = reduce(operator.mul, self.shape[:-dim])
34+ hw = reduce(operator.mul, output_size)
35+ indices_nc_shape = [1] * self.ndim
36+ indices_nc_shape[:-dim] = self.shape[:-dim]
37+ indices_flat = (
38+ indices + aten.arange(nc, device=self.device).view(indices_nc_shape) * hw
39+ ).reshape(-1)
40+ 
41+ output = self.new_zeros(list(self.shape[:-dim]) + list(output_size))
42+ return aten._unsafe_index_put(
43+ output.reshape(-1), [indices_flat], self.reshape(-1), accumulate=False
44+ ).view(output.shape)
45+ 
46+torch._decomp.decompositions._max_unpoolnd = _max_unpoolnd_patch