diff --git a/backends/qualcomm/passes/annotate_quant_attrs.py b/backends/qualcomm/passes/annotate_quant_attrs.py index 199d26b0262..0dc39d2a4de 100644 --- a/backends/qualcomm/passes/annotate_quant_attrs.py +++ b/backends/qualcomm/passes/annotate_quant_attrs.py @@ -94,9 +94,11 @@ def _dequant_fold_params(self, n, quant_attrs, param): def _annotate_quant_attrs( self, graph_module: torch.fx.GraphModule ) -> torch.fx.GraphModule: + # Keep track of const params that has been dequant, so it does not get + # dequant multiple times if the const param has more than 1 user + visited_const_param = set() for n in graph_module.graph.nodes: self._annotate_requant(n) - # With fold_quant enabled, check if the input of dq op is quantized param. param = None if n.target in dq_ops: @@ -106,7 +108,8 @@ def _annotate_quant_attrs( quant_attrs = get_quant_attrs(self.edge_program, n) self._annotate_source_nodes(n, quant_attrs) - if param is not None: + if param is not None and n.args[0] not in visited_const_param: + visited_const_param.add(n.args[0]) self._dequant_fold_params(n, quant_attrs, param) return graph_module diff --git a/backends/qualcomm/passes/recompose_pixel_unshuffle.py b/backends/qualcomm/passes/recompose_pixel_unshuffle.py index cadc310bbb6..a47f3d119a5 100644 --- a/backends/qualcomm/passes/recompose_pixel_unshuffle.py +++ b/backends/qualcomm/passes/recompose_pixel_unshuffle.py @@ -35,7 +35,13 @@ def call(self, graph_module: torch.fx.GraphModule): for node in graph.nodes: if node.op == "call_function" and node.target == self.reshape_target: with graph.inserting_after(node): - premute_node = node.args[0] + + # Clone op still exists between permute and reshape_target during quantization, + # so we need to check for args[0].args[0] to get permute node + if self.quantization_capture: + premute_node = node.args[0].args[0] + else: + premute_node = node.args[0] if any( [ len(node.args[1]) != 4, diff --git a/backends/qualcomm/quantizer/quantizer.py b/backends/qualcomm/quantizer/quantizer.py index 91e31b62e4d..d51e016473f 100644 --- a/backends/qualcomm/quantizer/quantizer.py +++ b/backends/qualcomm/quantizer/quantizer.py @@ -12,7 +12,6 @@ RecomposePixelUnshuffle, ) from executorch.backends.qualcomm.passes.reduce_dynamic_range import ReduceDynamicRange -from executorch.backends.qualcomm.passes.remove_redundancy import RemoveRedundancy from executorch.backends.qualcomm.passes.replace_inf_buffer import ReplaceInfBuffer from executorch.backends.transforms.decompose_sdpa import ( DecomposeScaledDotProductAttention, @@ -182,7 +181,6 @@ def set_per_channel_linear_quant(self, enable: bool) -> None: self._update_per_channel_weight_quant_ops(linear_ops, enable) def transform_for_annotation(self, model: GraphModule) -> GraphModule: - model = RemoveRedundancy()(model).graph_module model = ReduceDynamicRange()(model).graph_module model = RecomposePixelUnshuffle(quantization_capture=True)(model).graph_module model = DecomposeScaledDotProductAttention()(model).graph_module diff --git a/backends/qualcomm/tests/test_qnn_delegate.py b/backends/qualcomm/tests/test_qnn_delegate.py index 508a027da68..f9d05131bb1 100644 --- a/backends/qualcomm/tests/test_qnn_delegate.py +++ b/backends/qualcomm/tests/test_qnn_delegate.py @@ -1581,8 +1581,11 @@ def test_fbnet(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 60) - self.assertGreaterEqual(msg["top_5"], 90) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 90) def test_gMLP(self): if not self.required_envs([self.image_dataset]): @@ -1614,8 +1617,11 @@ def test_gMLP(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 60) - self.assertGreaterEqual(msg["top_5"], 90) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 90) def test_ssd300_vgg16(self): if not self.required_envs([self.pretrained_weight, self.oss_repo]): @@ -1649,7 +1655,10 @@ def test_ssd300_vgg16(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["mAP"], 0.70) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["mAP"], 0.70) def test_dino_v2(self): if not self.required_envs([self.image_dataset]): @@ -1680,8 +1689,11 @@ def test_dino_v2(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 70) - self.assertGreaterEqual(msg["top_5"], 85) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 70) + self.assertGreaterEqual(msg["top_5"], 85) def test_esrgan(self): if not self.required_envs(): @@ -1714,8 +1726,11 @@ def test_esrgan(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["PSNR"], 24) - self.assertGreaterEqual(msg["SSIM"], 0.8) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["PSNR"], 24) + self.assertGreaterEqual(msg["SSIM"], 0.8) def test_squeezenet(self): if not self.required_envs([self.image_dataset]): @@ -1747,8 +1762,11 @@ def test_squeezenet(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 40) - self.assertGreaterEqual(msg["top_5"], 70) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 40) + self.assertGreaterEqual(msg["top_5"], 70) class TestExampleScript(TestQNN): @@ -1794,8 +1812,11 @@ def test_mobilenet_v2(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 60) - self.assertGreaterEqual(msg["top_5"], 80) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 80) def test_mobilenet_v3(self): if not self.required_envs([self.image_dataset]): @@ -1829,8 +1850,11 @@ def test_mobilenet_v3(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 60) - self.assertGreaterEqual(msg["top_5"], 80) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 80) def test_inception_v3(self): if not self.required_envs([self.image_dataset]): @@ -1864,8 +1888,11 @@ def test_inception_v3(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 60) - self.assertGreaterEqual(msg["top_5"], 80) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 80) def test_inception_v4(self): if not self.required_envs([self.image_dataset]): @@ -1899,8 +1926,11 @@ def test_inception_v4(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 60) - self.assertGreaterEqual(msg["top_5"], 80) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 60) + self.assertGreaterEqual(msg["top_5"], 80) def test_vit(self): if not self.required_envs([self.image_dataset]): @@ -1934,8 +1964,11 @@ def test_vit(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["top_1"], 70) - self.assertGreaterEqual(msg["top_5"], 90) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["top_1"], 70) + self.assertGreaterEqual(msg["top_5"], 90) def test_edsr(self): if not self.required_envs(): @@ -1968,8 +2001,11 @@ def test_edsr(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["PSNR"], 25) - self.assertGreaterEqual(msg["SSIM"], 0.8) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["PSNR"], 25) + self.assertGreaterEqual(msg["SSIM"], 0.8) def test_deeplab_v3(self): if not self.required_envs(): @@ -2002,9 +2038,12 @@ def test_deeplab_v3(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - self.assertGreaterEqual(msg["PA"], 0.85) - self.assertGreaterEqual(msg["MPA"], 0.70) - self.assertGreaterEqual(msg["MIoU"], 0.55) + if "Error" in msg: + self.fail(msg["Error"]) + else: + self.assertGreaterEqual(msg["PA"], 0.85) + self.assertGreaterEqual(msg["MPA"], 0.70) + self.assertGreaterEqual(msg["MIoU"], 0.55) def test_stories_single_llama(self): if not self.required_envs(): @@ -2049,8 +2088,11 @@ def test_stories_single_llama(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - model_out = msg["result"][0] - self.assertTrue(model_out.startswith(golden_start_with)) + if "Error" in msg: + self.fail(msg["Error"]) + else: + model_out = msg["result"][0] + self.assertTrue(model_out.startswith(golden_start_with)) def test_mobilebert(self): if not self.required_envs([self.pretrained_weight]): @@ -2085,9 +2127,12 @@ def test_mobilebert(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - cpu, htp = msg["CPU"], msg["HTP"] - for k, v in cpu.items(): - self.assertLessEqual(abs(v[0] - htp[k][0]), 2) + if "Error" in msg: + self.fail(msg["Error"]) + else: + cpu, htp = msg["CPU"], msg["HTP"] + for k, v in cpu.items(): + self.assertLessEqual(abs(v[0] - htp[k][0]), 2) @unittest.skip("will be enabled after TODOs got resolved") def test_ptq_mobilebert(self): @@ -2127,9 +2172,12 @@ def test_ptq_mobilebert(self): conn = listener.accept() p.communicate() msg = json.loads(conn.recv()) - cpu, htp = msg["CPU"], msg["HTP"] - for k, v in cpu.items(): - self.assertLessEqual(abs(v[0] - htp[k][0]), 5) + if "Error" in msg: + self.fail(msg["Error"]) + else: + cpu, htp = msg["CPU"], msg["HTP"] + for k, v in cpu.items(): + self.assertLessEqual(abs(v[0] - htp[k][0]), 5) def test_export_example(self): if not self.required_envs([self.model_name]): diff --git a/examples/qualcomm/llama2/llama.py b/examples/qualcomm/llama2/llama.py index 79cf5606d6c..6e0f3f43999 100644 --- a/examples/qualcomm/llama2/llama.py +++ b/examples/qualcomm/llama2/llama.py @@ -586,4 +586,11 @@ def post_process(): if args.compile_only: exit(f"Finish compile_only and save to {args.artifact}") - inference(args) + try: + inference(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/dino_v2.py b/examples/qualcomm/oss_scripts/dino_v2.py index e4d4c6af252..03249b63d8e 100644 --- a/examples/qualcomm/oss_scripts/dino_v2.py +++ b/examples/qualcomm/oss_scripts/dino_v2.py @@ -67,31 +67,7 @@ def get_instance(): return model.eval() -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="Path for storing generated artifacts by this example. Default ./dino_v2", - default="./dino_v2", - 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, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -170,3 +146,37 @@ def get_instance(): 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 ./dino_v2", + default="./dino_v2", + 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, + ) + + 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/esrgan.py b/examples/qualcomm/oss_scripts/esrgan.py index 50dc59cf0cc..e4e609e1527 100644 --- a/examples/qualcomm/oss_scripts/esrgan.py +++ b/examples/qualcomm/oss_scripts/esrgan.py @@ -40,50 +40,7 @@ def get_instance(repo: str): return model.model.eval() -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./esrgan", - default="./esrgan", - type=str, - ) - - parser.add_argument( - "-r", - "--hr_ref_dir", - help="Path to the high resolution images", - default="", - type=str, - ) - - parser.add_argument( - "-l", - "--lr_dir", - help="Path to the low resolution image inputs", - default="", - type=str, - ) - - parser.add_argument( - "-d", - "--default_dataset", - help="If specified, download and use B100 dataset by torchSR API", - action="store_true", - default=False, - ) - - parser.add_argument( - "--oss_repo", - help="Path to cloned https://github.com/ai-forever/Real-ESRGAN", - type=str, - required=True, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -174,3 +131,56 @@ def post_process(): else: print(f"Average of PSNR is: {avg_PSNR}") print(f"Average of SSIM is: {avg_SSIM}") + + +if __name__ == "__main__": + parser = setup_common_args_and_variables() + + parser.add_argument( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. Default ./esrgan", + default="./esrgan", + type=str, + ) + + parser.add_argument( + "-r", + "--hr_ref_dir", + help="Path to the high resolution images", + default="", + type=str, + ) + + parser.add_argument( + "-l", + "--lr_dir", + help="Path to the low resolution image inputs", + default="", + type=str, + ) + + parser.add_argument( + "-d", + "--default_dataset", + help="If specified, download and use B100 dataset by torchSR API", + action="store_true", + default=False, + ) + + parser.add_argument( + "--oss_repo", + help="Path to cloned https://github.com/ai-forever/Real-ESRGAN", + type=str, + 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/fbnet.py b/examples/qualcomm/oss_scripts/fbnet.py index d62c4a78b15..fe07ab83d2a 100755 --- a/examples/qualcomm/oss_scripts/fbnet.py +++ b/examples/qualcomm/oss_scripts/fbnet.py @@ -23,30 +23,7 @@ ) -if __name__ == "__main__": - parser = setup_common_args_and_variables() - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./fbnet", - default="./fbnet", - 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, - ) - - args = parser.parse_args() - +def main(args): if not args.compile_only and args.device is None: raise RuntimeError( "device serial is required if not compile only. " @@ -126,3 +103,36 @@ def post_process(): 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 ./fbnet", + default="./fbnet", + 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, + ) + + 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/gMLP_image_classification.py b/examples/qualcomm/oss_scripts/gMLP_image_classification.py index 3d98f55a7da..e9b9b915071 100644 --- a/examples/qualcomm/oss_scripts/gMLP_image_classification.py +++ b/examples/qualcomm/oss_scripts/gMLP_image_classification.py @@ -59,30 +59,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./gMLP_image_classification", - default="./gMLP_image_classification", - 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, - ) - - args = parser.parse_args() +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -161,3 +138,37 @@ def get_data_loader(): 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 ./gMLP_image_classification", + default="./gMLP_image_classification", + 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, + ) + + 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 53edb98b91b..bc000c6938a 100644 --- a/examples/qualcomm/oss_scripts/squeezenet.py +++ b/examples/qualcomm/oss_scripts/squeezenet.py @@ -57,32 +57,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - 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( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. " - "Default ./squeezenet", - default="./squeezenet", - type=str, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -158,3 +133,38 @@ def get_data_loader(): 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( + "-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( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. " + "Default ./squeezenet", + default="./squeezenet", + type=str, + ) + + 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/ssd300_vgg16.py b/examples/qualcomm/oss_scripts/ssd300_vgg16.py index cd4eb8764f0..8fdb896e09c 100644 --- a/examples/qualcomm/oss_scripts/ssd300_vgg16.py +++ b/examples/qualcomm/oss_scripts/ssd300_vgg16.py @@ -119,50 +119,7 @@ def SSD300VGG16(pretrained_weight_model): return model.eval() -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./ssd300_vgg16", - default="./ssd300_vgg16", - type=str, - ) - - parser.add_argument( - "-d", - "--download", - help="If specified, download VOCSegmentation dataset by torchvision API", - action="store_true", - default=False, - ) - - parser.add_argument( - "--oss_repo", - help=( - "Repository that contains model backbone and score calculation." - "e.g., --M ./a-PyTorch-Tutorial-to-Object-Detection" - "Please clone the repository from https://github.com/sgrvinod/a-PyTorch-Tutorial-to-Object-Detection" - ), - type=str, - required=True, - ) - - parser.add_argument( - "-p", - "--pretrained_weight", - help=( - "Location of model pretrained weight." - "e.g., -p ./checkpoint_ssd300.pth.tar" - "Pretrained model can be found in the link https://github.com/sgrvinod/a-PyTorch-Tutorial-to-Object-Detection, under the Training Section" - ), - type=str, - required=True, - ) - - args = parser.parse_args() - +def main(args): sys.path.insert(0, args.oss_repo) skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) @@ -279,3 +236,56 @@ def post_process(): pp.pprint(APs) adb.pull(output_path=args.artifact, callback=post_process) + + +if __name__ == "__main__": + parser = setup_common_args_and_variables() + + parser.add_argument( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. Default ./ssd300_vgg16", + default="./ssd300_vgg16", + type=str, + ) + + parser.add_argument( + "-d", + "--download", + help="If specified, download VOCSegmentation dataset by torchvision API", + action="store_true", + default=False, + ) + + parser.add_argument( + "--oss_repo", + help=( + "Repository that contains model backbone and score calculation." + "e.g., --M ./a-PyTorch-Tutorial-to-Object-Detection" + "Please clone the repository from https://github.com/sgrvinod/a-PyTorch-Tutorial-to-Object-Detection" + ), + type=str, + required=True, + ) + + parser.add_argument( + "-p", + "--pretrained_weight", + help=( + "Location of model pretrained weight." + "e.g., -p ./checkpoint_ssd300.pth.tar" + "Pretrained model can be found in the link https://github.com/sgrvinod/a-PyTorch-Tutorial-to-Object-Detection, under the Training Section" + ), + type=str, + 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/scripts/deeplab_v3.py b/examples/qualcomm/scripts/deeplab_v3.py index ff1f53c1807..d870380e353 100755 --- a/examples/qualcomm/scripts/deeplab_v3.py +++ b/examples/qualcomm/scripts/deeplab_v3.py @@ -61,27 +61,7 @@ def get_dataset(data_size, dataset_dir, download): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./deeplab_v3", - default="./deeplab_v3", - type=str, - ) - - parser.add_argument( - "-d", - "--download", - help="If specified, download VOCSegmentation dataset by torchvision API", - action="store_true", - default=False, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -196,3 +176,33 @@ def post_process(): print(f"MPA : {mpa}%") print(f"MIoU : {miou}%") print(f"CIoU : \n{json.dumps(cls_iou, indent=2)}") + + +if __name__ == "__main__": + parser = setup_common_args_and_variables() + + parser.add_argument( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. Default ./deeplab_v3", + default="./deeplab_v3", + type=str, + ) + + parser.add_argument( + "-d", + "--download", + help="If specified, download VOCSegmentation dataset by torchvision API", + action="store_true", + default=False, + ) + + 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/scripts/edsr.py b/examples/qualcomm/scripts/edsr.py index 54cc8bff196..f602ecc1afc 100755 --- a/examples/qualcomm/scripts/edsr.py +++ b/examples/qualcomm/scripts/edsr.py @@ -91,43 +91,7 @@ def get_dataset(hr_dir: str, lr_dir: str, default_dataset: str, dataset_dir: str return SrDataset(hr_dir, lr_dir) -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./edsr", - default="./edsr", - type=str, - ) - - parser.add_argument( - "-r", - "--hr_ref_dir", - help="Path to the high resolution images", - default="", - type=str, - ) - - parser.add_argument( - "-l", - "--lr_dir", - help="Path to the low resolution image inputs", - default="", - type=str, - ) - - parser.add_argument( - "-d", - "--default_dataset", - help="If specified, download and use B100 dataset by torchSR API", - action="store_true", - default=False, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -223,3 +187,49 @@ def post_process(): else: print(f"Average of PNSR is: {avg_PSNR}") print(f"Average of SSIM is: {avg_SSIM}") + + +if __name__ == "__main__": + parser = setup_common_args_and_variables() + + parser.add_argument( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. Default ./edsr", + default="./edsr", + type=str, + ) + + parser.add_argument( + "-r", + "--hr_ref_dir", + help="Path to the high resolution images", + default="", + type=str, + ) + + parser.add_argument( + "-l", + "--lr_dir", + help="Path to the low resolution image inputs", + default="", + type=str, + ) + + parser.add_argument( + "-d", + "--default_dataset", + help="If specified, download and use B100 dataset by torchSR API", + action="store_true", + default=False, + ) + + 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/scripts/inception_v3.py b/examples/qualcomm/scripts/inception_v3.py index 94aa618c720..90eb8cf2060 100755 --- a/examples/qualcomm/scripts/inception_v3.py +++ b/examples/qualcomm/scripts/inception_v3.py @@ -58,32 +58,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - 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( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. " - "Default ./inception_v3", - default="./inception_v3", - type=str, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -159,3 +134,38 @@ def get_data_loader(): 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( + "-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( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. " + "Default ./inception_v3", + default="./inception_v3", + type=str, + ) + + 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/scripts/inception_v4.py b/examples/qualcomm/scripts/inception_v4.py index e457fef0f7c..84b20e6e203 100755 --- a/examples/qualcomm/scripts/inception_v4.py +++ b/examples/qualcomm/scripts/inception_v4.py @@ -57,32 +57,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - 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( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. " - "Default ./inception_v4", - default="./inception_v4", - type=str, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -158,3 +133,38 @@ def get_data_loader(): 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( + "-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( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. " + "Default ./inception_v4", + default="./inception_v4", + type=str, + ) + + 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/scripts/mobilebert_fine_tune.py b/examples/qualcomm/scripts/mobilebert_fine_tune.py index 85aafe7cae7..8972ca202f8 100755 --- a/examples/qualcomm/scripts/mobilebert_fine_tune.py +++ b/examples/qualcomm/scripts/mobilebert_fine_tune.py @@ -220,42 +220,7 @@ def get_fine_tuned_mobilebert(artifacts_dir, pretrained_weight, batch_size): return model.eval(), dataloader_val, labels -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - parser.add_argument( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. Default ./mobilebert_fine_tune", - default="./mobilebert_fine_tune", - type=str, - ) - - parser.add_argument( - "-p", - "--pretrained_weight", - help="Location of pretrained weight", - default=None, - type=str, - ) - - parser.add_argument( - "-F", - "--use_fp16", - help="If specified, will run in fp16 precision and discard ptq setting", - action="store_true", - default=False, - ) - - parser.add_argument( - "-P", - "--ptq", - help="If specified, will do PTQ quantization. default is 8bits activation and 8bits weight. Support 8a8w, 16a16w and 16a4w.", - default="8a8w", - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -353,3 +318,48 @@ def get_fine_tuned_mobilebert(artifacts_dir, pretrained_weight, batch_size): print(f"\n[{target[0]}]") for k, v in target[1].items(): print(f"{k}: {v[0]}/{v[1]}") + + +if __name__ == "__main__": + parser = setup_common_args_and_variables() + + parser.add_argument( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. Default ./mobilebert_fine_tune", + default="./mobilebert_fine_tune", + type=str, + ) + + parser.add_argument( + "-p", + "--pretrained_weight", + help="Location of pretrained weight", + default=None, + type=str, + ) + + parser.add_argument( + "-F", + "--use_fp16", + help="If specified, will run in fp16 precision and discard ptq setting", + action="store_true", + default=False, + ) + + parser.add_argument( + "-P", + "--ptq", + help="If specified, will do PTQ quantization. default is 8bits activation and 8bits weight. Support 8a8w, 16a16w and 16a4w.", + default="8a8w", + ) + + 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/scripts/mobilenet_v2.py b/examples/qualcomm/scripts/mobilenet_v2.py index f642e0172c1..3ebdcd5d05f 100755 --- a/examples/qualcomm/scripts/mobilenet_v2.py +++ b/examples/qualcomm/scripts/mobilenet_v2.py @@ -58,32 +58,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - 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( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. " - "Default ./mobilenet_v2", - default="./mobilenet_v2", - type=str, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -159,3 +134,38 @@ def get_data_loader(): 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( + "-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( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. " + "Default ./mobilenet_v2", + default="./mobilenet_v2", + type=str, + ) + + 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/scripts/mobilenet_v3.py b/examples/qualcomm/scripts/mobilenet_v3.py index d15827160a8..18fd7c849a6 100644 --- a/examples/qualcomm/scripts/mobilenet_v3.py +++ b/examples/qualcomm/scripts/mobilenet_v3.py @@ -57,32 +57,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - - 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( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. " - "Default ./mobilenet_v3", - default="./mobilenet_v3", - type=str, - ) - - args = parser.parse_args() - +def main(args): skip_node_id_set, skip_node_op_set = parse_skip_delegation_node(args) # ensure the working directory exist. @@ -157,3 +132,38 @@ def get_data_loader(): 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( + "-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( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. " + "Default ./mobilenet_v3", + default="./mobilenet_v3", + type=str, + ) + + 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/scripts/torchvision_vit.py b/examples/qualcomm/scripts/torchvision_vit.py index cd5463c8a2a..cfdbe5d0759 100755 --- a/examples/qualcomm/scripts/torchvision_vit.py +++ b/examples/qualcomm/scripts/torchvision_vit.py @@ -56,29 +56,7 @@ def get_data_loader(): return inputs, targets, input_list -if __name__ == "__main__": - parser = setup_common_args_and_variables() - 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( - "-a", - "--artifact", - help="path for storing generated artifacts by this example. " "Default ./vit", - default="./vit", - type=str, - ) - - args = parser.parse_args() - +def main(args): # ensure the working directory exist. os.makedirs(args.artifact, exist_ok=True) @@ -140,3 +118,35 @@ def get_data_loader(): 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( + "-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( + "-a", + "--artifact", + help="path for storing generated artifacts by this example. " "Default ./vit", + default="./vit", + type=str, + ) + + 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/scripts/utils.py b/examples/qualcomm/scripts/utils.py index d803932179c..1e4b1c69685 100755 --- a/examples/qualcomm/scripts/utils.py +++ b/examples/qualcomm/scripts/utils.py @@ -187,6 +187,7 @@ def build_executorch_binary( quantizer = QnnQuantizer() quantizer.add_custom_quant_annotations(custom_annotations) quantizer.set_per_channel_linear_quant(per_channel_linear) + quantizer.set_per_channel_conv_quant(True) if quant_dtype == QuantDtype.use_8a8w: pass # default setting @@ -214,7 +215,6 @@ def build_executorch_binary( for data in dataset: annotated_model(*data) quantized_model = convert_pt2e(annotated_model) - edge_prog = capture_program(quantized_model, inputs) else: edge_prog = capture_program(model, inputs)