aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Eilers <jan.eilers@arm.com>2020-08-12 14:59:06 +0100
committerTeresaARM <teresa.charlinreyes@arm.com>2020-08-17 16:10:54 +0000
commit841aca155b35cc17ea9527599d2c364695e28166 (patch)
tree8861d6f275f5955495201f0e1b0677bb44604a17
parent313c99f9a64c7fc51dc70757bffff3088c2e95cf (diff)
downloadarmnn-841aca155b35cc17ea9527599d2c364695e28166.tar.gz
IVGCVSW-5200 Update pyarmnn
* Add HalfPixelCenters to Resize * Update pyarmnn version to semantic versioning * Add fill operator * Add Bf16 optimization * Add Gather operator * Update TransposeConvolution2d descriptor * Add Rank operator * Add load dynamic tensor support of TfLiteParser Signed-off-by: Jan Eilers <jan.eilers@arm.com> Change-Id: I7e76ed286ab87bd97a65ff62868ba7db7967376f
-rw-r--r--python/pyarmnn/examples/example_utils.py4
-rw-r--r--python/pyarmnn/src/pyarmnn/__init__.py6
-rw-r--r--python/pyarmnn/src/pyarmnn/swig/armnn_tfliteparser.i30
-rw-r--r--python/pyarmnn/src/pyarmnn/swig/armnn_version.i4
-rw-r--r--python/pyarmnn/src/pyarmnn/swig/modules/armnn_descriptors.i66
-rw-r--r--python/pyarmnn/src/pyarmnn/swig/modules/armnn_network.i58
-rw-r--r--python/pyarmnn/test/test_descriptors.py21
-rw-r--r--python/pyarmnn/test/test_network.py19
-rw-r--r--python/pyarmnn/test/test_tflite_parser.py42
9 files changed, 217 insertions, 33 deletions
diff --git a/python/pyarmnn/examples/example_utils.py b/python/pyarmnn/examples/example_utils.py
index f4d1e4eb1f..5ef30f2331 100644
--- a/python/pyarmnn/examples/example_utils.py
+++ b/python/pyarmnn/examples/example_utils.py
@@ -73,7 +73,7 @@ def __create_network(model_file: str, backends: list, parser=None):
def create_tflite_network(model_file: str, backends: list = ['CpuAcc', 'CpuRef']):
- """Creates a network from an onnx model file.
+ """Creates a network from a tflite model file.
Args:
model_file (str): Path of the model file.
@@ -92,7 +92,7 @@ def create_tflite_network(model_file: str, backends: list = ['CpuAcc', 'CpuRef']
def create_onnx_network(model_file: str, backends: list = ['CpuAcc', 'CpuRef']):
- """Creates a network from a tflite model file.
+ """Creates a network from an onnx model file.
Args:
model_file (str): Path of the model file.
diff --git a/python/pyarmnn/src/pyarmnn/__init__.py b/python/pyarmnn/src/pyarmnn/__init__.py
index 265880f2bc..b1aa81f507 100644
--- a/python/pyarmnn/src/pyarmnn/__init__.py
+++ b/python/pyarmnn/src/pyarmnn/__init__.py
@@ -47,7 +47,7 @@ except ImportError as err:
raise RuntimeError(message)
try:
- from ._generated.pyarmnn_tfliteparser import ITfLiteParser
+ from ._generated.pyarmnn_tfliteparser import ITfLiteParser, TfLiteParserOptions
except ImportError as err:
logger = logging.getLogger(__name__)
message = "Your ArmNN library instance does not support TF lite models parser functionality. "
@@ -92,8 +92,8 @@ from ._generated.pyarmnn import ComparisonDescriptor, ComparisonOperation_Equal,
from ._generated.pyarmnn import UnaryOperation_Abs, UnaryOperation_Exp, UnaryOperation_Sqrt, UnaryOperation_Rsqrt, \
UnaryOperation_Neg, ElementwiseUnaryDescriptor
from ._generated.pyarmnn import Convolution2dDescriptor, DepthToSpaceDescriptor, DepthwiseConvolution2dDescriptor, \
- DetectionPostProcessDescriptor, FakeQuantizationDescriptor, FullyConnectedDescriptor, \
- InstanceNormalizationDescriptor, LstmDescriptor, L2NormalizationDescriptor, MeanDescriptor
+ DetectionPostProcessDescriptor, FakeQuantizationDescriptor, FillDescriptor, FullyConnectedDescriptor, \
+ GatherDescriptor, InstanceNormalizationDescriptor, LstmDescriptor, L2NormalizationDescriptor, MeanDescriptor
from ._generated.pyarmnn import NormalizationAlgorithmChannel_Across, NormalizationAlgorithmChannel_Within, \
NormalizationAlgorithmMethod_LocalBrightness, NormalizationAlgorithmMethod_LocalContrast, NormalizationDescriptor
from ._generated.pyarmnn import PadDescriptor
diff --git a/python/pyarmnn/src/pyarmnn/swig/armnn_tfliteparser.i b/python/pyarmnn/src/pyarmnn/swig/armnn_tfliteparser.i
index 825b104a27..3ed5d6b8fd 100644
--- a/python/pyarmnn/src/pyarmnn/swig/armnn_tfliteparser.i
+++ b/python/pyarmnn/src/pyarmnn/swig/armnn_tfliteparser.i
@@ -87,14 +87,37 @@ public:
list: A list of the output tensor names for the given model.
") GetSubgraphOutputTensorNames;
std::vector<std::string> GetSubgraphOutputTensorNames(size_t subgraphId);
+
+ %feature("flatnested");
+ %feature("docstring",
+ "
+ Options for TfLiteParser.
+
+ Contains:
+ m_StandInLayerForUnsupported (bool): Add StandInLayers as placeholders for unsupported operators.
+ Default: False
+ m_InferAndValidate (bool): Infer output shape of operations based on their input shape. Default: False
+ ")TfLiteParserOptions;
+ struct TfLiteParserOptions
+ {
+ TfLiteParserOptions();
+
+ bool m_StandInLayerForUnsupported;
+ bool m_InferAndValidate;
+ };
};
%extend ITfLiteParser {
// This is not a substitution of the default constructor of the Armnn class. It tells swig to create custom __init__
// method for ITfLiteParser python object that will use static factory method to do the job.
- ITfLiteParser() {
- return armnnTfLiteParser::ITfLiteParser::CreateRaw();
+ ITfLiteParser(const armnnTfLiteParser::ITfLiteParser::TfLiteParserOptions* options = nullptr) {
+ if (options) {
+ return armnnTfLiteParser::ITfLiteParser::CreateRaw(
+ armnn::Optional<armnnTfLiteParser::ITfLiteParser::TfLiteParserOptions>(*options));
+ } else {
+ return armnnTfLiteParser::ITfLiteParser::CreateRaw();
+ }
}
// The following does not replace a real destructor of the Armnn class.
@@ -127,6 +150,7 @@ public:
}
-}
+} // end of namespace armnnTfLiteParser
+
// Clear exception typemap.
%exception;
diff --git a/python/pyarmnn/src/pyarmnn/swig/armnn_version.i b/python/pyarmnn/src/pyarmnn/swig/armnn_version.i
index b21fbb1393..039b16605d 100644
--- a/python/pyarmnn/src/pyarmnn/swig/armnn_version.i
+++ b/python/pyarmnn/src/pyarmnn/swig/armnn_version.i
@@ -39,7 +39,7 @@ std::string GetVersion();
%feature("docstring",
"
- Returns Arm NN library major version. The year of the release.
+ Returns Arm NN library major version.
Returns:
str: Major version of Arm NN installed.
@@ -49,7 +49,7 @@ std::string GetMajorVersion();
%feature("docstring",
"
- Returns Arm NN library minor version. Month of the year of the release.
+ Returns Arm NN library minor version.
Returns:
str: Minor version of Arm NN installed.
diff --git a/python/pyarmnn/src/pyarmnn/swig/modules/armnn_descriptors.i b/python/pyarmnn/src/pyarmnn/swig/modules/armnn_descriptors.i
index 9a01a52e13..a050722bb9 100644
--- a/python/pyarmnn/src/pyarmnn/swig/modules/armnn_descriptors.i
+++ b/python/pyarmnn/src/pyarmnn/swig/modules/armnn_descriptors.i
@@ -15,6 +15,7 @@ namespace std {
}
%include "typemaps/vectors.i"
+%include "stdint.i"
%typemap(out) const uint32_t*
%{
@@ -388,6 +389,46 @@ struct FakeQuantizationDescriptor
%feature("docstring",
"
+ A descriptor for the Fill layer. Creates a tensor filled with a scalar value.
+
+ Contains:
+ m_Value (float): Value the tensor will be filled with.
+
+ ") FillDescriptor;
+struct FillDescriptor
+{
+ FillDescriptor();
+ FillDescriptor(const float& value);
+
+ bool operator ==(const FillDescriptor& rhs) const;
+
+ float m_Value;
+};
+
+%feature("docstring",
+ "
+ A descriptor for the Gather layer.
+
+ Contains:
+ m_Axis (int32_t): The axis from where to gather values from.
+
+ ") GatherDescriptor;
+struct GatherDescriptor
+{
+ GatherDescriptor();
+
+ GatherDescriptor(int32_t axis);
+
+ bool operator ==(const GatherDescriptor& rhs) const
+ {
+ return m_Axis == rhs.m_Axis;
+ }
+
+ int32_t m_Axis;
+};
+
+%feature("docstring",
+ "
A descriptor for the FullyConnected layer. See `INetwork.AddFullyConnectedLayer()`.
Contains:
@@ -661,7 +702,9 @@ struct ReshapeDescriptor
Default: `ResizeMethod_NearestNeighbor`.
m_DataLayout (int): The data layout to be used (`DataLayout_NCHW`, `DataLayout_NHWC`). Default: `DataLayout_NCHW`.
m_AlignCorners (bool): Align corners or not when resizing. If True, corner pixel values are preserved after resizing.
- Default: False
+ Default: False.
+ m_HalfPixelCenters (bool): If true, calculates the pixels from the center instead of from the edge.
+ Default: False.
") ResizeDescriptor;
struct ResizeDescriptor
@@ -673,6 +716,7 @@ struct ResizeDescriptor
ResizeMethod m_Method;
DataLayout m_DataLayout;
bool m_AlignCorners;
+ bool m_HalfPixelCenters;
bool operator ==(const ResizeDescriptor& rhs) const;
};
@@ -970,20 +1014,24 @@ struct SoftmaxDescriptor
m_StrideY (int): Underlying C++ data type is uint32_t. Stride value when proceeding through input for the height dimension. Default: 0.
m_BiasEnabled (bool): Enable/disable bias. Default: false.
m_DataLayout (int): The data layout to be used (`DataLayout_NCHW`, `DataLayout_NHWC`). Default: `DataLayout_NCHW`.
+ m_OutputShapeEnabled (bool): Set to true if output shape is specified. Will prevent output shape inference.
+ m_OutputShape (list of int): Output shape if it has been specified.
") TransposeConvolution2dDescriptor;
struct TransposeConvolution2dDescriptor
{
TransposeConvolution2dDescriptor();
- uint32_t m_PadLeft;
- uint32_t m_PadRight;
- uint32_t m_PadTop;
- uint32_t m_PadBottom;
- uint32_t m_StrideX;
- uint32_t m_StrideY;
- bool m_BiasEnabled;
- DataLayout m_DataLayout;
+ uint32_t m_PadLeft;
+ uint32_t m_PadRight;
+ uint32_t m_PadTop;
+ uint32_t m_PadBottom;
+ uint32_t m_StrideX;
+ uint32_t m_StrideY;
+ bool m_BiasEnabled;
+ DataLayout m_DataLayout;
+ bool m_OutputShapeEnabled;
+ std::vector<unsigned int> m_OutputShape;
bool operator ==(const TransposeConvolution2dDescriptor& rhs) const;
};
diff --git a/python/pyarmnn/src/pyarmnn/swig/modules/armnn_network.i b/python/pyarmnn/src/pyarmnn/swig/modules/armnn_network.i
index b065331992..4665e6087e 100644
--- a/python/pyarmnn/src/pyarmnn/swig/modules/armnn_network.i
+++ b/python/pyarmnn/src/pyarmnn/swig/modules/armnn_network.i
@@ -20,15 +20,21 @@ Struct for holding options relating to the Arm NN optimizer. See `Optimize`.
Contains:
m_debug (bool): Add debug data for easier troubleshooting.
- m_ReduceFp32ToFp16 (bool): Reduce Fp32 data to Fp16 for faster processing.
+ m_ReduceFp32ToBf16 (bool): Reduces Fp32 network to BFloat16 (Bf16) for faster processing. Layers
+ that can not be reduced will be left in Fp32.
+ m_ReduceFp32ToFp16 (bool): Reduces Fp32 network to Fp16 for faster processing. Layers
+ that can not be reduced will be left in Fp32.
") OptimizerOptions;
struct OptimizerOptions
{
OptimizerOptions();
- OptimizerOptions(bool reduceFp32ToFp16, bool debug);
+ OptimizerOptions(bool reduceFp32ToFp16,
+ bool debug,
+ bool reduceFp32ToBf16 = false);
+ bool m_ReduceFp32ToBf16;
bool m_ReduceFp32ToFp16;
bool m_Debug;
};
@@ -501,21 +507,35 @@ public:
armnn::IConnectableLayer* AddDivisionLayer(const char* name = nullptr);
%feature("docstring",
- "
- Adds an Elementwise Unary layer to the network. Type of unary operation to use is decided by elementwiseUnaryDescriptor. Unary operations supported are (Abs, Exp, Neg, Rsqrt, Sqrt)
+ "
+ Adds an Elementwise Unary layer to the network. Type of unary operation to use is decided by elementwiseUnaryDescriptor. Unary operations supported are (Abs, Exp, Neg, Rsqrt, Sqrt)
- Args:
- elementwiseUnaryDescriptor (ElementwiseUnaryDescriptor): ElementwiseUnaryDescriptor to configure the choice of unary operation added to the network.
- name (str): Optional name for the layer.
+ Args:
+ elementwiseUnaryDescriptor (ElementwiseUnaryDescriptor): ElementwiseUnaryDescriptor to configure the choice of unary operation added to the network.
+ name (str): Optional name for the layer.
- Returns:
- IConnectableLayer: Interface for configuring the layer.
- ") AddElementwiseUnaryLayer;
+ Returns:
+ IConnectableLayer: Interface for configuring the layer.
+ ") AddElementwiseUnaryLayer;
armnn::IConnectableLayer* AddElementwiseUnaryLayer(const ElementwiseUnaryDescriptor& elementwiseUnaryDescriptor,
const char* name = nullptr);
%feature("docstring",
"
+ Add a Fill layer to the network.
+
+ Args:
+ FillDescriptor (FillDescriptor): Descriptor for the fill operation.
+ name (str): Optional name for the layer.
+
+ Returns:
+ IConnectableLayer: Interface for configuring the layer.
+ ") AddFillLayer;
+ armnn::IConnectableLayer* AddFillLayer(const FillDescriptor& fillDescriptor,
+ const char* name = nullptr);
+
+ %feature("docstring",
+ "
Adds a Floor layer to the network.
Args:
@@ -531,12 +551,14 @@ public:
Add Gather layer to the network.
Args:
+ descriptor (GatherDescriptor): Descriptor for the gather operation.
name (str): Optional name for the layer.
Returns:
IConnectableLayer: Interface for configuring the layer.
") AddGatherLayer;
- armnn::IConnectableLayer* AddGatherLayer(const char* name = nullptr);
+ armnn::IConnectableLayer* AddGatherLayer(const GatherDescriptor& descriptor,
+ const char* name = nullptr);
%feature("docstring",
"
@@ -752,6 +774,20 @@ public:
armnn::IConnectableLayer* AddQuantizedLstmLayer(const armnn::QuantizedLstmInputParams& params,
const char* name = nullptr);
+
+ %feature("docstring",
+ "
+ Adds a Rank layer to the network.
+
+ Args:
+ name (str): Optional name for the layer.
+
+ Returns:
+ IConnectableLayer: Interface for configuring the layer.
+ ") AddRankLayer;
+ armnn::IConnectableLayer* AddRankLayer(const char* name = nullptr);
+
+
%feature("docstring",
"
Adds a Reshape layer to the network.
diff --git a/python/pyarmnn/test/test_descriptors.py b/python/pyarmnn/test/test_descriptors.py
index 6d49747d5a..b0574a14ba 100644
--- a/python/pyarmnn/test/test_descriptors.py
+++ b/python/pyarmnn/test/test_descriptors.py
@@ -143,6 +143,16 @@ def test_fakequantization_descriptor_default_values():
np.allclose(-6, desc.m_Min)
+def test_fill_descriptor_default_values():
+ desc = ann.FillDescriptor()
+ np.allclose(0, desc.m_Value)
+
+
+def test_gather_descriptor_default_values():
+ desc = ann.GatherDescriptor()
+ assert desc.m_Axis == 0
+
+
def test_fully_connected_descriptor_default_values():
desc = ann.FullyConnectedDescriptor()
assert desc.m_BiasEnabled == False
@@ -370,7 +380,7 @@ def test_space_to_batch_nd_descriptor_ctor():
def test_transpose_convolution2d_descriptor_default_values():
- desc = ann.DepthwiseConvolution2dDescriptor()
+ desc = ann.TransposeConvolution2dDescriptor()
assert desc.m_PadLeft == 0
assert desc.m_PadTop == 0
assert desc.m_PadRight == 0
@@ -379,6 +389,7 @@ def test_transpose_convolution2d_descriptor_default_values():
assert desc.m_StrideY == 0
assert desc.m_BiasEnabled == False
assert desc.m_DataLayout == ann.DataLayout_NCHW
+ assert desc.m_OutputShapeEnabled == False
def test_view_descriptor_default_values():
@@ -480,7 +491,9 @@ generated_classes_names = list(map(lambda x: x[0], generated_classes))
'StackDescriptor',
'StridedSliceDescriptor',
'TransposeConvolution2dDescriptor',
- 'ElementwiseUnaryDescriptor'])
+ 'ElementwiseUnaryDescriptor',
+ 'FillDescriptor',
+ 'GatherDescriptor'])
class TestDescriptorMassChecks:
def test_desc_implemented(self, desc_name):
@@ -522,7 +535,9 @@ generated_classes_names = list(map(lambda x: x[0], generated_classes))
'StackDescriptor',
'StridedSliceDescriptor',
'TransposeConvolution2dDescriptor',
- 'ElementwiseUnaryDescriptor'])
+ 'ElementwiseUnaryDescriptor',
+ 'FillDescriptor',
+ 'GatherDescriptor'])
class TestDescriptorMassChecks:
def test_desc_implemented(self, desc_name):
diff --git a/python/pyarmnn/test/test_network.py b/python/pyarmnn/test/test_network.py
index fc2591c1d5..679e640374 100644
--- a/python/pyarmnn/test/test_network.py
+++ b/python/pyarmnn/test/test_network.py
@@ -6,6 +6,23 @@ import stat
import pytest
import pyarmnn as ann
+def test_optimizer_options_default_values():
+ opt = ann.OptimizerOptions()
+ assert opt.m_ReduceFp32ToFp16 == False
+ assert opt.m_Debug == False
+ assert opt.m_ReduceFp32ToBf16 == False
+
+def test_optimizer_options_set_values1():
+ opt = ann.OptimizerOptions(True, True)
+ assert opt.m_ReduceFp32ToFp16 == True
+ assert opt.m_Debug == True
+ assert opt.m_ReduceFp32ToBf16 == False
+
+def test_optimizer_options_set_values2():
+ opt = ann.OptimizerOptions(False, False, True)
+ assert opt.m_ReduceFp32ToFp16 == False
+ assert opt.m_Debug == False
+ assert opt.m_ReduceFp32ToBf16 == True
@pytest.fixture(scope="function")
def get_runtime(shared_data_folder, network_file):
@@ -166,6 +183,7 @@ def test_serialize_to_dot_mode_readonly(network_file, get_runtime, tmpdir):
'AddDivisionLayer',
'AddElementwiseUnaryLayer',
'AddFloorLayer',
+ 'AddFillLayer',
'AddFullyConnectedLayer',
'AddGatherLayer',
'AddInputLayer',
@@ -186,6 +204,7 @@ def test_serialize_to_dot_mode_readonly(network_file, get_runtime, tmpdir):
'AddPreluLayer',
'AddQuantizeLayer',
'AddQuantizedLstmLayer',
+ 'AddRankLayer',
'AddReshapeLayer',
'AddResizeLayer',
'AddSliceLayer',
diff --git a/python/pyarmnn/test/test_tflite_parser.py b/python/pyarmnn/test/test_tflite_parser.py
index 344ec7ca13..8735eef3fb 100644
--- a/python/pyarmnn/test/test_tflite_parser.py
+++ b/python/pyarmnn/test/test_tflite_parser.py
@@ -7,6 +7,12 @@ import pyarmnn as ann
import numpy as np
+def test_TfLiteParserOptions_default_values():
+ parserOptions = ann.TfLiteParserOptions()
+ assert parserOptions.m_InferAndValidate == False
+ assert parserOptions.m_StandInLayerForUnsupported == False
+
+
@pytest.fixture()
def parser(shared_data_folder):
"""
@@ -30,6 +36,42 @@ def test_check_tflite_parser_swig_ownership(parser):
assert parser.thisown
+def test_tflite_parser_with_optional_options():
+ parserOptions = ann.TfLiteParserOptions()
+ parserOptions.m_InferAndValidate = True
+ parser = ann.ITfLiteParser(parserOptions)
+ assert parser.thisown
+
+
+def create_with_opt() :
+ parserOptions = ann.TfLiteParserOptions()
+ parserOptions.m_InferAndValidate = True
+ return ann.ITfLiteParser(parserOptions)
+
+def test_tflite_parser_with_optional_options_out_of_scope(shared_data_folder):
+ parser = create_with_opt()
+ network = parser.CreateNetworkFromBinaryFile(os.path.join(shared_data_folder, "mock_model.tflite"))
+
+ graphs_count = parser.GetSubgraphCount()
+ graph_id = graphs_count - 1
+
+ input_names = parser.GetSubgraphInputTensorNames(graph_id)
+ input_binding_info = parser.GetNetworkInputBindingInfo(graph_id, input_names[0])
+
+ output_names = parser.GetSubgraphOutputTensorNames(graph_id)
+
+ preferred_backends = [ann.BackendId('CpuAcc'), ann.BackendId('CpuRef')]
+
+ options = ann.CreationOptions()
+ runtime = ann.IRuntime(options)
+
+ opt_network, messages = ann.Optimize(network, preferred_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
+ assert 0 == len(messages)
+
+ net_id, messages = runtime.LoadNetwork(opt_network)
+ assert "" == messages
+
+
def test_tflite_get_sub_graph_count(parser):
graphs_count = parser.GetSubgraphCount()
assert graphs_count == 1