From 487d390b94ee93e1d89f5066ef8ca9442ab0a590 Mon Sep 17 00:00:00 2001 From: Freddie Liardet Date: Tue, 21 Sep 2021 12:36:43 +0100 Subject: Add user provided JSON operator list build Allow ACL to be built via a user provided JSON file containing operators, data types and data layouts. Modify TFLite file to JSON file script to output data layouts. Fix build issue with "fat_binary" and "high_priority" options. Resolves: COMPMID-4697, COMPMID-4837 Signed-off-by: Freddie Liardet Change-Id: I08d494151c98f804325707ffd922ffe216813023 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/6427 Comments-Addressed: Arm Jenkins Tested-by: Arm Jenkins Reviewed-by: Gunes Bayir --- .../scripts/report-model-ops/report_model_ops.py | 63 ++++++++++++++-------- python/scripts/utils/model_identification.py | 4 +- python/scripts/utils/tflite_helpers.py | 44 +++++++++++++-- 3 files changed, 82 insertions(+), 29 deletions(-) mode change 100644 => 100755 python/scripts/report-model-ops/report_model_ops.py (limited to 'python') diff --git a/python/scripts/report-model-ops/report_model_ops.py b/python/scripts/report-model-ops/report_model_ops.py old mode 100644 new mode 100755 index 3888b801e6..1549005da5 --- a/python/scripts/report-model-ops/report_model_ops.py +++ b/python/scripts/report-model-ops/report_model_ops.py @@ -31,20 +31,20 @@ import tflite sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../") from utils.model_identification import identify_model_type -from utils.tflite_helpers import tflite_op2acl, tflite_typecode2name +from utils.tflite_helpers import tflite_op2acl, tflite_typecode2name, tflite_typecode2aclname SUPPORTED_MODEL_TYPES = ["tflite"] logger = logging.getLogger("report_model_ops") -def get_ops_from_tflite_graph(model): +def get_ops_types_from_tflite_graph(model): """ - Helper function that extract operator related meta-data from a TfLite model + Helper function that extract operator related meta-data from a TFLite model Parameters ---------- model: str - Respective TfLite model to analyse + Respective TFLite model to analyse Returns ---------- @@ -52,7 +52,7 @@ def get_ops_from_tflite_graph(model): A tuple with the sets of unique operator types and data-types that are present in the model """ - logger.debug(f"Analysing TfLite mode '{model}'!") + logger.debug(f"Analysing TFLite mode '{model}'!") with open(model, "rb") as f: buf = f.read() @@ -63,11 +63,16 @@ def get_ops_from_tflite_graph(model): unique_ops = {tflite.opcode2name(model.OperatorCodes(op_id).BuiltinCode()) for op_id in range(0, nr_unique_ops)} # Extract IO data-types - data_types = set() + supported_data_types = set() + unsupported_data_types = set() for subgraph_id in range(0, model.SubgraphsLength()): subgraph = model.Subgraphs(subgraph_id) for tensor_id in range(0, subgraph.TensorsLength()): - data_types.add(tflite_typecode2name(subgraph.Tensors(tensor_id).Type())) + try: + supported_data_types.add(tflite_typecode2aclname(subgraph.Tensors(tensor_id).Type())) + except ValueError: + unsupported_data_types.add(tflite_typecode2name(subgraph.Tensors(tensor_id).Type())) + logger.warning(f"Data type {tflite_typecode2name(subgraph.Tensors(tensor_id).Type())} is not supported by ComputeLibrary") # Perform mapping between TfLite ops to ComputeLibrary ones supported_ops = set() @@ -75,17 +80,17 @@ def get_ops_from_tflite_graph(model): for top in unique_ops: try: supported_ops.add(tflite_op2acl(top)) - except: + except ValueError: unsupported_ops.add(top) - logger.warning(f"Operator {top} has not ComputeLibrary mapping") + logger.warning(f"Operator {top} does not have ComputeLibrary mapping") - return (supported_ops, unsupported_ops, data_types) + return (supported_ops, unsupported_ops, supported_data_types, unsupported_data_types) def extract_model_meta(model, model_type): """ Function that calls the appropriate model parser to extract model related meta-data - Supported parsers: TfLite + Supported parsers: TFLite Parameters ---------- @@ -101,13 +106,13 @@ def extract_model_meta(model, model_type): """ if model_type == "tflite": - return get_ops_from_tflite_graph(model) + return get_ops_types_from_tflite_graph(model) else: logger.warning(f"Model type '{model_type}' is unsupported!") return () -def generate_build_config(ops, data_types): +def generate_build_config(ops, data_types, data_layouts): """ Function that generates a compatible ComputeLibrary operator-based build configuration @@ -117,6 +122,8 @@ def generate_build_config(ops, data_types): Set with the operators to add in the build configuration data_types: Set with the data types to add in the build configuration + data_layouts: + Set with the data layouts to add in the build configuration Returns ---------- @@ -126,6 +133,7 @@ def generate_build_config(ops, data_types): config_data = {} config_data["operators"] = list(ops) config_data["data_types"] = list(data_types) + config_data["data_layouts"] = list(data_layouts) return config_data @@ -134,7 +142,7 @@ if __name__ == "__main__": parser = ArgumentParser( description="""Report map of operations in a list of models. The script consumes deep learning models and reports the type of operations and data-types used - Supported model types: TfLite """ + Supported model types: TFLite """ ) parser.add_argument( @@ -163,26 +171,35 @@ if __name__ == "__main__": # Extract operator mapping final_supported_ops = set() final_unsupported_ops = set() - final_dts = set() + final_supported_dts = set() + final_unsupported_dts = set() + final_layouts = {"nhwc"} # Data layout for TFLite is always NHWC for model in args.models: logger.debug(f"Starting analyzing {model} model") model_type = identify_model_type(model) - supported_model_ops, unsupported_mode_ops, model_dts = extract_model_meta(model, model_type) + supported_model_ops, unsupported_mode_ops, supported_model_dts, unsupported_model_dts = extract_model_meta(model, model_type) final_supported_ops.update(supported_model_ops) final_unsupported_ops.update(unsupported_mode_ops) - final_dts.update(model_dts) + final_supported_dts.update(supported_model_dts) + final_unsupported_dts.update(unsupported_model_dts) logger.info("=== Supported Operators") logger.info(final_supported_ops) - logger.info("=== Unsupported Operators") - logger.info(final_unsupported_ops) + if(len(final_unsupported_ops)): + logger.info("=== Unsupported Operators") + logger.info(final_unsupported_ops) logger.info("=== Data Types") - logger.info(final_dts) - - # Generate json file + logger.info(final_supported_dts) + if(len(final_unsupported_dts)): + logger.info("=== Unsupported Data Types") + logger.info(final_unsupported_dts) + logger.info("=== Data Layouts") + logger.info(final_layouts) + + # Generate JSON file if args.config: logger.debug("Generating JSON build configuration file") - config_data = generate_build_config(final_supported_ops, final_dts) + config_data = generate_build_config(final_supported_ops, final_supported_dts, final_layouts) with open(args.config, "w") as f: json.dump(config_data, f) diff --git a/python/scripts/utils/model_identification.py b/python/scripts/utils/model_identification.py index 43e7d20f61..84a6e1a097 100644 --- a/python/scripts/utils/model_identification.py +++ b/python/scripts/utils/model_identification.py @@ -24,7 +24,7 @@ import os def is_tflite_model(model_path): - """Check if a model is of TfLite type + """Check if a model is of TFLite type Parameters: ---------- @@ -34,7 +34,7 @@ def is_tflite_model(model_path): Returns ---------- bool: - True if given path is a valid TfLite model + True if given path is a valid TFLite model """ try: diff --git a/python/scripts/utils/tflite_helpers.py b/python/scripts/utils/tflite_helpers.py index 8f8d422743..c2aeaac6a7 100644 --- a/python/scripts/utils/tflite_helpers.py +++ b/python/scripts/utils/tflite_helpers.py @@ -20,6 +20,19 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +_TFLITE_TYPECODE2ACLNAME = { + 0: "fp32", # Float32 + 1: "fp16", # Float16 + 2: "integer", # Int32 + 3: "qasymm8", # Uint8 + # 4: "Unsupported", # Int64 + # 5: "Unsupported", # String + 6: "integer", # Bool + 7: "qsymm16", # Int16 + # 8: "Unsupported", # Complex64 + 9: "qasymm8_signed", # Int8 +} + _TFLITE_TYPECODE2NAME = { 0: "Float32", 1: "Float16", @@ -182,13 +195,36 @@ _TFLITE_TO_ACL = { } +def tflite_typecode2aclname(toc): + """Stringify TFLite data-type opcodes to ACL versions + + Parameters: + ---------- + toc: int + TFLite type opcode + + Returns + ---------- + str + Stringified opcode + + Raises + ------ + ValueError + If opcode does not exist in the map + """ + if toc in _TFLITE_TYPECODE2ACLNAME: + return _TFLITE_TYPECODE2ACLNAME[toc] + else: + raise ValueError("Unknown ACL typecode %d" % toc) + def tflite_typecode2name(toc): - """Stringify TfLite data-type opcodes + """Stringify TFLite data-type opcodes Parameters: ---------- toc: int - TfLite type opcode + TFLite type opcode Returns ---------- @@ -207,12 +243,12 @@ def tflite_typecode2name(toc): def tflite_op2acl(top): - """Map TfLite operators to ComputeLibrary ones + """Map TFLite operators to ComputeLibrary ones Parameters: ---------- top: str - TfLite operator name + TFLite operator name Returns ---------- -- cgit v1.2.1