IVGCVSW-4010 Add serialization support for StandInLayer
authorAron Virginas-Tar <Aron.Virginas-Tar@arm.com>
Wed, 23 Oct 2019 09:41:35 +0000 (10:41 +0100)
committerMatteo Martincigh <matteo.martincigh@arm.com>
Wed, 23 Oct 2019 13:19:45 +0000 (13:19 +0000)
Signed-off-by: Aron Virginas-Tar <Aron.Virginas-Tar@arm.com>
Change-Id: I2017c15b485b82437c6ffdac4d3112bcc2cbe9e9

include/armnn/Descriptors.hpp
src/armnn/layers/StandInLayer.cpp
src/armnnDeserializer/Deserializer.cpp
src/armnnDeserializer/Deserializer.hpp
src/armnnDeserializer/DeserializerSupport.md
src/armnnSerializer/ArmnnSchema.fbs
src/armnnSerializer/Serializer.cpp
src/armnnSerializer/SerializerSupport.md
src/armnnSerializer/test/SerializerTests.cpp

index 425c526..ba9a56a 100644 (file)
@@ -962,6 +962,12 @@ struct StandInDescriptor
         , m_NumOutputs(numOutputs)
     {}
 
+    bool operator ==(const StandInDescriptor& rhs) const
+    {
+        return m_NumInputs  == rhs.m_NumInputs &&
+               m_NumOutputs == rhs.m_NumOutputs;
+    }
+
     /// Number of input tensors
     uint32_t m_NumInputs = 0;
     /// Number of output tensors
index fdc905f..7d693bf 100644 (file)
@@ -10,7 +10,7 @@ namespace armnn
 {
 
 StandInLayer::StandInLayer(const StandInDescriptor& param, const char* name)
-    : LayerWithParameters(param.m_NumInputs, 1, LayerType::StandIn, param, name)
+    : LayerWithParameters(param.m_NumInputs, param.m_NumOutputs, LayerType::StandIn, param, name)
 {
 }
 
@@ -42,6 +42,4 @@ void StandInLayer::Accept(ILayerVisitor& visitor) const
 {
     visitor.VisitStandInLayer(this, GetParameters(), GetName());
 }
-} //namespace armnn
-
-
+} // namespace armnn
index 6779f1e..92212b6 100644 (file)
@@ -232,6 +232,7 @@ m_ParserFunctions(Layer_MAX+1, &Deserializer::ParseUnsupportedLayer)
     m_ParserFunctions[Layer_SpaceToDepthLayer]           = &Deserializer::ParseSpaceToDepth;
     m_ParserFunctions[Layer_SplitterLayer]               = &Deserializer::ParseSplitter;
     m_ParserFunctions[Layer_StackLayer]                  = &Deserializer::ParseStack;
+    m_ParserFunctions[Layer_StandInLayer]                = &Deserializer::ParseStandIn;
     m_ParserFunctions[Layer_StridedSliceLayer]           = &Deserializer::ParseStridedSlice;
     m_ParserFunctions[Layer_SubtractionLayer]            = &Deserializer::ParseSubtraction;
     m_ParserFunctions[Layer_SwitchLayer]                 = &Deserializer::ParseSwitch;
@@ -342,6 +343,8 @@ Deserializer::LayerBaseRawPtr Deserializer::GetBaseLayer(const GraphPtr& graphPt
             return graphPtr->layers()->Get(layerIndex)->layer_as_SplitterLayer()->base();
         case Layer::Layer_StackLayer:
             return graphPtr->layers()->Get(layerIndex)->layer_as_StackLayer()->base();
+        case Layer::Layer_StandInLayer:
+            return graphPtr->layers()->Get(layerIndex)->layer_as_StandInLayer()->base();
         case Layer::Layer_StridedSliceLayer:
             return graphPtr->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->base();
         case Layer::Layer_SubtractionLayer:
@@ -2685,4 +2688,34 @@ void Deserializer::ParseStack(GraphPtr graph, unsigned int layerIndex)
     RegisterOutputSlots(graph, layerIndex, layer);
 }
 
+void Deserializer::ParseStandIn(GraphPtr graph, unsigned int layerIndex)
+{
+    CHECK_LAYERS(graph, 0, layerIndex);
+
+    auto inputs  = GetInputs(graph, layerIndex);
+    auto outputs = GetOutputs(graph, layerIndex);
+
+    auto fbLayer      = graph->layers()->Get(layerIndex)->layer_as_StandInLayer();
+    auto fbDescriptor = fbLayer->descriptor();
+
+    armnn::StandInDescriptor descriptor;
+    descriptor.m_NumInputs  = fbDescriptor->numInputs();
+    descriptor.m_NumOutputs = fbDescriptor->numOutputs();
+
+    CHECK_VALID_SIZE(inputs.size(),  descriptor.m_NumInputs);
+    CHECK_VALID_SIZE(outputs.size(), descriptor.m_NumOutputs);
+
+    const std::string layerName     = GetLayerName(graph, layerIndex);
+    armnn::IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
+
+    for (unsigned int i = 0u; i < descriptor.m_NumOutputs; ++i)
+    {
+        armnn::TensorInfo outputInfo = ToTensorInfo(outputs[i]);
+        layer->GetOutputSlot(i).SetTensorInfo(outputInfo);
+    }
+
+    RegisterInputSlots(graph, layerIndex, layer);
+    RegisterOutputSlots(graph, layerIndex, layer);
+}
+
 } // namespace armnnDeserializer
index b951483..babb56e 100644 (file)
@@ -123,6 +123,7 @@ private:
     void ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex);
     void ParseSplitter(GraphPtr graph, unsigned int layerIndex);
     void ParseStack(GraphPtr graph, unsigned int layerIndex);
+    void ParseStandIn(GraphPtr graph, unsigned int layerIndex);
     void ParseStridedSlice(GraphPtr graph, unsigned int layerIndex);
     void ParseSubtraction(GraphPtr graph, unsigned int layerIndex);
     void ParseSwitch(GraphPtr graph, unsigned int layerIndex);
index fce7064..fcadacc 100644 (file)
@@ -50,6 +50,7 @@ The Arm NN SDK Deserialize parser currently supports the following layers:
 * SpaceToDepth
 * Splitter
 * Stack
+* StandIn
 * StridedSlice
 * Subtraction
 * Switch
index 0756784..bad95cf 100644 (file)
@@ -144,7 +144,8 @@ enum LayerType : uint {
     DepthToSpace = 49,
     InstanceNormalization = 50,
     LogSoftmax = 51,
-    Comparison = 52
+    Comparison = 52,
+    StandIn = 53
 }
 
 // Base layer table to be used as part of other layers
@@ -731,6 +732,16 @@ table StackDescriptor {
     inputShape:[uint];
 }
 
+table StandInDescriptor {
+    numInputs:uint;
+    numOutputs:uint;
+}
+
+table StandInLayer {
+    base:LayerBase;
+    descriptor:StandInDescriptor;
+}
+
 union Layer {
     ActivationLayer,
     AdditionLayer,
@@ -784,7 +795,8 @@ union Layer {
     DepthToSpaceLayer,
     InstanceNormalizationLayer,
     LogSoftmaxLayer,
-    ComparisonLayer
+    ComparisonLayer,
+    StandInLayer
 }
 
 table AnyLayer {
index d147d47..81091bc 100644 (file)
@@ -1094,7 +1094,14 @@ void SerializerVisitor::VisitStandInLayer(const armnn::IConnectableLayer *layer,
                                           const armnn::StandInDescriptor& standInDescriptor,
                                           const char *name)
 {
-    // TODO: IVGCVSW-4010 Implement serialization
+    auto fbDescriptor = serializer::CreateStandInDescriptor(m_flatBufferBuilder,
+                                                            standInDescriptor.m_NumInputs,
+                                                            standInDescriptor.m_NumOutputs);
+
+    auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_StandIn);
+    auto fbLayer     = serializer::CreateStandInLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);
+
+    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_StandInLayer);
 }
 
 void SerializerVisitor::VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
index 4b12f9c..4fc880a 100644 (file)
@@ -50,6 +50,7 @@ The Arm NN SDK Serializer currently supports the following layers:
 * SpaceToDepth
 * Splitter
 * Stack
+* StandIn
 * StridedSlice
 * Subtraction
 * Switch
index 10627d0..1f97e93 100644 (file)
@@ -2289,6 +2289,41 @@ BOOST_AUTO_TEST_CASE(SerializeStack)
     deserializedNetwork->Accept(verifier);
 }
 
+BOOST_AUTO_TEST_CASE(SerializeStandIn)
+{
+    DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StandIn)
+
+    const std::string layerName("standIn");
+
+    armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
+    armnn::StandInDescriptor descriptor(2u, 2u);
+
+    armnn::INetworkPtr network = armnn::INetwork::Create();
+    armnn::IConnectableLayer* const inputLayer0  = network->AddInputLayer(0);
+    armnn::IConnectableLayer* const inputLayer1  = network->AddInputLayer(1);
+    armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
+    armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
+    armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
+
+    inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
+    inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
+
+    inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
+    inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
+
+    standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
+    standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
+
+    standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
+    standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
+
+    armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
+    BOOST_CHECK(deserializedNetwork);
+
+    StandInLayerVerifier verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
+    deserializedNetwork->Accept(verifier);
+}
+
 BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
 {
     DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StridedSlice)