From a79b1a6a4e2984c250c91b3951aad56e604bcecd Mon Sep 17 00:00:00 2001 From: winskuo-quic <143469905+winskuo-quic@users.noreply.github.com> Date: Wed, 28 Aug 2024 10:22:03 +0800 Subject: [PATCH] Support regnet_x_400mf and regnet_y_400mf (#4925) --- backends/qualcomm/tests/test_qnn_delegate.py | 40 ++++ examples/qualcomm/oss_scripts/dino_v2.py | 6 - examples/qualcomm/oss_scripts/esrgan.py | 6 - .../oss_scripts/gMLP_image_classification.py | 6 - examples/qualcomm/oss_scripts/regnet.py | 181 ++++++++++++++++++ examples/qualcomm/oss_scripts/squeezenet.py | 6 - examples/qualcomm/oss_scripts/ssd300_vgg16.py | 6 - examples/qualcomm/scripts/deeplab_v3.py | 6 - examples/qualcomm/scripts/edsr.py | 6 - examples/qualcomm/scripts/inception_v3.py | 6 - examples/qualcomm/scripts/inception_v4.py | 6 - .../qualcomm/scripts/mobilebert_fine_tune.py | 6 - examples/qualcomm/scripts/mobilenet_v2.py | 6 - examples/qualcomm/scripts/mobilenet_v3.py | 6 - examples/qualcomm/scripts/torchvision_vit.py | 7 +- 15 files changed, 222 insertions(+), 78 deletions(-) create mode 100644 examples/qualcomm/oss_scripts/regnet.py diff --git a/backends/qualcomm/tests/test_qnn_delegate.py b/backends/qualcomm/tests/test_qnn_delegate.py index 08fd907c40..79b8443dc7 100644 --- a/backends/qualcomm/tests/test_qnn_delegate.py +++ b/backends/qualcomm/tests/test_qnn_delegate.py @@ -1668,6 +1668,46 @@ def test_gMLP(self): self.assertGreaterEqual(msg["top_1"], 60) self.assertGreaterEqual(msg["top_5"], 90) + def test_regnet(self): + if not self.required_envs([self.image_dataset]): + self.skipTest("missing required envs") + + weights = ["regnet_y_400mf", "regnet_x_400mf"] + cmds = [ + "python", + f"{self.executorch_root}/examples/qualcomm/oss_scripts/regnet.py", + "--dataset", + self.image_dataset, + "--artifact", + self.artifact_dir, + "--build_folder", + self.build_folder, + "--device", + self.device, + "--model", + self.model, + "--ip", + self.ip, + "--port", + str(self.port), + ] + if self.host: + cmds.extend(["--host", self.host]) + + for weight in weights: + p = subprocess.Popen( + cmds + ["--weights", weight], stdout=subprocess.DEVNULL + ) + with Listener((self.ip, self.port)) as listener: + conn = listener.accept() + p.communicate() + msg = json.loads(conn.recv()) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 85) + def test_ssd300_vgg16(self): if not self.required_envs([self.pretrained_weight, self.oss_repo]): self.skipTest("missing required envs") diff --git a/examples/qualcomm/oss_scripts/dino_v2.py b/examples/qualcomm/oss_scripts/dino_v2.py index b3fecfbbe6..a8241e34a7 100644 --- a/examples/qualcomm/oss_scripts/dino_v2.py +++ b/examples/qualcomm/oss_scripts/dino_v2.py @@ -105,12 +105,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/oss_scripts/esrgan.py b/examples/qualcomm/oss_scripts/esrgan.py index 56871db764..df02374e4b 100644 --- a/examples/qualcomm/oss_scripts/esrgan.py +++ b/examples/qualcomm/oss_scripts/esrgan.py @@ -74,12 +74,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/oss_scripts/gMLP_image_classification.py b/examples/qualcomm/oss_scripts/gMLP_image_classification.py index 864a9b919f..cbcd6d88cb 100644 --- a/examples/qualcomm/oss_scripts/gMLP_image_classification.py +++ b/examples/qualcomm/oss_scripts/gMLP_image_classification.py @@ -96,12 +96,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where artifacts were built - # pte_path : path where QNN delegate executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/oss_scripts/regnet.py b/examples/qualcomm/oss_scripts/regnet.py new file mode 100644 index 0000000000..0dc70608da --- /dev/null +++ b/examples/qualcomm/oss_scripts/regnet.py @@ -0,0 +1,181 @@ +# Copyright (c) Qualcomm Innovation Center, Inc. +# 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. + +import json +import os +import sys +from multiprocessing.connection import Client + +import numpy as np +import torch +from executorch.backends.qualcomm.quantizer.quantizer import QuantDtype +from executorch.examples.qualcomm.utils import ( + build_executorch_binary, + make_output_dir, + parse_skip_delegation_node, + setup_common_args_and_variables, + SimpleADB, + topk_accuracy, +) + +from torchvision.models import ( + regnet_x_400mf, + RegNet_X_400MF_Weights, + regnet_y_400mf, + RegNet_Y_400MF_Weights, +) + + +def get_dataset(dataset_path, data_size): + from torchvision import datasets, transforms + + def get_data_loader(): + preprocess = transforms.Compose( + [ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ) + imagenet_data = datasets.ImageFolder(dataset_path, transform=preprocess) + return torch.utils.data.DataLoader( + imagenet_data, + shuffle=True, + ) + + # prepare input data + inputs, targets, input_list = [], [], "" + data_loader = get_data_loader() + for index, data in enumerate(data_loader): + if index >= data_size: + break + feature, target = data + inputs.append((feature,)) + for element in target: + targets.append(element) + input_list += f"input_{index}_0.raw\n" + + return inputs, targets, input_list + + +def main(args): + skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) + + # ensure the working directory exist. + os.makedirs(args.artifact, exist_ok=True) + + if not args.compile_only and args.device is None: + raise RuntimeError( + "device serial is required if not compile only. " + "Please specify a device serial by -s/--device argument." + ) + + data_num = 100 + inputs, targets, input_list = get_dataset( + dataset_path=f"{args.dataset}", + data_size=data_num, + ) + + if args.weights == "regnet_y_400mf": + weights = RegNet_Y_400MF_Weights.DEFAULT + model = regnet_y_400mf(weights=weights).eval() + pte_filename = "regnet_y_400mf" + else: + weights = RegNet_X_400MF_Weights.DEFAULT + model = regnet_x_400mf(weights=weights).eval() + pte_filename = "regnet_x_400mf" + + build_executorch_binary( + model, + inputs[0], + args.model, + f"{args.artifact}/{pte_filename}", + inputs, + quant_dtype=QuantDtype.use_8a8w, + ) + + if args.compile_only: + sys.exit(0) + + adb = SimpleADB( + qnn_sdk=os.getenv("QNN_SDK_ROOT"), + build_path=f"{args.build_folder}", + pte_path=f"{args.artifact}/{pte_filename}.pte", + workspace=f"/data/local/tmp/executorch/{pte_filename}", + device_id=args.device, + host_id=args.host, + soc_model=args.model, + ) + adb.push(inputs=inputs, input_list=input_list) + adb.execute() + + # collect output data + output_data_folder = f"{args.artifact}/outputs" + make_output_dir(output_data_folder) + + adb.pull(output_path=args.artifact) + + # top-k analysis + predictions = [] + for i in range(data_num): + predictions.append( + np.fromfile( + os.path.join(output_data_folder, f"output_{i}_0.raw"), dtype=np.float32 + ) + ) + + k_val = [1, 5] + topk = [topk_accuracy(predictions, targets, k).item() for k in k_val] + if args.ip and args.port != -1: + with Client((args.ip, args.port)) as conn: + conn.send(json.dumps({f"top_{k}": topk[i] for i, k in enumerate(k_val)})) + else: + for i, k in enumerate(k_val): + print(f"top_{k}->{topk[i]}%") + + +if __name__ == "__main__": + parser = setup_common_args_and_variables() + parser.add_argument( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. Default ./regnet", + default="./regnet", + type=str, + ) + + parser.add_argument( + "-d", + "--dataset", + help=( + "path to the validation folder of ImageNet dataset. " + "e.g. --dataset imagenet-mini/val " + "for https://www.kaggle.com/datasets/ifigotin/imagenetmini-1000)" + ), + type=str, + required=True, + ) + + parser.add_argument( + "--weights", + type=str, + choices=["regnet_y_400mf", "regnet_x_400mf"], + help="Specify which regent weights/model to execute", + required=True, + ) + + args = parser.parse_args() + try: + main(args) + except Exception as e: + if args.ip and args.port != -1: + with Client((args.ip, args.port)) as conn: + conn.send(json.dumps({"Error": str(e)})) + else: + raise Exception(e) diff --git a/examples/qualcomm/oss_scripts/squeezenet.py b/examples/qualcomm/oss_scripts/squeezenet.py index 820f23d119..64b317068c 100644 --- a/examples/qualcomm/oss_scripts/squeezenet.py +++ b/examples/qualcomm/oss_scripts/squeezenet.py @@ -92,12 +92,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/oss_scripts/ssd300_vgg16.py b/examples/qualcomm/oss_scripts/ssd300_vgg16.py index 45e3073bae..a5db138233 100644 --- a/examples/qualcomm/oss_scripts/ssd300_vgg16.py +++ b/examples/qualcomm/oss_scripts/ssd300_vgg16.py @@ -155,12 +155,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/deeplab_v3.py b/examples/qualcomm/scripts/deeplab_v3.py index 8d1aa376e7..34a94c8a76 100755 --- a/examples/qualcomm/scripts/deeplab_v3.py +++ b/examples/qualcomm/scripts/deeplab_v3.py @@ -95,12 +95,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/edsr.py b/examples/qualcomm/scripts/edsr.py index c5e3f8b010..8852cf0e4c 100755 --- a/examples/qualcomm/scripts/edsr.py +++ b/examples/qualcomm/scripts/edsr.py @@ -126,12 +126,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/inception_v3.py b/examples/qualcomm/scripts/inception_v3.py index 50361938e8..82b290d253 100755 --- a/examples/qualcomm/scripts/inception_v3.py +++ b/examples/qualcomm/scripts/inception_v3.py @@ -92,12 +92,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/inception_v4.py b/examples/qualcomm/scripts/inception_v4.py index cd4dcb7cd9..e7f2fea1cd 100755 --- a/examples/qualcomm/scripts/inception_v4.py +++ b/examples/qualcomm/scripts/inception_v4.py @@ -91,12 +91,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/mobilebert_fine_tune.py b/examples/qualcomm/scripts/mobilebert_fine_tune.py index 94f528dbc3..278ab8e8c0 100755 --- a/examples/qualcomm/scripts/mobilebert_fine_tune.py +++ b/examples/qualcomm/scripts/mobilebert_fine_tune.py @@ -268,12 +268,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/mobilenet_v2.py b/examples/qualcomm/scripts/mobilenet_v2.py index 8a3032df02..7cc0226e25 100755 --- a/examples/qualcomm/scripts/mobilenet_v2.py +++ b/examples/qualcomm/scripts/mobilenet_v2.py @@ -92,12 +92,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/mobilenet_v3.py b/examples/qualcomm/scripts/mobilenet_v3.py index d0cd7bb4df..08c6590463 100644 --- a/examples/qualcomm/scripts/mobilenet_v3.py +++ b/examples/qualcomm/scripts/mobilenet_v3.py @@ -90,12 +90,6 @@ def main(args): if args.compile_only: sys.exit(0) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}", diff --git a/examples/qualcomm/scripts/torchvision_vit.py b/examples/qualcomm/scripts/torchvision_vit.py index 85852ebb2f..dc9459bb13 100755 --- a/examples/qualcomm/scripts/torchvision_vit.py +++ b/examples/qualcomm/scripts/torchvision_vit.py @@ -76,12 +76,7 @@ def main(args): quant_dtype=QuantDtype.use_8a8w, shared_buffer=args.shared_buffer, ) - # setup required paths accordingly - # qnn_sdk : QNN SDK path setup in environment variable - # build_path : path where QNN delegate artifacts were built - # pte_path : path where executorch binary was stored - # device_id : serial number of android device - # workspace : folder for storing artifacts on android device + adb = SimpleADB( qnn_sdk=os.getenv("QNN_SDK_ROOT"), build_path=f"{args.build_folder}",