diff options
Diffstat (limited to 'ethosu/vela/tflite_graph_optimiser.py')
-rw-r--r-- | ethosu/vela/tflite_graph_optimiser.py | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/ethosu/vela/tflite_graph_optimiser.py b/ethosu/vela/tflite_graph_optimiser.py index 2026892e..3a49309d 100644 --- a/ethosu/vela/tflite_graph_optimiser.py +++ b/ethosu/vela/tflite_graph_optimiser.py @@ -1583,16 +1583,42 @@ def fixup_bias_tensors(op, arch, nng, dtype=None): return op -def fixup_asymmetric_weights(op, arch, nng): - if op.run_on_npu and (op.type.is_conv2d_op() or op.type.is_depthwise_conv2d_op()): - if op.ifm.dtype == DataType.int8: +def detect_asymmetric_weights(op): + # Check all ops (cpu and npu) + if op.type.is_conv2d_op() or op.type.is_depthwise_conv2d_op(): + if op.ifm.dtype in (DataType.int8, DataType.int16): if not np.all(op.weights.quantization.zero_point == 0): - print(f"Warning: {op.type} '{op.name}' has asymmetric weights, zero points have been adjusted.") - op.weights.quantization.zero_point *= 0 + print(f"Warning: Op {op.type} '{op.name}' has asymmetric weights.", end=" ") + return True + return False + + +def fixup_asymmetric_weights(op, arch, nng): + if detect_asymmetric_weights(op): + if op.run_on_npu: + print("Zero points have been adjusted.") + op.weights.quantization.zero_point *= 0 + return op + +def check_asymmetric_weights(op, arch, nng): + # This function can modify the run_on_npu flag which causes an operator to be placed on the CPU. It is usually only + # set by the supported operator checks. Therefore, it should be run immediately after those checks to avoid the + # possibility of other graph optimiser functions modify the operator (that is later run on the CPU) + if detect_asymmetric_weights(op): + if op.run_on_npu: + print("To run the operator on Ethos-U use the option --force-symmetric-int-weights") + op.run_on_npu = False return op +def fixup_or_check_asymmetric_weights(force_symmetric_int_weights): + if force_symmetric_int_weights: + return fixup_asymmetric_weights + else: + return check_asymmetric_weights + + def convert_mean_to_depthwise_conv_or_avgpool(op, arch, nng): if op.type == Op.Mean and op.run_on_npu: inp, axis = op.inputs @@ -1871,9 +1897,13 @@ def supported_operator_check(op, arch, nng): return op -def tflite_optimise_graph(nng, arch): +def tflite_optimise_graph(nng, arch, force_symmetric_int_weights): # Compile time static optimisations - optimisation_list = [optimise_quantize, convert_shape_op_to_constant_tensor] + optimisation_list = [ + optimise_quantize, + convert_shape_op_to_constant_tensor, + fixup_or_check_asymmetric_weights(force_symmetric_int_weights), + ] for idx, sg in enumerate(nng.subgraphs): nng.subgraphs[idx] = rewrite_graph.rewrite_graph_pre_order( @@ -1886,10 +1916,7 @@ def tflite_optimise_graph(nng, arch): ) # Pre-processing step - pre_process_list = [ - supported_operator_check, - set_ifm_ofm_op_shapes, - ] + pre_process_list = [supported_operator_check, set_ifm_ofm_op_shapes] for idx, sg in enumerate(nng.subgraphs): nng.subgraphs[idx] = rewrite_graph.rewrite_graph_pre_order( |