diff options
Diffstat (limited to 'src/armnnSerializer')
-rw-r--r-- | src/armnnSerializer/ArmnnSchema.fbs | 16 | ||||
-rw-r--r-- | src/armnnSerializer/Serializer.cpp | 65 | ||||
-rw-r--r-- | src/armnnSerializer/Serializer.hpp | 4 | ||||
-rw-r--r-- | src/armnnSerializer/SerializerSupport.md | 1 | ||||
-rw-r--r-- | src/armnnSerializer/test/SerializerTests.cpp | 79 |
5 files changed, 161 insertions, 4 deletions
diff --git a/src/armnnSerializer/ArmnnSchema.fbs b/src/armnnSerializer/ArmnnSchema.fbs index 36389b780b..40ee7a5e45 100644 --- a/src/armnnSerializer/ArmnnSchema.fbs +++ b/src/armnnSerializer/ArmnnSchema.fbs @@ -112,7 +112,8 @@ enum LayerType : uint { Gather = 28, Mean = 29, Merger = 30, - L2Normalization = 31 + L2Normalization = 31, + Splitter = 32 } // Base layer table to be used as part of other layers @@ -442,6 +443,16 @@ table OriginsDescriptor { viewOrigins:[UintVector]; } +table ViewsDescriptor { + origins:OriginsDescriptor; + viewSizes:[UintVector]; +} + +table SplitterLayer { + base:LayerBase; + descriptor:ViewsDescriptor; +} + union Layer { ActivationLayer, AdditionLayer, @@ -474,7 +485,8 @@ union Layer { GatherLayer, MeanLayer, MergerLayer, - L2NormalizationLayer + L2NormalizationLayer, + SplitterLayer } table AnyLayer { diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp index eaf19d52b5..3774c250e1 100644 --- a/src/armnnSerializer/Serializer.cpp +++ b/src/armnnSerializer/Serializer.cpp @@ -634,6 +634,71 @@ void SerializerVisitor::VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_SpaceToBatchNdLayer); } +// Build FlatBuffer for Splitter Layer +void SerializerVisitor::VisitSplitterLayer(const armnn::IConnectableLayer* layer, + const armnn::ViewsDescriptor& viewsDescriptor, + const char* name) +{ + // Create FlatBuffer ViewOrigins + std::vector<flatbuffers::Offset<UintVector>> flatBufferViewOrigins; + flatBufferViewOrigins.reserve(viewsDescriptor.GetNumViews()); + + for(unsigned int vIdx = 0; vIdx < viewsDescriptor.GetNumViews(); ++vIdx) + { + std::vector<uint32_t> viewOrigin; + viewOrigin.reserve(viewsDescriptor.GetNumDimensions()); + + // Copy vector + for(unsigned int dIdx = 0; dIdx < viewsDescriptor.GetNumDimensions(); ++dIdx) + { + viewOrigin.push_back(viewsDescriptor.GetViewOrigin(vIdx)[dIdx]); + } + + flatBufferViewOrigins.push_back(CreateUintVector(m_flatBufferBuilder, + m_flatBufferBuilder.CreateVector(viewOrigin))); + } + + // Create FlatBuffer OriginsDescriptor + auto flatBufferOriginDescriptor = CreateOriginsDescriptor(m_flatBufferBuilder, + viewsDescriptor.GetOrigins().GetConcatAxis(), + viewsDescriptor.GetOrigins().GetNumViews(), + viewsDescriptor.GetOrigins().GetNumDimensions(), + m_flatBufferBuilder.CreateVector(flatBufferViewOrigins)); + + // Create FlatBuffer ViewOrigins + std::vector<flatbuffers::Offset<UintVector>> flatBufferViewSizes; + flatBufferViewSizes.reserve(viewsDescriptor.GetNumViews()); + + for(unsigned int vIdx = 0; vIdx < viewsDescriptor.GetNumViews(); ++vIdx) + { + std::vector<uint32_t> viewSize; + viewSize.reserve(viewsDescriptor.GetNumDimensions()); + + // Copy vector + for(unsigned int dIdx = 0; dIdx < viewsDescriptor.GetNumDimensions(); ++dIdx) + { + viewSize.push_back(viewsDescriptor.GetViewSizes(vIdx)[dIdx]); + } + + flatBufferViewSizes.push_back(CreateUintVector(m_flatBufferBuilder, + m_flatBufferBuilder.CreateVector(viewSize))); + } + + // Create FlatBuffer ViewsDescriptor + auto flatBufferViewsDescriptor = CreateViewsDescriptor(m_flatBufferBuilder, + flatBufferOriginDescriptor, + m_flatBufferBuilder.CreateVector(flatBufferViewSizes)); + + // Create FlatBuffer BaseLayer + auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Splitter); + + auto flatBufferSplitterLayer = serializer::CreateSplitterLayer(m_flatBufferBuilder, + flatBufferBaseLayer, + flatBufferViewsDescriptor); + + CreateAnyLayer(flatBufferSplitterLayer.o, serializer::Layer::Layer_SplitterLayer); +} + void SerializerVisitor::VisitNormalizationLayer(const armnn::IConnectableLayer* layer, const armnn::NormalizationDescriptor& descriptor, const char* name) diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp index c0e70c982c..cb05792863 100644 --- a/src/armnnSerializer/Serializer.hpp +++ b/src/armnnSerializer/Serializer.hpp @@ -162,6 +162,10 @@ public: const armnn::NormalizationDescriptor& normalizationDescriptor, const char* name = nullptr) override; + void VisitSplitterLayer(const armnn::IConnectableLayer* layer, + const armnn::ViewsDescriptor& viewsDescriptor, + const char* name = nullptr) override; + void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer, const armnn::StridedSliceDescriptor& stridedSliceDescriptor, const char* name = nullptr) override; diff --git a/src/armnnSerializer/SerializerSupport.md b/src/armnnSerializer/SerializerSupport.md index d557756810..81d2faa8fe 100644 --- a/src/armnnSerializer/SerializerSupport.md +++ b/src/armnnSerializer/SerializerSupport.md @@ -34,6 +34,7 @@ The Arm NN SDK Serializer currently supports the following layers: * Rsqrt * Softmax * SpaceToBatchNd +* Splitter * StridedSlice * Subtraction diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp index 069b9d699c..41f5d14ce3 100644 --- a/src/armnnSerializer/test/SerializerTests.cpp +++ b/src/armnnSerializer/test/SerializerTests.cpp @@ -473,8 +473,8 @@ BOOST_AUTO_TEST_CASE(SerializeDeserializeL2Normalization) VerifyL2NormalizationName nameChecker(l2NormLayerName); deserializedNetwork->Accept(nameChecker); - CheckDeserializedNetworkAgainstOriginal<float>(*network, - *deserializedNetwork, + CheckDeserializedNetworkAgainstOriginal<float>(*deserializedNetwork, + *network, { info.GetShape() }, { info.GetShape() }); } @@ -1520,4 +1520,79 @@ BOOST_AUTO_TEST_CASE(SerializeDeserializeMerger) {0, 1}); } +BOOST_AUTO_TEST_CASE(SerializeDeserializeSplitter) +{ + class VerifySplitterName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy> + { + public: + void VisitSplitterLayer(const armnn::IConnectableLayer*, + const armnn::ViewsDescriptor& viewsDescriptor, + const char* name) override + { + BOOST_TEST(name == "splitter"); + } + }; + + unsigned int numViews = 3; + unsigned int numDimensions = 4; + unsigned int inputShape[] = {1,18, 4, 4}; + unsigned int outputShape[] = {1, 6, 4, 4}; + + auto inputTensorInfo = armnn::TensorInfo(numDimensions, inputShape, armnn::DataType::Float32); + auto outputTensorInfo = armnn::TensorInfo(numDimensions, outputShape, armnn::DataType::Float32); + + // This is modelled on how the caffe parser sets up a splitter layer to partition an input + // along dimension one. + unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]), + static_cast<unsigned int>(inputShape[1]), + static_cast<unsigned int>(inputShape[2]), + static_cast<unsigned int>(inputShape[3])}; + splitterDimSizes[1] /= numViews; + armnn::ViewsDescriptor desc(numViews, numDimensions); + + for (unsigned int g = 0; g < numViews; ++g) + { + desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g); + + // Set the size of the views. + for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++) + { + desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]); + } + } + + const char* splitterLayerName = "splitter"; + + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, splitterLayerName); + armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0); + armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1); + armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2); + + inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); + splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0)); + splitterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0)); + splitterLayer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo); + splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0)); + splitterLayer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo); + + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); + BOOST_CHECK(deserializedNetwork); + + VerifySplitterName nameChecker; + deserializedNetwork->Accept(nameChecker); + + CheckDeserializedNetworkAgainstOriginal<float>(*deserializedNetwork, + *network, + {inputTensorInfo.GetShape()}, + {outputTensorInfo.GetShape(), + outputTensorInfo.GetShape(), + outputTensorInfo.GetShape()}, + {0}, + {0, 1, 2}); +} + BOOST_AUTO_TEST_SUITE_END() |