From 5785fc3e80bddf1af04fda270b869881363e3308 Mon Sep 17 00:00:00 2001 From: JP <46308822+zonglinpeng@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:46:17 -0800 Subject: [PATCH] add unit test for op_add (#7087) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add op_add shapes to generate as binaries (#7087) Summary: generates the add model pte’s for cadence to execute on. will use graph builder in later diffs Test Plan: Imported from GitHub, without a `Test Plan:` line. {F1968254537} Reviewed By: hsharma35 Differential Revision: D66510372 Pulled By: zonglinpeng --- backends/cadence/aot/TARGETS | 20 ++++ backends/cadence/aot/export_example.py | 14 +-- backends/cadence/aot/utils.py | 3 +- backends/cadence/runtime/TARGETS | 2 + examples/cadence/operators/TARGETS | 26 +++++ examples/cadence/operators/test_add_op.py | 115 ++++++++++++++++++++++ 6 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 examples/cadence/operators/TARGETS create mode 100644 examples/cadence/operators/test_add_op.py diff --git a/backends/cadence/aot/TARGETS b/backends/cadence/aot/TARGETS index 24b0266911..661f8cf0d4 100644 --- a/backends/cadence/aot/TARGETS +++ b/backends/cadence/aot/TARGETS @@ -50,6 +50,26 @@ python_library( ], ) +python_library( + name = "export_example", + srcs = [ + "export_example.py", + ], + deps = [ + ":passes", + ":utils", + ":ops_registrations", + ":replace_ops", + "//caffe2:torch", + "//executorch/backends/cadence/aot/quantizer:fusion_pass", + "//executorch/backends/cadence/runtime:runtime", + "//executorch/backends/cadence/aot/quantizer:quantizer", + "//executorch/backends/transforms:decompose_sdpa", + "//executorch/backends/transforms:remove_clone_ops", + "//executorch/exir:lib", + "//executorch/devtools:lib", + ], +) python_library( name = "pass_utils", diff --git a/backends/cadence/aot/export_example.py b/backends/cadence/aot/export_example.py index 146d4f806c..4ba5bffc96 100644 --- a/backends/cadence/aot/export_example.py +++ b/backends/cadence/aot/export_example.py @@ -60,6 +60,7 @@ def export_model( model: nn.Module, example_inputs: Tuple[Any, ...], file_name: str = "CadenceDemoModel", + run_and_compare: bool = True, ): # create work directory for outputs and model binary working_dir = tempfile.mkdtemp(dir="/tmp") @@ -112,9 +113,10 @@ def export_model( ) # TODO: move to test infra - runtime.run_and_compare( - executorch_prog=exec_prog, - inputs=example_inputs, - ref_outputs=ref_outputs, - working_dir=working_dir, - ) + if run_and_compare: + runtime.run_and_compare( + executorch_prog=exec_prog, + inputs=example_inputs, + ref_outputs=ref_outputs, + working_dir=working_dir, + ) diff --git a/backends/cadence/aot/utils.py b/backends/cadence/aot/utils.py index e8b64ef567..534b4f0d9f 100644 --- a/backends/cadence/aot/utils.py +++ b/backends/cadence/aot/utils.py @@ -162,7 +162,8 @@ def print_ops_info( # Print the final ops and their counts in a tabular format logging.info( - tabulate( + "\n" + + tabulate( sorted_ops_count, headers=[ "Final Operators ", # one character longer than the longest op name diff --git a/backends/cadence/runtime/TARGETS b/backends/cadence/runtime/TARGETS index 1b55a7d541..db3fe0ad1e 100644 --- a/backends/cadence/runtime/TARGETS +++ b/backends/cadence/runtime/TARGETS @@ -7,6 +7,8 @@ python_library( srcs = [ "__init__.py", "executor.py", + "runtime.py", + "utils.py" ] + glob([ "xtsc-cfg/**/*", ]), diff --git a/examples/cadence/operators/TARGETS b/examples/cadence/operators/TARGETS new file mode 100644 index 0000000000..732f1ced09 --- /dev/null +++ b/examples/cadence/operators/TARGETS @@ -0,0 +1,26 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +load("@fbcode_macros//build_defs:python_unittest.bzl", "python_unittest") + +oncall("odai_jarvis") + + +python_unittest( + name = "test_add_op", + srcs = [ + "test_add_op.py", + ], + typing = True, + supports_static_listing = False, + deps = [ + "fbsource//third-party/pypi/parameterized:parameterized", + "//caffe2:torch", + "//executorch/backends/cadence/aot:ops_registrations", + "//executorch/backends/cadence/aot:export_example", + "//executorch/backends/cadence/aot:compiler", + ], +) diff --git a/examples/cadence/operators/test_add_op.py b/examples/cadence/operators/test_add_op.py new file mode 100644 index 0000000000..5481540b4f --- /dev/null +++ b/examples/cadence/operators/test_add_op.py @@ -0,0 +1,115 @@ +# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import unittest +from typing import Tuple + +from parameterized import parameterized + +from executorch.backends.cadence.aot.ops_registrations import * # noqa + +import torch +import torch.nn as nn +from executorch.backends.cadence.aot.export_example import export_model + + +class ATenOpTestCases(unittest.TestCase): + @parameterized.expand( + [ + [(7, 5, 6), (7, 5, 6)], + [(7, 5, 6), (1)], + [(1), (7, 5, 6)], + [(1), (7, 5, 6), 2.23], + [(1), (7, 5, 6), -1.0], + [(1), (7, 5, 6), -2.23], + [(7, 5, 6), (7, 5, 6), 1.23], + [(6, 7), (6, 7)], + [(6, 7), (6, 7), 2], + # Broadcast tests (should be optimized on G3) + [(1, 32, 64), (1, 1, 64)], + [(1, 32, 64), (64)], + [(1, 1, 32), (32)], + [(16, 1, 16), (1, 1, 16)], + [(16, 1, 16), (16)], + [(1, 4, 8, 8), (1, 1, 8, 8)], + [(1, 4, 8, 8), (8, 8)], + # Broadcast tests (should go to portable ops) + [(1, 10, 1, 8), (4, 1, 4, 1)], + [(1, 1, 16), (1, 8, 1), 2.5], + # # aten.upsample_nearest2d tests + [(5, 6, 6, 8), (5, 6, 6, 8)], + [(1, 1, 12, 16), (1, 1, 12, 16)], + ] + ) + def test_aten_add_out( + self, Xshape: Tuple[int], Yshape: Tuple[int], alpha: float = 1 + ) -> None: + class AddTensor(nn.Module): + def __init__(self, alpha: float): + super().__init__() + self.alpha = alpha + + def forward(self, x: torch.Tensor, y: torch.Tensor): + return torch.add(x, y, alpha=self.alpha) + + model = AddTensor(alpha) + + X = torch.randn(Xshape) + Y = torch.randn(Yshape) + + model.eval() + export_model( + model, (X, Y), file_name=self._testMethodName, run_and_compare=False + ) + + @parameterized.expand( + [ + [(7, 5, 6), (7, 5, 6)], + [(7, 5, 6), (1)], + [(1), (7, 5, 6)], + [(1), (7, 5, 6), 2.23], + [(1), (7, 5, 6), -1.0], + [(1), (7, 5, 6), -2.23], + [(7, 5, 6), (7, 5, 6), 1.23], + [(6, 7), (6, 7)], + [(6, 7), (6, 7), 2], + # Broadcast tests (should be optimized on G3) + [(1, 32, 64), (1, 1, 64)], + [(1, 32, 64), (64)], + [(1, 1, 32), (32)], + [(16, 1, 16), (1, 1, 16)], + [(16, 1, 16), (16)], + [(1, 4, 8, 8), (1, 1, 8, 8)], + [(1, 4, 8, 8), (8, 8)], + # Broadcast tests (should go to portable ops) + [(1, 10, 1, 8), (4, 1, 4, 1)], + [(1, 1, 16), (1, 8, 1), 2.5], + # # aten.upsample_nearest2d tests + [(5, 6, 6, 8), (5, 6, 6, 8)], + [(1, 1, 12, 16), (1, 1, 12, 16)], + ] + ) + def test_aten_add_scalar_out( + self, Xshape: Tuple[int], Yshape: Tuple[int], alpha: float = 1 + ) -> None: + # Tensor-Scalar addition + class AddScalar(nn.Module): + def __init__(self, alpha: float): + super().__init__() + self.alpha = alpha + + def forward(self, x: torch.Tensor, y: float): + return torch.add(x, y, alpha=self.alpha) + + model = AddScalar(alpha) + + X = torch.randn(Xshape) + Y = 2.34 + + model.eval() + export_model( + model, (X, Y), file_name=self._testMethodName, run_and_compare=False + ) + + +if __name__ == "__main__": + unittest.main()