已合并
[feat] aclnnHardswishBackwardV2 has the same boundary values with the community #4978
culechan创建于 5月19日
[feat] aclnnHardswishBackwardV2 has the same boundary values with the community #4978
已合并
culechan创建于 5月19日
3 个文件变更+54-9
@@ -34,17 +34,22 @@ at::Tensor hardswish_backward(const at::Tensor & grad_output, const at::Tensor &
34at::Tensor hardswish_backward(const at::Tensor & grad_output, const at::Tensor & self)34at::Tensor hardswish_backward(const at::Tensor & grad_output, const at::Tensor & self)
35{35{
36 DO_COMPATIBILITY(aclnnHardswishBackward, acl_op::hardswish_backward(grad_output, self));36 DO_COMPATIBILITY(aclnnHardswishBackward, acl_op::hardswish_backward(grad_output, self));
37+ static const bool checkv2_is_available = check_aclnn_kernel_available("aclnnHardswishBackwardV2");
37 auto output_size_0 = self.sizes();38 auto output_size_0 = self.sizes();
38 auto output_dtype_0 = self.scalar_type();39 auto output_dtype_0 = self.scalar_type();
39 at::Tensor out = npu_preparation::apply_tensor_without_format(output_size_0,40 at::Tensor out = npu_preparation::apply_tensor_without_format(output_size_0,
40 grad_output.options().dtype(output_dtype_0));41 grad_output.options().dtype(output_dtype_0));
41- EXEC_NPU_CMD(aclnnHardswishBackward, grad_output, self, out);42+ if (checkv2_is_available) {
42- at::Tensor values_le3 = at::empty({}, self.options());43+ EXEC_NPU_CMD(aclnnHardswishBackwardV2, grad_output, self, out);
43- at::Tensor values_ge3 = at::empty({}, self.options());44+ } else {
44- op_api::fill_(values_le3, 0.0f);45+ EXEC_NPU_CMD(aclnnHardswishBackward, grad_output, self, out);
45- op_api::fill_(values_ge3, 1.0f);46+ at::Tensor values_le3 = at::empty({}, self.options());
46- out.index_put_({self.eq(-3.0f)}, values_le3);47+ at::Tensor values_ge3 = at::empty({}, self.options());
47- out.index_put_({self.eq(3.0f)}, values_ge3);48+ op_api::fill_(values_le3, 0.0f);
49+ op_api::fill_(values_ge3, 1.0f);
50+ out.index_put_({self.eq(-3.0f)}, values_le3);
51+ out.index_put_({self.eq(3.0f)}, values_ge3);
52+ }
48 return out;53 return out;
49}54}
50#endif55#endif
@@ -58,6 +58,24 @@ class TestHardSwish(TestCase):
58 58 
59 self.assertRtolEqual(cpu_output, npu_output)59 self.assertRtolEqual(cpu_output, npu_output)
60 60 
61+ def _boundary_values(self):
62+ """Values around hardswish boundaries -3 and 3."""
63+ return [-3.5, -3.1, -3.0, -2.999, -2.5, -1.0, 0.0, 1.0, 2.5, 2.999, 3.0, 3.1, 3.5]
64+ 
65+ def test_hardswish_boundary_fp32(self):
66+ boundary = torch.tensor([self._boundary_values()], dtype=torch.float32)
67+ cpu_output = self.cpu_op_exec(boundary)
68+ npu_input = boundary.to("npu")
69+ npu_output = self.npu_op_exec(npu_input)
70+ self.assertRtolEqual(cpu_output, npu_output)
71+ 
72+ def test_hardswish_boundary_fp16(self):
73+ cpu_input = torch.tensor([self._boundary_values()], dtype=torch.float32)
74+ cpu_output = self.cpu_op_exec(cpu_input)
75+ npu_input = torch.tensor([self._boundary_values()], dtype=torch.float16).to("npu")
76+ npu_output = self.npu_op_exec(npu_input)
77+ cpu_output = cpu_output.astype(npu_output.dtype)
78+ self.assertRtolEqual(cpu_output, npu_output)
61 79 
62if __name__ == "__main__":80if __name__ == "__main__":
63 run_tests()81 run_tests()
@@ -8,7 +8,7 @@ from torch_npu.testing.common_utils import create_common_tensor
8 8 
9class TestHardSwishBackWard(TestCase):9class TestHardSwishBackWard(TestCase):
10 def cpu_op_exec(self, input1):10 def cpu_op_exec(self, input1):
11- input1.requires_grad = True11+ input1 = input1.clone().detach().requires_grad_(True)
12 cpu_output = torch.nn.functional.hardswish(input1, inplace=False)12 cpu_output = torch.nn.functional.hardswish(input1, inplace=False)
13 cpu_output.backward(torch.ones_like(cpu_output))13 cpu_output.backward(torch.ones_like(cpu_output))
14 output_grad = input1.grad14 output_grad = input1.grad
@@ -18,7 +18,7 @@ class TestHardSwishBackWard(TestCase):
18 return cpu_output, output_grad18 return cpu_output, output_grad
19 19 
20 def npu_op_exec(self, input1):20 def npu_op_exec(self, input1):
21- input1.requires_grad = True21+ input1 = input1.clone().detach().requires_grad_(True)
22 output = torch.nn.functional.hardswish(input1, inplace=False)22 output = torch.nn.functional.hardswish(input1, inplace=False)
23 output.backward(torch.ones_like(output))23 output.backward(torch.ones_like(output))
24 output = output.to("cpu")24 output = output.to("cpu")
@@ -72,6 +72,28 @@ class TestHardSwishBackWard(TestCase):
72 self.assertRtolEqual(cpu_output, npu_output)72 self.assertRtolEqual(cpu_output, npu_output)
73 self.assertRtolEqual(cpu_output_grad, npu_output_grad)73 self.assertRtolEqual(cpu_output_grad, npu_output_grad)
74 74 
75+ def _boundary_values(self):
76+ """Values around hardswish boundaries -3 and 3."""
77+ return [-3.5, -3.1, -3.0, -2.999, -2.5, -1.0, 0.0, 1.0, 2.5, 2.999, 3.0, 3.1, 3.5]
78+ 
79+ def test_hardswish_boundary_fp32(self):
80+ boundary = torch.tensor([self._boundary_values()], dtype=torch.float32)
81+ cpu_output, cpu_grad = self.cpu_op_exec(boundary)
82+ npu_input = boundary.to("npu")
83+ npu_output, npu_grad = self.npu_op_exec(npu_input)
84+ self.assertRtolEqual(cpu_output, npu_output)
85+ self.assertRtolEqual(cpu_grad, npu_grad)
86+ 
87+ def test_hardswish_boundary_fp16(self):
88+ cpu_input = torch.tensor([self._boundary_values()], dtype=torch.float32)
89+ cpu_output, cpu_grad = self.cpu_op_exec(cpu_input)
90+ npu_input = torch.tensor([self._boundary_values()], dtype=torch.float16).to("npu")
91+ npu_output, npu_grad = self.npu_op_exec(npu_input)
92+ cpu_output = cpu_output.astype(npu_output.dtype)
93+ cpu_grad = cpu_grad.astype(npu_grad.dtype)
94+ self.assertRtolEqual(cpu_output, npu_output)
95+ self.assertRtolEqual(cpu_grad, npu_grad)
96+ 
75 97 
76if __name__ == "__main__":98if __name__ == "__main__":
77 run_tests()99 run_tests()