From 6bf1613c5894d81849dd12b5be6145c1f24caca2 Mon Sep 17 00:00:00 2001 From: James Ward Date: Wed, 8 Sep 2021 11:14:20 +0100 Subject: MLBEDSW-5162 MLCE: Vela [3.1.0] falling to run with yolov4_int8.tflite * fix indices for tflite mapping of EXP operator * fix indices for tflite mapping of Transpose operator * ensure read offset after slice is aligned to 16 bytes for NHCWB16 or force linear format * add unit test to ensure mapping of indices is consistent across TFLite, TOSA and NNG Signed-off-by: James Ward Change-Id: I17b6e44bc06853325d5eea62a558418ee1ebefe8 --- ethosu/vela/graph_optimiser_util.py | 17 +++++++++------ ethosu/vela/operation.py | 2 +- ethosu/vela/test/test_nng_mapping.py | 41 ++++++++++++++++++++++++++++++++++++ ethosu/vela/tflite_mapping.py | 4 ++-- 4 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 ethosu/vela/test/test_nng_mapping.py diff --git a/ethosu/vela/graph_optimiser_util.py b/ethosu/vela/graph_optimiser_util.py index 73fbf6c7..3e15f126 100644 --- a/ethosu/vela/graph_optimiser_util.py +++ b/ethosu/vela/graph_optimiser_util.py @@ -49,15 +49,18 @@ def _avoid_nhcwb16_for_concat(tens): def _avoid_nhcwb16_for_split(tens): # If read offset is not a multiple of 16 in the C-dimension, NHCWB16 need to be avoided in the input + + # Return True if NHCWB16 needs to be avoided + def offset_not_aligned(read_offset): + return read_offset is not None and (read_offset.depth % 16) != 0 + for cons_op in tens.consumer_list: if cons_op.ifm == tens: - read_offset = cons_op.read_offsets[0] - elif cons_op.type.is_binary_elementwise_op() and cons_op.ifm2 == tens: - read_offset = cons_op.read_offsets[1] - else: - assert False - if read_offset is not None and (read_offset[-1] % 16) != 0: - return True + if offset_not_aligned(cons_op.read_offsets[0]): + return True + if cons_op.ifm2 is not None and cons_op.ifm2 == tens: + if offset_not_aligned(cons_op.read_offsets[1]): + return True return False diff --git a/ethosu/vela/operation.py b/ethosu/vela/operation.py index 1e733d56..1707d318 100644 --- a/ethosu/vela/operation.py +++ b/ethosu/vela/operation.py @@ -285,7 +285,7 @@ class Op(Enum): Tanh = OperatorInfo(indices=NNG_IFM_INDICES) Tile = OperatorInfo() TopKV2 = OperatorInfo() - Transpose = OperatorInfo(indices=NNG_IFM_INDICES) + Transpose = OperatorInfo(indices=NNG_IFM_IFM2_INDICES) UnidirectionalSequenceLstm = OperatorInfo(block_type=NpuBlockType.VectorProduct, indices=NNG_IFM_WEIGHTS_INDICES) UnidirectionalSequenceRnn = OperatorInfo(block_type=NpuBlockType.VectorProduct, indices=NNG_IFM_WEIGHTS_INDICES) Unique = OperatorInfo() diff --git a/ethosu/vela/test/test_nng_mapping.py b/ethosu/vela/test/test_nng_mapping.py new file mode 100644 index 00000000..08d77fea --- /dev/null +++ b/ethosu/vela/test/test_nng_mapping.py @@ -0,0 +1,41 @@ +# Copyright (C) 2021 Arm Limited or its affiliates. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Description: +# Unit tests for the mapping of TFLite or TOSA to NNG +import pytest + +from ethosu.vela.tflite_mapping import builtin_operator_map +from ethosu.vela.tosa_mapping import tosa_operator_map + + +class TestNNGMapping: + """Ensure the mappings from TFLite to NNG are consistent.""" + + @pytest.mark.parametrize( + "operator_map", + ((builtin_operator_map), (tosa_operator_map)), + ids=("test_tflite_indices_match_nng", "test_tosa_indices_match_nng"), + ) + def test_op_indices_match(self, operator_map): + """Ensure TFLite/TOSA indices and NNG indices are consistent for each operator.""" + for map_op in operator_map.values(): + op_type = map_op[0] + map_op_indices = map_op[-1] # TFLite/TOSA indices in last element of tuple + + nng_indices = op_type.info.indices + + for idx in range(3): + assert len(map_op_indices[idx]) == len(nng_indices[idx]) diff --git a/ethosu/vela/tflite_mapping.py b/ethosu/vela/tflite_mapping.py index d52e074a..396ed5ec 100644 --- a/ethosu/vela/tflite_mapping.py +++ b/ethosu/vela/tflite_mapping.py @@ -650,7 +650,7 @@ builtin_operator_map = { OptionsSerializer("SpaceToBatchNDOptions"), TFLITE_NO_INDICES, ), - BuiltinOperator.TRANSPOSE: (Op.Transpose, OptionsSerializer("TransposeOptions"), TFLITE_NO_INDICES), + BuiltinOperator.TRANSPOSE: (Op.Transpose, OptionsSerializer("TransposeOptions"), TFLITE_IFM_IFM2_INDICES), BuiltinOperator.MEAN: (Op.Mean, OptionsSerializer("ReducerOptions", ("keep_dims",)), TFLITE_IFM_INDICES), BuiltinOperator.SUB: ( Op.Sub, @@ -685,7 +685,7 @@ builtin_operator_map = { ), TFLITE_IFM_WEIGHTS_INDICES, ), - BuiltinOperator.EXP: (Op.Exp, OptionsSerializer("ExpOptions"), TFLITE_IFM_INDICES), + BuiltinOperator.EXP: (Op.Exp, OptionsSerializer("ExpOptions"), TFLITE_NO_INDICES), BuiltinOperator.TOPK_V2: (Op.TopKV2, OptionsSerializer("TopKV2Options"), TFLITE_NO_INDICES), BuiltinOperator.SPLIT: (Op.Split, OptionsSerializer("SplitOptions", ("num_splits",)), TFLITE_SPLIT_IFM_INDICES), BuiltinOperator.LOG_SOFTMAX: (Op.LogSoftmax, OptionsSerializer("LogSoftmaxOptions"), TFLITE_NO_INDICES), -- cgit v1.2.1