From 2605b236d103e1ba27069e0d668599042a4761af Mon Sep 17 00:00:00 2001 From: Finn Williams Date: Wed, 10 Jun 2020 15:53:46 +0100 Subject: IVGCVSW-4624 Add a RANK Reference Implementation * Add Rank front end * Add Rank reference implementation * Add Rank serialization support * Add Scalar serialization support Signed-off-by: Finn Williams Change-Id: I06e4a468c2a84e79bae2e6c5348596bbbf853b4b --- Android.mk | 1 + CMakeLists.txt | 5 +- include/armnn/ILayerSupport.hpp | 4 + include/armnn/ILayerVisitor.hpp | 6 + include/armnn/INetwork.hpp | 5 + include/armnn/LayerVisitorBase.hpp | 3 + src/armnn/InternalTypes.hpp | 3 +- src/armnn/LayersFwd.hpp | 2 + src/armnn/Network.cpp | 5 + src/armnn/Network.hpp | 2 + src/armnn/layers/RankLayer.cpp | 47 ++++ src/armnn/layers/RankLayer.hpp | 34 +++ src/armnn/test/TestNameOnlyLayerVisitor.cpp | 1 + src/armnn/test/TestNameOnlyLayerVisitor.hpp | 1 + src/armnnDeserializer/Deserializer.cpp | 35 ++- src/armnnDeserializer/Deserializer.hpp | 3 +- src/armnnDeserializer/DeserializerSupport.md | 1 + src/armnnDeserializer/test/DeserializeRank.cpp | 151 ++++++++++++ src/armnnSerializer/ArmnnSchema.fbs | 11 +- src/armnnSerializer/Serializer.cpp | 23 +- src/armnnSerializer/Serializer.hpp | 3 + src/armnnSerializer/SerializerSupport.md | 1 + src/armnnSerializer/test/SerializerTests.cpp | 26 ++ src/backends/backendsCommon/LayerSupportBase.cpp | 7 + src/backends/backendsCommon/LayerSupportBase.hpp | 4 + src/backends/backendsCommon/WorkloadData.cpp | 29 +++ src/backends/backendsCommon/WorkloadData.hpp | 5 + src/backends/backendsCommon/WorkloadFactory.cpp | 17 +- src/backends/backendsCommon/WorkloadFactory.hpp | 3 + .../backendsCommon/WorkloadFactoryBase.hpp | 4 + src/backends/backendsCommon/common.mk | 1 + src/backends/backendsCommon/test/CMakeLists.txt | 2 + .../test/IsLayerSupportedTestImpl.hpp | 2 + src/backends/backendsCommon/test/LayerTests.hpp | 3 +- .../test/layerTests/RankTestImpl.cpp | 262 +++++++++++++++++++++ .../test/layerTests/RankTestImpl.hpp | 40 ++++ src/backends/reference/RefLayerSupport.cpp | 15 ++ src/backends/reference/RefLayerSupport.hpp | 4 + src/backends/reference/RefWorkloadFactory.cpp | 6 + src/backends/reference/RefWorkloadFactory.hpp | 3 + src/backends/reference/test/RefLayerTests.cpp | 40 +++- src/backends/reference/workloads/CMakeLists.txt | 3 +- .../reference/workloads/RefRankWorkload.hpp | 32 +++ src/backends/reference/workloads/RefWorkloads.hpp | 3 +- 44 files changed, 840 insertions(+), 18 deletions(-) create mode 100644 src/armnn/layers/RankLayer.cpp create mode 100644 src/armnn/layers/RankLayer.hpp create mode 100644 src/armnnDeserializer/test/DeserializeRank.cpp create mode 100644 src/backends/backendsCommon/test/layerTests/RankTestImpl.cpp create mode 100644 src/backends/backendsCommon/test/layerTests/RankTestImpl.hpp create mode 100644 src/backends/reference/workloads/RefRankWorkload.hpp diff --git a/Android.mk b/Android.mk index 31fda2f852..38b2ad4008 100644 --- a/Android.mk +++ b/Android.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ src/armnn/layers/QLstmLayer.cpp \ src/armnn/layers/QuantizeLayer.cpp \ src/armnn/layers/QuantizedLstmLayer.cpp \ + src/armnn/layers/RankLayer.cpp \ src/armnn/layers/ReshapeLayer.cpp \ src/armnn/layers/ResizeLayer.cpp \ src/armnn/layers/SliceLayer.cpp \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f5a0bd046..968c57f9ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright © 2020 Arm Ltd. All rights reserved. +# Copyright © 2020 Arm Ltd. and Contributors All rights reserved. # Copyright 2020 NXP # SPDX-License-Identifier: MIT # @@ -354,6 +354,8 @@ list(APPEND armnn_sources src/armnn/layers/PreCompiledLayer.cpp src/armnn/layers/PreluLayer.hpp src/armnn/layers/PreluLayer.cpp + src/armnn/layers/RankLayer.hpp + src/armnn/layers/RankLayer.cpp src/armnn/layers/ReshapeLayer.hpp src/armnn/layers/ReshapeLayer.cpp src/armnn/layers/ResizeLayer.hpp @@ -894,6 +896,7 @@ if(BUILD_UNIT_TESTS) src/armnnDeserializer/test/DeserializePad.cpp src/armnnDeserializer/test/DeserializePermute.cpp src/armnnDeserializer/test/DeserializePooling2d.cpp + src/armnnDeserializer/test/DeserializeRank.cpp src/armnnDeserializer/test/DeserializeReshape.cpp src/armnnDeserializer/test/DeserializeResizeBilinear.cpp src/armnnDeserializer/test/DeserializeRsqrt.cpp diff --git a/include/armnn/ILayerSupport.hpp b/include/armnn/ILayerSupport.hpp index 889b811903..ed234fe4db 100644 --- a/include/armnn/ILayerSupport.hpp +++ b/include/armnn/ILayerSupport.hpp @@ -314,6 +314,10 @@ public: const QuantizedLstmInputParamsInfo& paramsInfo, Optional reasonIfUnsupported = EmptyOptional()) const = 0; + virtual bool IsRankSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const = 0; + virtual bool IsReshapeSupported(const TensorInfo& input, const TensorInfo& output, const ReshapeDescriptor& descriptor, diff --git a/include/armnn/ILayerVisitor.hpp b/include/armnn/ILayerVisitor.hpp index 9b3998db9a..385ad62225 100644 --- a/include/armnn/ILayerVisitor.hpp +++ b/include/armnn/ILayerVisitor.hpp @@ -395,6 +395,12 @@ public: const QuantizedLstmInputParams& params, const char* name = nullptr) = 0; + /// Function a rank layer should call back to when its Accept(ILayerVisitor&) function is invoked. + /// @param layer - pointer to the layer which is calling back to this visit function. + /// @param name - Optional name for the layer. + virtual void VisitRankLayer(const IConnectableLayer* layer, + const char* name = nullptr) = 0; + /// Function a reshape layer should call back to when its Accept(ILayerVisitor&) function is invoked. /// @param layer - pointer to the layer which is calling back to this visit function. /// @param reshapeDescriptor - Parameters for the reshape operation. diff --git a/include/armnn/INetwork.hpp b/include/armnn/INetwork.hpp index 8e7a4437c8..c0c52f974a 100644 --- a/include/armnn/INetwork.hpp +++ b/include/armnn/INetwork.hpp @@ -352,6 +352,11 @@ public: const ConstTensor& gamma, const char* name = nullptr) = 0; + /// Adds a rank layer to the network. + /// @param name - Optional name for the layer. + /// @return - Interface for configuring the layer. + virtual IConnectableLayer* AddRankLayer(const char* name = nullptr) = 0; + /// Adds a resize bilinear layer to the network. /// @param resizeDesc - Parameters for the resize operation. /// @param name - Optional name for the layer. diff --git a/include/armnn/LayerVisitorBase.hpp b/include/armnn/LayerVisitorBase.hpp index 93ba7fe287..75237a4372 100644 --- a/include/armnn/LayerVisitorBase.hpp +++ b/include/armnn/LayerVisitorBase.hpp @@ -201,6 +201,9 @@ public: const QuantizedLstmInputParams&, const char*) override { DefaultPolicy::Apply(__func__); } + void VisitRankLayer(const IConnectableLayer*, + const char*) override { DefaultPolicy::Apply(__func__); } + void VisitReshapeLayer(const IConnectableLayer*, const ReshapeDescriptor&, const char*) override { DefaultPolicy::Apply(__func__); } diff --git a/src/armnn/InternalTypes.hpp b/src/armnn/InternalTypes.hpp index e2ad7a2ea5..fc35d35ef9 100644 --- a/src/armnn/InternalTypes.hpp +++ b/src/armnn/InternalTypes.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once @@ -60,6 +60,7 @@ X(Quantize) \ X(QuantizedLstm) \ X(Reshape) \ + X(Rank) \ X(Resize) \ X(Slice) \ X(Softmax) \ diff --git a/src/armnn/LayersFwd.hpp b/src/armnn/LayersFwd.hpp index 575c3e5c68..fda00df7cc 100644 --- a/src/armnn/LayersFwd.hpp +++ b/src/armnn/LayersFwd.hpp @@ -53,6 +53,7 @@ #include "layers/QuantizeLayer.hpp" #include "layers/QLstmLayer.hpp" #include "layers/QuantizedLstmLayer.hpp" +#include "layers/RankLayer.hpp" #include "layers/ReshapeLayer.hpp" #include "layers/ResizeLayer.hpp" #include "layers/SliceLayer.hpp" @@ -142,6 +143,7 @@ DECLARE_LAYER(Prelu) DECLARE_LAYER(Quantize) DECLARE_LAYER(QLstm) DECLARE_LAYER(QuantizedLstm) +DECLARE_LAYER(Rank) DECLARE_LAYER(Reshape) DECLARE_LAYER(Resize) DECLARE_LAYER(Slice) diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp index 6c7314feb2..e0607bda33 100644 --- a/src/armnn/Network.cpp +++ b/src/armnn/Network.cpp @@ -1460,6 +1460,11 @@ IConnectableLayer* Network::AddBatchNormalizationLayer(const BatchNormalizationD return layer; } +IConnectableLayer* Network::AddRankLayer(const char* name) +{ + return m_Graph->AddLayer(name); +} + IConnectableLayer* Network::AddResizeBilinearLayer(const ResizeBilinearDescriptor& descriptor, const char* name) { diff --git a/src/armnn/Network.hpp b/src/armnn/Network.hpp index 53bf3115f1..6bc0ac7650 100644 --- a/src/armnn/Network.hpp +++ b/src/armnn/Network.hpp @@ -160,6 +160,8 @@ public: const ConstTensor& gamma, const char* name = nullptr) override; + IConnectableLayer* AddRankLayer(const char* name = nullptr) override; + ARMNN_DEPRECATED_MSG("Use AddResizeLayer instead") IConnectableLayer* AddResizeBilinearLayer(const ResizeBilinearDescriptor& resizeDesc, const char* name = nullptr) override; diff --git a/src/armnn/layers/RankLayer.cpp b/src/armnn/layers/RankLayer.cpp new file mode 100644 index 0000000000..f1a24b1633 --- /dev/null +++ b/src/armnn/layers/RankLayer.cpp @@ -0,0 +1,47 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RankLayer.hpp" + +#include "LayerCloneBase.hpp" + +#include +#include + +namespace armnn +{ + +RankLayer::RankLayer(const char* name) + : Layer(1, 1, LayerType::Rank, name) +{} + +std::unique_ptr RankLayer::CreateWorkload(const IWorkloadFactory& factory) const +{ + RankQueueDescriptor descriptor; + return factory.CreateRank(descriptor, PrepInfoAndDesc(descriptor)); +} + +Layer* RankLayer::Clone(Graph& graph) const +{ + RankLayer* clone = CloneBase(graph, GetName()); + return clone; +} + +void RankLayer::ValidateTensorShapesFromInputs(ShapeInferenceMethod shapeInferenceMethod) +{ + IgnoreUnused(shapeInferenceMethod); + VerifyLayerConnections(1, CHECK_LOCATION()); + + ConditionalThrowIfNotEqual( + "Rank: TensorShape set on OutputSlot[0] does not match the inferred shape.", + GetOutputSlot(0).GetTensorInfo().GetShape(), {TensorShape{Dimensionality::Scalar}}); +} + +void RankLayer::Accept(ILayerVisitor& visitor) const +{ + visitor.VisitRankLayer(this, GetName()); +} + +} //namespace armnn \ No newline at end of file diff --git a/src/armnn/layers/RankLayer.hpp b/src/armnn/layers/RankLayer.hpp new file mode 100644 index 0000000000..e160d60354 --- /dev/null +++ b/src/armnn/layers/RankLayer.hpp @@ -0,0 +1,34 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +namespace armnn +{ + +class RankLayer : public Layer +{ + public: + /// Makes a workload for the Rank type. + /// @param [in] factory The workload factory which will create the workload. + /// @return A pointer to the created workload, or nullptr if not created. + virtual std::unique_ptr CreateWorkload(const IWorkloadFactory& factory) const override; + + Layer* Clone(Graph& graph) const override; + + void ValidateTensorShapesFromInputs(ShapeInferenceMethod shapeInferenceMethod) override; + + void Accept(ILayerVisitor& visitor) const override; + + protected: + RankLayer(const char* name); + ~RankLayer() = default; +}; + +} //namespace armnn + + diff --git a/src/armnn/test/TestNameOnlyLayerVisitor.cpp b/src/armnn/test/TestNameOnlyLayerVisitor.cpp index 945afa8ff5..994375d435 100644 --- a/src/armnn/test/TestNameOnlyLayerVisitor.cpp +++ b/src/armnn/test/TestNameOnlyLayerVisitor.cpp @@ -48,6 +48,7 @@ TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Minimum) TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Multiplication) TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Prelu) TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Quantize) +TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Rank) TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Subtraction) TEST_SUITE_NAME_ONLY_LAYER_VISITOR(Switch) diff --git a/src/armnn/test/TestNameOnlyLayerVisitor.hpp b/src/armnn/test/TestNameOnlyLayerVisitor.hpp index 0e1ea8eac7..519cbbacc6 100644 --- a/src/armnn/test/TestNameOnlyLayerVisitor.hpp +++ b/src/armnn/test/TestNameOnlyLayerVisitor.hpp @@ -35,5 +35,6 @@ DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Minimum) DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Multiplication) DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Prelu) DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Quantize) +DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Rank) DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Subtraction) DECLARE_TEST_NAME_ONLY_LAYER_VISITOR_CLASS(Switch) diff --git a/src/armnnDeserializer/Deserializer.cpp b/src/armnnDeserializer/Deserializer.cpp index 31fae2af86..7143cdbdcc 100644 --- a/src/armnnDeserializer/Deserializer.cpp +++ b/src/armnnDeserializer/Deserializer.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -225,6 +225,7 @@ m_ParserFunctions(Layer_MAX+1, &Deserializer::ParseUnsupportedLayer) m_ParserFunctions[Layer_QLstmLayer] = &Deserializer::ParseQLstm; m_ParserFunctions[Layer_QuantizeLayer] = &Deserializer::ParseQuantize; m_ParserFunctions[Layer_QuantizedLstmLayer] = &Deserializer::ParseQuantizedLstm; + m_ParserFunctions[Layer_RankLayer] = &Deserializer::ParseRank; m_ParserFunctions[Layer_ReshapeLayer] = &Deserializer::ParseReshape; m_ParserFunctions[Layer_ResizeBilinearLayer] = &Deserializer::ParseResizeBilinear; m_ParserFunctions[Layer_ResizeLayer] = &Deserializer::ParseResize; @@ -331,6 +332,8 @@ Deserializer::LayerBaseRawPtr Deserializer::GetBaseLayer(const GraphPtr& graphPt return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizeLayer()->base(); case Layer::Layer_QuantizedLstmLayer: return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer()->base(); + case Layer::Layer_RankLayer: + return graphPtr->layers()->Get(layerIndex)->layer_as_RankLayer()->base(); case Layer::Layer_ReshapeLayer: return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base(); case Layer::Layer_ResizeBilinearLayer: @@ -545,6 +548,16 @@ armnn::TensorInfo ToTensorInfo(Deserializer::TensorRawPtr tensorPtr) } } + if (tensorPtr->dimensionality() == static_cast(Dimensionality::Scalar)) + { + float quantizationScale = tensorPtr->quantizationScale(); + int32_t quantizationOffset = tensorPtr->quantizationOffset(); + + return armnn::TensorInfo(armnn::TensorShape{armnn::Dimensionality::Scalar}, + type, + quantizationScale, + quantizationOffset); + } auto dimensions = tensorPtr->dimensions(); unsigned int size = dimensions->size(); @@ -2008,6 +2021,26 @@ armnn::TensorInfo Deserializer::OutputShapeOfReshape(const armnn::TensorInfo& in return reshapeInfo; } +void Deserializer::ParseRank(GraphPtr graph, unsigned int layerIndex) +{ + CHECK_LAYERS(graph, 0, layerIndex); + + Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex); + CHECK_VALID_SIZE(inputs.size(), 1); + + Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex); + CHECK_VALID_SIZE(outputs.size(), 1); + + auto layerName = GetLayerName(graph, layerIndex); + IConnectableLayer* layer = m_Network->AddRankLayer( layerName.c_str()); + + armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]); + layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + + RegisterInputSlots(graph, layerIndex, layer); + RegisterOutputSlots(graph, layerIndex, layer); +} + void Deserializer::ParseReshape(GraphPtr graph, unsigned int layerIndex) { CHECK_LAYERS(graph, 0, layerIndex); diff --git a/src/armnnDeserializer/Deserializer.hpp b/src/armnnDeserializer/Deserializer.hpp index 69868c210a..4a1bdad8a8 100644 --- a/src/armnnDeserializer/Deserializer.hpp +++ b/src/armnnDeserializer/Deserializer.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -118,6 +118,7 @@ private: void ParsePrelu(GraphPtr graph, unsigned int layerIndex); void ParseQLstm(GraphPtr graph, unsigned int layerIndex); void ParseQuantize(GraphPtr graph, unsigned int layerIndex); + void ParseRank(GraphPtr graph, unsigned int layerIndex); void ParseReshape(GraphPtr graph, unsigned int layerIndex); void ParseResize(GraphPtr graph, unsigned int layerIndex); void ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex); diff --git a/src/armnnDeserializer/DeserializerSupport.md b/src/armnnDeserializer/DeserializerSupport.md index b4982ec78a..4e2ead41bc 100644 --- a/src/armnnDeserializer/DeserializerSupport.md +++ b/src/armnnDeserializer/DeserializerSupport.md @@ -45,6 +45,7 @@ The Arm NN SDK Deserialize parser currently supports the following layers: * Quantize * QLstm * QuantizedLstm +* Rank * Reshape * Resize * ResizeBilinear diff --git a/src/armnnDeserializer/test/DeserializeRank.cpp b/src/armnnDeserializer/test/DeserializeRank.cpp new file mode 100644 index 0000000000..8f14af150b --- /dev/null +++ b/src/armnnDeserializer/test/DeserializeRank.cpp @@ -0,0 +1,151 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include +#include "ParserFlatbuffersSerializeFixture.hpp" +#include "../Deserializer.hpp" + +#include + +BOOST_AUTO_TEST_SUITE(Deserializer) + +struct RankFixture : public ParserFlatbuffersSerializeFixture +{ + explicit RankFixture(const std::string &inputShape, + const std::string &dataType) + { + m_JsonString = R"( + { + inputIds: [0], + outputIds: [2], + layers: [ + { + layer_type: "InputLayer", + layer: { + base: { + base: { + layerName: "", + layerType: "Input", + inputSlots: [ + + ], + outputSlots: [ + { + tensorInfo: { + dimensions: )" + inputShape + R"(, + dataType: )" + dataType + R"(, + quantizationScale: 0.0 + } + } + ] + } + } + } + }, + { + layer_type: "RankLayer", + layer: { + base: { + index: 1, + layerName: "rank", + layerType: "Rank", + inputSlots: [ + { + connection: { + sourceLayerIndex: 0, + outputSlotIndex: 0 + } + } + ], + outputSlots: [ + { + tensorInfo: { + dimensions: [ 1 ], + dataType: "Signed32", + quantizationScale: 0.0, + dimensionality: 2 + } + } + ] + } + } + }, + { + layer_type: "OutputLayer", + layer: { + base: { + base: { + index: 2, + layerName: "", + layerType: "Output", + inputSlots: [ + { + connection: { + sourceLayerIndex: 1, + outputSlotIndex: 0 + } + } + ], + outputSlots: [] + } + } + } + } + ], + } + )"; + Setup(); + } +}; + +struct SimpleRankDimSize1Fixture : RankFixture +{ + SimpleRankDimSize1Fixture() : RankFixture("[ 8 ]", "QSymmS16") {} +}; + +struct SimpleRankDimSize2Fixture : RankFixture +{ + SimpleRankDimSize2Fixture() : RankFixture("[ 3, 3 ]", "QSymmS8") {} +}; + +struct SimpleRankDimSize3Fixture : RankFixture +{ + SimpleRankDimSize3Fixture() : RankFixture("[ 2, 2, 1 ]", "Signed32") {} +}; + +struct SimpleRankDimSize4Fixture : RankFixture +{ + SimpleRankDimSize4Fixture() : RankFixture("[ 2, 2, 1, 1 ]", "Float32") {} +}; + +BOOST_FIXTURE_TEST_CASE(RankDimSize1Float16, SimpleRankDimSize1Fixture) +{ + RunTest<1, armnn::DataType::QSymmS16, armnn::DataType::Signed32>( 0, + { 1, 2, 3, 4, 5, 6, 7, 8 }, + { 1 }); +} + +BOOST_FIXTURE_TEST_CASE(RankDimSize2QAsymmU8, SimpleRankDimSize2Fixture) +{ + RunTest<1, armnn::DataType::QSymmS8, armnn::DataType::Signed32>( 0, + { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + { 2 }); +} + +BOOST_FIXTURE_TEST_CASE(RankDimSize3Signed32, SimpleRankDimSize3Fixture) +{ + RunTest<1, armnn::DataType::Signed32, armnn::DataType::Signed32>( 0, + { 111, 85, 226, 3 }, + { 3 }); +} + +BOOST_FIXTURE_TEST_CASE(RankDimSize4Float32, SimpleRankDimSize4Fixture) +{ + RunTest<1, armnn::DataType::Float32, armnn::DataType::Signed32>( 0, + { 111, 85, 226, 3 }, + { 4 }); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/armnnSerializer/ArmnnSchema.fbs b/src/armnnSerializer/ArmnnSchema.fbs index 6a388db699..e1b6e1f768 100644 --- a/src/armnnSerializer/ArmnnSchema.fbs +++ b/src/armnnSerializer/ArmnnSchema.fbs @@ -59,6 +59,7 @@ table TensorInfo { quantizationOffset:int = 0; quantizationScales:[float]; quantizationDim:uint; + dimensionality:uint = 1; } struct Connection { @@ -157,7 +158,8 @@ enum LayerType : uint { ElementwiseUnary = 54, Transpose = 55, QLstm = 56, - Fill = 57 + Fill = 57, + Rank = 58 } // Base layer table to be used as part of other layers @@ -859,6 +861,10 @@ table StandInLayer { descriptor:StandInDescriptor; } +table RankLayer { + base:LayerBase; +} + union Layer { ActivationLayer, AdditionLayer, @@ -917,7 +923,8 @@ union Layer { ElementwiseUnaryLayer, TransposeLayer, QLstmLayer, - FillLayer + FillLayer, + RankLayer } table AnyLayer { diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp index 6555a34be7..8a1f7716a1 100644 --- a/src/armnnSerializer/Serializer.cpp +++ b/src/armnnSerializer/Serializer.cpp @@ -2,7 +2,6 @@ // Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // - #include "Serializer.hpp" #include @@ -851,6 +850,16 @@ void SerializerVisitor::VisitPermuteLayer(const armnn::IConnectableLayer* layer, CreateAnyLayer(flatBufferPermuteLayer.o, serializer::Layer::Layer_PermuteLayer); } +// Build FlatBuffer for Rank Layer +void SerializerVisitor::VisitRankLayer(const armnn::IConnectableLayer* layer, + const char* name) +{ + IgnoreUnused(name); + auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Rank); + auto flatBufferRankLayer = serializer::CreateRankLayer(m_flatBufferBuilder, flatBufferBaseLayer); + + CreateAnyLayer(flatBufferRankLayer.o, serializer::Layer::Layer_RankLayer); +} // Build FlatBuffer for Reshape Layer void SerializerVisitor::VisitReshapeLayer(const armnn::IConnectableLayer* layer, const armnn::ReshapeDescriptor& reshapeDescriptor, @@ -1584,7 +1593,9 @@ flatbuffers::Offset SerializerVisitor::CreateTensorInfo(const armnn tensorInfo.GetQuantizationScales()[0], tensorInfo.GetQuantizationOffset(), m_flatBufferBuilder.CreateVector(tensorInfo.GetQuantizationScales()), - tensorInfo.GetQuantizationDim().value()); + tensorInfo.GetQuantizationDim().value(), + static_cast + (tensorInfo.GetShape().GetDimensionality())); return flatBufferTensorInfo; } @@ -1593,7 +1604,11 @@ flatbuffers::Offset SerializerVisitor::CreateTensorInfo(const armnn m_flatBufferBuilder.CreateVector(shape), GetFlatBufferDataType(tensorInfo.GetDataType()), tensorInfo.GetQuantizationScale(), - tensorInfo.GetQuantizationOffset()); + tensorInfo.GetQuantizationOffset(), + 0, + 0, + static_cast + (tensorInfo.GetShape().GetDimensionality())); return flatBufferTensorInfo; } @@ -1742,4 +1757,4 @@ bool Serializer::SaveSerializedToStream(std::ostream& stream) return !stream.bad(); } -} // namespace armnnSerializer \ No newline at end of file +} // namespace armnnSerializer diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp index e4104dda8e..babecdc056 100644 --- a/src/armnnSerializer/Serializer.hpp +++ b/src/armnnSerializer/Serializer.hpp @@ -219,6 +219,9 @@ public: const armnn::QuantizedLstmInputParams& params, const char* name = nullptr) override; + void VisitRankLayer(const armnn::IConnectableLayer* layer, + const char* name = nullptr) override; + void VisitReshapeLayer(const armnn::IConnectableLayer* layer, const armnn::ReshapeDescriptor& reshapeDescriptor, const char* name = nullptr) override; diff --git a/src/armnnSerializer/SerializerSupport.md b/src/armnnSerializer/SerializerSupport.md index 4f7868bee7..438335341a 100644 --- a/src/armnnSerializer/SerializerSupport.md +++ b/src/armnnSerializer/SerializerSupport.md @@ -44,6 +44,7 @@ The Arm NN SDK Serializer currently supports the following layers: * QLstm * Quantize * QuantizedLstm +* Rank * Reshape * Resize * Slice diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp index 088282a18a..e059511fc2 100644 --- a/src/armnnSerializer/test/SerializerTests.cpp +++ b/src/armnnSerializer/test/SerializerTests.cpp @@ -2202,6 +2202,32 @@ BOOST_AUTO_TEST_CASE(SerializeQuantize) deserializedNetwork->Accept(verifier); } +BOOST_AUTO_TEST_CASE(SerializeRank) +{ + DECLARE_LAYER_VERIFIER_CLASS(Rank) + + const std::string layerName("rank"); + const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({1}, armnn::DataType::Signed32); + + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const rankLayer = network->AddRankLayer(layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); + + inputLayer->GetOutputSlot(0).Connect(rankLayer->GetInputSlot(0)); + rankLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + rankLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); + BOOST_CHECK(deserializedNetwork); + + RankLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}); + deserializedNetwork->Accept(verifier); +} + BOOST_AUTO_TEST_CASE(SerializeReshape) { DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Reshape) diff --git a/src/backends/backendsCommon/LayerSupportBase.cpp b/src/backends/backendsCommon/LayerSupportBase.cpp index 52e615a2d9..92c1023583 100644 --- a/src/backends/backendsCommon/LayerSupportBase.cpp +++ b/src/backends/backendsCommon/LayerSupportBase.cpp @@ -488,6 +488,13 @@ bool LayerSupportBase::IsQuantizedLstmSupported(const TensorInfo&, // input return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); } +bool LayerSupportBase::IsRankSupported(const TensorInfo&, // input + const TensorInfo&, // output + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + bool LayerSupportBase::IsReshapeSupported(const TensorInfo&, // input const TensorInfo&, // output const ReshapeDescriptor&, // descriptor diff --git a/src/backends/backendsCommon/LayerSupportBase.hpp b/src/backends/backendsCommon/LayerSupportBase.hpp index 8d5535ab4e..13fd39ea2e 100644 --- a/src/backends/backendsCommon/LayerSupportBase.hpp +++ b/src/backends/backendsCommon/LayerSupportBase.hpp @@ -300,6 +300,10 @@ public: const QuantizedLstmInputParamsInfo& paramsInfo, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsRankSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported) const override; + bool IsReshapeSupported(const TensorInfo& input, const TensorInfo& output, const ReshapeDescriptor& descriptor, diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index 3949fa945d..c7650dc58d 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -3515,4 +3515,33 @@ void ElementwiseUnaryQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output"); } +void RankQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const +{ + const std::string descriptorName{"RankQueueDescriptor"}; + + ValidateNumInputs(workloadInfo, descriptorName, 1); + ValidateNumOutputs(workloadInfo, descriptorName, 1); + + const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0]; + const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0]; + + ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output"); + ValidateTensorNumElements(outputTensorInfo, descriptorName, 1, "output"); + + std::vector supportedTypes = + { + DataType::BFloat16, + DataType::Float16, + DataType::Float32, + DataType::QAsymmS8, + DataType::QAsymmU8, + DataType::QSymmS8, + DataType::QSymmS16, + DataType::Signed32 + }; + + ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName); + ValidateDataTypes(outputTensorInfo, { DataType::Signed32 }, descriptorName); +} + } // namespace armnn diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp index 6b2c00e298..1f54f9aaed 100644 --- a/src/backends/backendsCommon/WorkloadData.hpp +++ b/src/backends/backendsCommon/WorkloadData.hpp @@ -290,6 +290,11 @@ struct BatchNormalizationQueueDescriptor : QueueDescriptorWithParameters { void Validate(const WorkloadInfo& workloadInfo) const; diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp index 788cb7e712..09d7c2d568 100644 --- a/src/backends/backendsCommon/WorkloadFactory.cpp +++ b/src/backends/backendsCommon/WorkloadFactory.cpp @@ -13,15 +13,12 @@ #include #include -#include #include -#include #include #include -#include #include namespace armnn @@ -924,6 +921,15 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, reason); break; } + case LayerType::Rank: + { + const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo(); + const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo(); + result = layerSupportObject->IsRankSupported(OverrideDataType(input, dataType), + OverrideDataType(output, dataType), + reason); + break; + } case LayerType::Reshape: { auto cLayer = PolymorphicDowncast(&layer); @@ -1515,6 +1521,11 @@ std::unique_ptr IWorkloadFactory::CreateQuantizedLstm(const Quantized { return std::unique_ptr(); } +std::unique_ptr IWorkloadFactory::CreateRank(const RankQueueDescriptor& /*descriptor*/, + const WorkloadInfo& /*info*/) const +{ + return std::unique_ptr(); +} std::unique_ptr IWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& /*descriptor*/, const WorkloadInfo& /*info*/) const diff --git a/src/backends/backendsCommon/WorkloadFactory.hpp b/src/backends/backendsCommon/WorkloadFactory.hpp index e373a4f218..04b895e882 100644 --- a/src/backends/backendsCommon/WorkloadFactory.hpp +++ b/src/backends/backendsCommon/WorkloadFactory.hpp @@ -206,6 +206,9 @@ public: virtual std::unique_ptr CreateQuantizedLstm(const QuantizedLstmQueueDescriptor& descriptor, const WorkloadInfo& info) const; + virtual std::unique_ptr CreateRank(const RankQueueDescriptor& descriptor, + const WorkloadInfo& info) const; + virtual std::unique_ptr CreateReshape(const ReshapeQueueDescriptor& descriptor, const WorkloadInfo& info) const; diff --git a/src/backends/backendsCommon/WorkloadFactoryBase.hpp b/src/backends/backendsCommon/WorkloadFactoryBase.hpp index 960dbd3413..bfdb5e9b33 100644 --- a/src/backends/backendsCommon/WorkloadFactoryBase.hpp +++ b/src/backends/backendsCommon/WorkloadFactoryBase.hpp @@ -218,6 +218,10 @@ public: const WorkloadInfo& /*info*/) const override { return nullptr; } + std::unique_ptr CreateRank(const RankQueueDescriptor& /*descriptor*/, + const WorkloadInfo& /*info*/) const override + { return nullptr; } + std::unique_ptr CreateReshape(const ReshapeQueueDescriptor& /*descriptor*/, const WorkloadInfo& /*info*/) const override { return nullptr; } diff --git a/src/backends/backendsCommon/common.mk b/src/backends/backendsCommon/common.mk index c31b1f07a4..7829abbbb9 100644 --- a/src/backends/backendsCommon/common.mk +++ b/src/backends/backendsCommon/common.mk @@ -71,6 +71,7 @@ COMMON_TEST_SOURCES := \ test/layerTests/NormalizationTestImpl.cpp \ test/layerTests/PadTestImpl.cpp \ test/layerTests/Pooling2dTestImpl.cpp \ + test/layerTests/RankTestImpl.cpp \ test/layerTests/ReshapeTestImpl.cpp \ test/layerTests/ResizeTestImpl.cpp \ test/layerTests/RsqrtTestImpl.cpp \ diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt index 0ce529906f..8373c28cd3 100644 --- a/src/backends/backendsCommon/test/CMakeLists.txt +++ b/src/backends/backendsCommon/test/CMakeLists.txt @@ -131,6 +131,8 @@ list(APPEND armnnBackendsCommonUnitTests_sources layerTests/PreluTestImpl.hpp layerTests/QuantizeTestImpl.cpp layerTests/QuantizeTestImpl.hpp + layerTests/RankTestImpl.cpp + layerTests/RankTestImpl.hpp layerTests/ReshapeTestImpl.cpp layerTests/ReshapeTestImpl.hpp layerTests/ResizeTestImpl.cpp diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp index e30cbb3d31..ed4b6ff09a 100644 --- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp +++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp @@ -595,6 +595,8 @@ DECLARE_LAYER_POLICY_1_PARAM(QuantizedLstm) DECLARE_LAYER_POLICY_1_PARAM(Division) +DECLARE_LAYER_POLICY_1_PARAM(Rank) + DECLARE_LAYER_POLICY_2_PARAM(Resize) DECLARE_LAYER_POLICY_2_PARAM(Reshape) diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 7e8b301b54..a4615914d3 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/src/backends/backendsCommon/test/layerTests/RankTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/RankTestImpl.cpp new file mode 100644 index 0000000000..82de11ae21 --- /dev/null +++ b/src/backends/backendsCommon/test/layerTests/RankTestImpl.cpp @@ -0,0 +1,262 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RankTestImpl.hpp" + +#include +#include +#include + +#include + +template +LayerTestResult RankTest( + armnn::TensorInfo inputTensorInfo, + boost::multi_array input, + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + IgnoreUnused(memoryManager); + + const armnn::TensorShape outputShape{armnn::Dimensionality::Scalar}; + armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Signed32); + + LayerTestResult ret(outputTensorInfo); + ret.outputExpected = MakeTensor(outputTensorInfo, { n }); + + std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); + + armnn::RankQueueDescriptor data; + armnn::WorkloadInfo info; + AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + + std::unique_ptr workload = workloadFactory.CreateRank(data, info); + + inputHandle->Allocate(); + outputHandle->Allocate(); + + CopyDataToITensorHandle(inputHandle.get(), input.origin()); + + workload->Execute(); + + CopyDataFromITensorHandle(&ret.output[0], outputHandle.get()); + + return ret; +} + +template +LayerTestResult RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorInfo inputTensorInfo({6}, ArmnnType, 1.0f, 0); + auto input = MakeTensor(inputTensorInfo, ConvertToDataType( + { -37.5f, -15.2f, -8.76f, -2.0f, -1.3f, -0.5f }, + inputTensorInfo)); + + return RankTest(inputTensorInfo, input, workloadFactory, memoryManager); +} + +template +LayerTestResult RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorInfo inputTensorInfo({1, 3}, ArmnnType, 1.0f, 0); + auto input = MakeTensor(inputTensorInfo, ConvertToDataType( + { -37.5f, -15.2f, -8.76f }, + inputTensorInfo)); + + return RankTest(inputTensorInfo, input, workloadFactory, memoryManager); +} + +template +LayerTestResult RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorInfo inputTensorInfo({1, 3, 2}, ArmnnType, 1.0f, 0); + auto input = MakeTensor(inputTensorInfo, ConvertToDataType( + { -37.5f, -15.2f, -8.76f, -2.0f, -1.5f, -1.3f}, + inputTensorInfo)); + + return RankTest(inputTensorInfo, input, workloadFactory, memoryManager); +} + +template +LayerTestResult RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorInfo inputTensorInfo({1, 3, 2, 3}, ArmnnType, 1.0f, 0); + auto input = MakeTensor(inputTensorInfo, ConvertToDataType( + { -37.5f, -15.2f, -8.76f, -2.0f, -1.5f, -1.3f, -0.5f, -0.4f, 0.0f, + 1.0f, 0.4f, 0.5f, 1.3f, 1.5f, 2.0f, 8.76f, 15.2f, 37.5f }, + inputTensorInfo)); + + return RankTest(inputTensorInfo, input, workloadFactory, memoryManager); +} + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template LayerTestResult +RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); \ No newline at end of file diff --git a/src/backends/backendsCommon/test/layerTests/RankTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/RankTestImpl.hpp new file mode 100644 index 0000000000..ac82ac949d --- /dev/null +++ b/src/backends/backendsCommon/test/layerTests/RankTestImpl.hpp @@ -0,0 +1,40 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "LayerTestResult.hpp" + +#include + +#include +#include + +template +LayerTestResult RankTest( + armnn::TensorInfo inputTensorInfo, + boost::multi_array input, + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template> +LayerTestResult RankDimSize1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template> +LayerTestResult RankDimSize2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template> +LayerTestResult RankDimSize3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +template> +LayerTestResult RankDimSize4Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index 696c6d9dac..877d200208 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -1651,6 +1651,21 @@ bool RefLayerSupport::IsQuantizeSupported(const TensorInfo& input, return supported; } +bool RefLayerSupport::IsRankSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + IgnoreUnused(input); + // Define supported output types. + std::array supportedOutputTypes = + { + DataType::Signed32, + }; + + return CheckSupportRule(TypeAnyOf(output, supportedOutputTypes), reasonIfUnsupported, + "Reference rank: input type not supported."); +} + bool RefLayerSupport::IsReshapeSupported(const TensorInfo& input, const TensorInfo& output, const ReshapeDescriptor& descriptor, diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp index 7d2bbf240e..a233082aaa 100644 --- a/src/backends/reference/RefLayerSupport.hpp +++ b/src/backends/reference/RefLayerSupport.hpp @@ -265,6 +265,10 @@ public: const LstmInputParamsInfo& paramsInfo, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsRankSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsReshapeSupported(const TensorInfo& input, const TensorInfo& output, const ReshapeDescriptor& descriptor, diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index dcdabe17ff..cac1d1bd8a 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -549,6 +549,12 @@ std::unique_ptr RefWorkloadFactory::CreateQuantize(const QuantizeQueu return std::make_unique(descriptor, info); } +std::unique_ptr RefWorkloadFactory::CreateRank(const RankQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return std::make_unique(descriptor, info); +} + std::unique_ptr RefWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor, const WorkloadInfo& info) const { diff --git a/src/backends/reference/RefWorkloadFactory.hpp b/src/backends/reference/RefWorkloadFactory.hpp index 941f1a6636..e2eab072e3 100644 --- a/src/backends/reference/RefWorkloadFactory.hpp +++ b/src/backends/reference/RefWorkloadFactory.hpp @@ -209,6 +209,9 @@ public: std::unique_ptr CreateQuantize(const QuantizeQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + std::unique_ptr CreateRank(const RankQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + std::unique_ptr CreateReshape(const ReshapeQueueDescriptor& descriptor, const WorkloadInfo& info) const override; diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index d96fa8be59..53df9a36b3 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -9,7 +9,6 @@ #include -#include #include #include @@ -797,6 +796,43 @@ ARMNN_AUTO_TEST_CASE(BatchNormUint8Nhwc, BatchNormUint8NhwcTest) ARMNN_AUTO_TEST_CASE(BatchNormInt16, BatchNormInt16Test) ARMNN_AUTO_TEST_CASE(BatchNormInt16Nhwc, BatchNormInt16NhwcTest) +// Rank +ARMNN_AUTO_TEST_CASE(RankDimSize1Float16, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1Float32, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1QAsymmU8, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1Signed32, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1QSymmS16, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1QSymmS8, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1QAsymmS8, RankDimSize1Test) +ARMNN_AUTO_TEST_CASE(RankDimSize1BFloat16, RankDimSize1Test) + +ARMNN_AUTO_TEST_CASE(RankDimSize2Float16, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2Float32, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2QAsymmU8, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2Signed32, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2QSymmS16, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2QSymmS8, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2QAsymmS8, RankDimSize2Test) +ARMNN_AUTO_TEST_CASE(RankDimSize2BFloat16, RankDimSize2Test) + +ARMNN_AUTO_TEST_CASE(RankDimSize3Float16, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3Float32, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3QAsymmU8, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3Signed32, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3QSymmS16, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3QSymmS8, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3QAsymmS8, RankDimSize3Test) +ARMNN_AUTO_TEST_CASE(RankDimSize3BFloat16, RankDimSize3Test) + +ARMNN_AUTO_TEST_CASE(RankDimSize4Float16, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4Float32, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4QAsymmU8, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4Signed32, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4QSymmS16, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4QSymmS8, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4QAsymmS8, RankDimSize4Test) +ARMNN_AUTO_TEST_CASE(RankDimSize4BFloat16, RankDimSize4Test) + // Resize Bilinear - NCHW ARMNN_AUTO_TEST_CASE(SimpleResizeBilinear, SimpleResizeBilinearTest, diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index d51db365cc..937a32029e 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright © 2017 Arm Ltd. All rights reserved. +# Copyright © 2017 Arm Ltd and Contributors. All rights reserved. # SPDX-License-Identifier: MIT # @@ -129,6 +129,7 @@ list(APPEND armnnRefBackendWorkloads_sources RefQuantizeWorkload.hpp RefQLstmWorkload.cpp RefQLstmWorkload.hpp + RefRankWorkload.hpp RefReshapeWorkload.cpp RefReshapeWorkload.hpp RefResizeBilinearWorkload.cpp diff --git a/src/backends/reference/workloads/RefRankWorkload.hpp b/src/backends/reference/workloads/RefRankWorkload.hpp new file mode 100644 index 0000000000..780d3be533 --- /dev/null +++ b/src/backends/reference/workloads/RefRankWorkload.hpp @@ -0,0 +1,32 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +#include "RefWorkloadUtils.hpp" + +namespace armnn +{ + +struct RefRankWorkload : public BaseWorkload +{ +public: + using BaseWorkload::BaseWorkload; + virtual void Execute() const override + { + const int32_t rank = static_cast(GetTensorInfo(m_Data.m_Inputs[0]).GetNumDimensions()); + + std::memcpy(GetOutputTensorData(0, m_Data), &rank, sizeof(int32_t)); + } +}; + +} //namespace armnn + + + + diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 951e3a1e29..fc47cff84f 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -51,6 +51,7 @@ #include "RefPreluWorkload.hpp" #include "RefQLstmWorkload.hpp" #include "RefQuantizeWorkload.hpp" +#include "RefRankWorkload.hpp" #include "RefReshapeWorkload.hpp" #include "RefResizeBilinearWorkload.hpp" #include "RefResizeWorkload.hpp" -- cgit v1.2.1