已合并
[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
已合并
共 3 个文件变更+54-9
| @@ -34,17 +34,22 @@ at::Tensor hardswish_backward(const at::Tensor & grad_output, const at::Tensor & | |||
| 34 | at::Tensor hardswish_backward(const at::Tensor & grad_output, const at::Tensor & self) | 34 | at::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 | 55 | ||
| @@ -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 | ||
| 62 | if __name__ == "__main__": | 80 | if __name__ == "__main__": |
| 63 | run_tests() | 81 | run_tests() |
| @@ -8,7 +8,7 @@ from torch_npu.testing.common_utils import create_common_tensor | |||
| 8 | 8 | ||
| 9 | class TestHardSwishBackWard(TestCase): | 9 | class TestHardSwishBackWard(TestCase): |
| 10 | def cpu_op_exec(self, input1): | 10 | def cpu_op_exec(self, input1): |
| 11 | - input1.requires_grad = True | 11 | + 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.grad | 14 | output_grad = input1.grad |
| @@ -18,7 +18,7 @@ class TestHardSwishBackWard(TestCase): | |||
| 18 | return cpu_output, output_grad | 18 | 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 = True | 21 | + 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 | ||
| 76 | if __name__ == "__main__": | 98 | if __name__ == "__main__": |
| 77 | run_tests() | 99 | run_tests() |