aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFredrik Svedberg <fredrik.svedberg@arm.com>2022-07-06 14:54:12 +0200
committerFredrik Svedberg <fredrik.svedberg@arm.com>2022-07-15 13:20:47 +0000
commit1156317a8a8df1bc0c25a54db8475d84495f1a79 (patch)
treea34f60c1d874bcac6e65052e39fca1608f3b72fb
parent93f492bae9c4dd16a1f64b851b237263695ee03e (diff)
downloadethos-u-vela-1156317a8a8df1bc0c25a54db8475d84495f1a79.tar.gz
MLBEDSW-6703 Add SHAPE operator to supported operators
Added SHAPE operator to the supported operators report. Updated the constraints for QUANTIZE and SHAPE operator. Also fixed RESHAPE consuming statically optimised shape. Signed-off-by: Fredrik Svedberg <fredrik.svedberg@arm.com> Change-Id: I1d964d602d3f361a0f16dae8133197280dd84c48
-rw-r--r--SUPPORTED_OPS.md11
-rw-r--r--ethosu/vela/operation.py13
-rw-r--r--ethosu/vela/tflite_graph_optimiser.py8
-rw-r--r--ethosu/vela/tflite_model_semantic.py11
-rw-r--r--ethosu/vela/tflite_supported_operators.py10
5 files changed, 34 insertions, 19 deletions
diff --git a/SUPPORTED_OPS.md b/SUPPORTED_OPS.md
index 83429b7a..d16d5f8e 100644
--- a/SUPPORTED_OPS.md
+++ b/SUPPORTED_OPS.md
@@ -1,7 +1,7 @@
# Supported Ops
This file was automatically generated by Vela using the `--supported-ops-report` parameter.
-Vela version: `3.4.0rc3.dev1+g5e0ae55`
+Vela version: `3.4.1.dev3+g5c30971e`
This file complies with
[**Gitiles Markdown syntax**](https://github.com/google/gitiles/blob/master/Documentation/markdown.md)
@@ -42,6 +42,7 @@ Please check the supported operator list for your chosen runtime for further inf
| RELU_N1_TO_1 | [Generic](#tflite-generic-constraints) |
| RESHAPE | [Generic](#tflite-generic-constraints), [Specific](#tflite-reshape-constraints) |
| RESIZE_BILINEAR | [Generic](#tflite-generic-constraints), [Specific](#tflite-resize_bilinear-constraints) |
+| SHAPE | [Generic](#tflite-generic-constraints) |
| SLICE | [Generic](#tflite-generic-constraints) |
| SOFTMAX | [Generic](#tflite-generic-constraints), [Specific](#tflite-softmax-constraints) |
| SPLIT | [Generic](#tflite-generic-constraints) |
@@ -61,14 +62,14 @@ This is a list of constraints most NPU operators must satisfy in order to be sch
- Input(s) and Output tensors must not be dynamic - [Quantize]
- Input(s) and Output tensors must have a defined shape
- Output tensors cannot be scalar - [Quantize]
-- Scalar Input tensors are only valid for op type: ADD, EXPAND_DIMS, MAXIMUM, MEAN, MINIMUM, MUL, SPLIT, SPLIT_V, SUB - [Quantize]
+- Scalar Input tensors are only valid for op type: ADD, EXPAND_DIMS, MAXIMUM, MEAN, MINIMUM, MUL, QUANTIZE, SPLIT, SPLIT_V, SUB
- Input(s) and Output tensors must not be greater than 4D
- Input(s), Output and Weight tensors must have quantization parameters - [Shape]
-- Input(s), Output and Weight tensors with quantization scales must be finite - [Shape]
-- Input and Output tensors must have quantization scales that fit within float32 precision - [Shape]
+- Input(s), Output and Weight tensors with quantization scales must be finite
+- Input and Output tensors must have quantization scales that fit within float32 precision
- Constant tensors should not have NoneType-values
- Tensors must be of type: int16, int32, int8, uint8
-- Tensors which are int32 are only valid when op type is: ADD, MUL, SUB
+- Tensors which are int32 are only valid when op type is: ADD, MUL, SHAPE, SUB
- Tensor dimensions must be in the range [1, 65535]
- Per-axis quantization is only supported for the following op types: CONV_2D, DEPTHWISE_CONV_2D, TRANSPOSE_CONV
- The fused activation function (if present) must be one of type: LOGISTIC, RELU, RELU6, RELU_N1_TO_1, TANH
diff --git a/ethosu/vela/operation.py b/ethosu/vela/operation.py
index 5ed18621..db1c6f18 100644
--- a/ethosu/vela/operation.py
+++ b/ethosu/vela/operation.py
@@ -834,7 +834,16 @@ class Operation:
self.ifm_shapes = []
self.ofm_shapes = []
- ifm_tensor, ifm2_tensor, weight_tensor, ofm_tensor = self.get_ifm_ifm2_weights_ofm()
+ ifm_tensor, ifm2_tensor, ofm_tensor = self.get_ifm_ifm2_ofm()
+
+ if self.type == Op.Reshape:
+ # Set ofm shape
+ if len(self.inputs) > 1 and self.inputs[1].values is not None:
+ ofm_tensor.shape = self.inputs[1].values.flatten().tolist()
+ ofm_elements = ofm_tensor.elements()
+ # Stretch dimension
+ if ofm_elements < 0:
+ ofm_tensor.shape[ofm_tensor.shape.index(-1)] = int(ifm_tensor.elements() / abs(ofm_elements))
# set all shapes to op, as 4D
if self.type == Op.FullyConnected:
@@ -847,7 +856,7 @@ class Operation:
self.ofm_shapes.append(Shape4D([self.ofm.shape[0], 1, 1, self.ofm.shape[1]]))
else:
self.ofm_shapes.append(Shape4D(ofm_tensor.get_full_shape()))
- if self.type == Op.Softmax:
+ elif self.type == Op.Softmax:
self.ifm_shapes.append(Shape4D(ifm_tensor.get_full_shape()))
self.ofm_shapes.append(Shape4D(ofm_tensor.get_full_shape()))
elif self.type.is_split_op() or self.type.is_concat_op():
diff --git a/ethosu/vela/tflite_graph_optimiser.py b/ethosu/vela/tflite_graph_optimiser.py
index f2a8c803..b1a56605 100644
--- a/ethosu/vela/tflite_graph_optimiser.py
+++ b/ethosu/vela/tflite_graph_optimiser.py
@@ -1408,10 +1408,8 @@ def optimise_quantize(op: Operation, arch, nng):
if input_values.ndim == 0:
input_values = np.array([input_values])
- # requantized int8 to int8
- if (ifm.dtype == DataType.int8 and ofm.dtype == DataType.int8) or (
- ifm.dtype == DataType.int16 and ofm.dtype == DataType.int16
- ):
+ # requantized int8 to int8 or int16 to int16
+ if ifm.dtype == ofm.dtype == DataType.int8 or ifm.dtype == ofm.dtype == DataType.int16:
# scale needs to use double precision to match TFLite reference kernel
effective_scale = np.float64(ifm.quantization.scale_f32) / np.float64(ofm.quantization.scale_f32)
@@ -1495,7 +1493,7 @@ def supported_operator_check(op, arch, nng):
def tflite_optimise_graph(nng, arch):
- # Compile time optimisations
+ # Compile time static optimisations
optimisation_list = [optimise_quantize, convert_shape_op_to_constant_tensor]
for idx, sg in enumerate(nng.subgraphs):
diff --git a/ethosu/vela/tflite_model_semantic.py b/ethosu/vela/tflite_model_semantic.py
index 9408e0ce..16ca2797 100644
--- a/ethosu/vela/tflite_model_semantic.py
+++ b/ethosu/vela/tflite_model_semantic.py
@@ -76,7 +76,7 @@ class TFLiteSemantic:
)
binary_elem_wise_main_ops = binary_elem_wise_min_max_ops | binary_elem_wise_add_mul_sub | binary_elem_wise_shift_ops
elem_wise_main_ops = binary_elem_wise_main_ops | unary_elem_wise_main_ops
- shapeless_input_ops = binary_elem_wise_main_ops | set((Op.Split, Op.SplitV, Op.Mean, Op.ExpandDims))
+ shapeless_input_ops = binary_elem_wise_main_ops | set((Op.Split, Op.SplitV, Op.Mean, Op.ExpandDims, Op.Quantize))
reshape_ops = set(
(
Op.Reshape,
@@ -214,13 +214,10 @@ class TFLiteSemantic:
generic_constraints_exclude_list = {
Op.Shape: [
TFLiteSemantic.constraint_tens_quant_none_check,
- TFLiteSemantic.constraint_tens_quant_scale,
- TFLiteSemantic.constraint_quant_scale_inf,
],
Op.Quantize: [
TFLiteSemantic.constraint_tens_no_dynamic,
TFLiteSemantic.constraint_tens_output_scalar,
- TFLiteSemantic.constraint_tens_input_scalar,
],
}
return generic_constraints_exclude_list
@@ -314,7 +311,11 @@ class TFLiteSemantic:
extra = []
tensors = [tens for tens in op.get_ifm_ifm2_weights_ofm() if tens]
for tens in tensors:
- if (tens.quantization.scale_f32 is not None) and np.isinf(tens.quantization.scale_f32).any():
+ if (
+ tens.quantization
+ and tens.quantization.scale_f32 is not None
+ and np.isinf(tens.quantization.scale_f32).any()
+ ):
valid = False
extra.append(f"Tensor '{tens.name}' has quantization scale: {tens.quantization.scale_f32}")
return valid, ", ".join(extra)
diff --git a/ethosu/vela/tflite_supported_operators.py b/ethosu/vela/tflite_supported_operators.py
index 6328a4e5..25a34e82 100644
--- a/ethosu/vela/tflite_supported_operators.py
+++ b/ethosu/vela/tflite_supported_operators.py
@@ -39,7 +39,12 @@ def _optype_formatter(op_list):
class TFLiteSupportedOperators:
# Categorised lists of supported operators
- npu_pre_ops = set((Op.SplitSliceRead,))
+ npu_pre_ops = set(
+ (
+ Op.SplitSliceRead,
+ Op.Shape,
+ )
+ )
convolution_ops = set(
(
Op.Conv2DBias,
@@ -103,6 +108,7 @@ class TFLiteSupportedOperators:
(
Op.ReduceSum,
Op.CLZ,
+ Op.Shape,
)
)
| binary_elem_wise_add_mul_sub
@@ -363,7 +369,7 @@ class TFLiteSupportedOperators:
if op.type not in cls.per_axis_quant_ops:
tensors = [tens for tens in op.get_ifm_ifm2_weights_ofm() if tens]
for tens in tensors:
- if tens.quantization.is_per_axis():
+ if tens.quantization and tens.quantization.is_per_axis():
valid = False
extra.append(tens.name)
return valid, "The following tensor(s) have per-axis quantization parameters: " + ", ".join(extra)