diff options
Diffstat (limited to 'src/armnnDeserializeParser')
-rw-r--r-- | src/armnnDeserializeParser/DeserializeParser.cpp | 125 | ||||
-rw-r--r-- | src/armnnDeserializeParser/DeserializeParser.hpp | 5 | ||||
-rw-r--r-- | src/armnnDeserializeParser/test/DeserializePooling2d.cpp | 162 |
3 files changed, 287 insertions, 5 deletions
diff --git a/src/armnnDeserializeParser/DeserializeParser.cpp b/src/armnnDeserializeParser/DeserializeParser.cpp index eb7bccaa1d..f47c23f0b5 100644 --- a/src/armnnDeserializeParser/DeserializeParser.cpp +++ b/src/armnnDeserializeParser/DeserializeParser.cpp @@ -136,6 +136,7 @@ m_ParserFunctions(Layer_MAX+1, &DeserializeParser::ParseUnsupportedLayer) // register supported layers m_ParserFunctions[Layer_AdditionLayer] = &DeserializeParser::ParseAdd; m_ParserFunctions[Layer_MultiplicationLayer] = &DeserializeParser::ParseMultiplication; + m_ParserFunctions[Layer_Pooling2dLayer] = &DeserializeParser::ParsePooling2d; m_ParserFunctions[Layer_SoftmaxLayer] = &DeserializeParser::ParseSoftmax; } @@ -153,6 +154,8 @@ DeserializeParser::LayerBaseRawPtr DeserializeParser::GetBaseLayer(const GraphPt return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base(); case Layer::Layer_OutputLayer: return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base(); + case Layer::Layer_Pooling2dLayer: + return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base(); case Layer::Layer_SoftmaxLayer: return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base(); case Layer::Layer_NONE: @@ -356,7 +359,6 @@ DeserializeParser::GraphPtr DeserializeParser::LoadGraphFromFile(const char* fil } std::ifstream file(fileName, std::ios::binary); fileContent = std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); - return LoadGraphFromBinary(reinterpret_cast<const uint8_t*>(fileContent.c_str()), fileContent.size()); } @@ -581,8 +583,8 @@ void DeserializeParser::ParseAdd(unsigned int layerIndex) auto outputs = GetOutputs(m_Graph, layerIndex); CHECK_VALID_SIZE(outputs.size(), 1); - auto layerName = boost::str(boost::format("Addition:%1%") % layerIndex); - IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str()); + m_layerName = boost::str(boost::format("Addition:%1%") % layerIndex); + IConnectableLayer* layer = m_Network->AddAdditionLayer(m_layerName.c_str()); armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]); layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); @@ -601,8 +603,8 @@ void DeserializeParser::ParseMultiplication(unsigned int layerIndex) auto outputs = GetOutputs(m_Graph, layerIndex); CHECK_VALID_SIZE(outputs.size(), 1); - auto layerName = boost::str(boost::format("Multiplication:%1%") % layerIndex); - IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str()); + m_layerName = boost::str(boost::format("Multiplication:%1%") % layerIndex); + IConnectableLayer* layer = m_Network->AddMultiplicationLayer(m_layerName.c_str()); armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]); layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); @@ -611,6 +613,119 @@ void DeserializeParser::ParseMultiplication(unsigned int layerIndex) RegisterOutputSlots(layerIndex, layer); } +armnn::Pooling2dDescriptor DeserializeParser::GetPoolingDescriptor(DeserializeParser::PoolingDescriptor pooling2dDesc, + unsigned int layerIndex) +{ + armnn::Pooling2dDescriptor desc; + + switch (pooling2dDesc->poolType()) + { + case PoolingAlgorithm_Average: + { + desc.m_PoolType = armnn::PoolingAlgorithm::Average; + m_layerName = boost::str(boost::format("AveragePool2D:%1%") % layerIndex); + break; + } + case PoolingAlgorithm_Max: + { + desc.m_PoolType = armnn::PoolingAlgorithm::Max; + m_layerName = boost::str(boost::format("MaxPool2D:%1%") % layerIndex); + break; + } + default: + { + BOOST_ASSERT_MSG(false, "Unsupported pooling algorithm"); + } + } + + switch (pooling2dDesc->outputShapeRounding()) + { + case OutputShapeRounding_Floor: + { + desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor; + break; + } + case OutputShapeRounding_Ceiling: + { + desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling; + break; + } + default: + { + BOOST_ASSERT_MSG(false, "Unsupported output shape rounding"); + } + } + + switch (pooling2dDesc->paddingMethod()) + { + case PaddingMethod_Exclude: + { + desc.m_PaddingMethod = armnn::PaddingMethod::Exclude; + break; + } + case PaddingMethod_IgnoreValue: + { + desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue; + break; + } + default: + { + BOOST_ASSERT_MSG(false, "Unsupported padding method"); + } + } + + switch (pooling2dDesc->dataLayout()) + { + case DataLayout_NCHW: + { + desc.m_DataLayout = armnn::DataLayout::NCHW; + break; + } + case DataLayout_NHWC: + { + desc.m_DataLayout = armnn::DataLayout::NHWC; + break; + } + default: + { + BOOST_ASSERT_MSG(false, "Unsupported data layout"); + } + } + + desc.m_PadRight = pooling2dDesc->padRight(); + desc.m_PadLeft = pooling2dDesc->padLeft(); + desc.m_PadBottom = pooling2dDesc->padBottom(); + desc.m_PadTop = pooling2dDesc->padTop(); + desc.m_StrideX = pooling2dDesc->strideX(); + desc.m_StrideY = pooling2dDesc->strideY(); + desc.m_PoolWidth = pooling2dDesc->poolWidth(); + desc.m_PoolHeight = pooling2dDesc->poolHeight(); + + return desc; +} + +void DeserializeParser::ParsePooling2d(unsigned int layerIndex) +{ + CHECK_LAYERS(m_Graph, 0, layerIndex); + + auto pooling2dDes = m_Graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor(); + + auto inputs = GetInputs(m_Graph, layerIndex); + CHECK_VALID_SIZE(inputs.size(), 1); + + auto outputs = GetOutputs(m_Graph, layerIndex); + CHECK_VALID_SIZE(outputs.size(), 1); + auto outputInfo = ToTensorInfo(outputs[0]); + + auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex); + + IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, m_layerName.c_str()); + layer->GetOutputSlot(0).SetTensorInfo(outputInfo); + + RegisterInputSlots(layerIndex, layer); + RegisterOutputSlots(layerIndex, layer); +} + void DeserializeParser::ParseSoftmax(unsigned int layerIndex) { CHECK_LAYERS(m_Graph, 0, layerIndex); diff --git a/src/armnnDeserializeParser/DeserializeParser.hpp b/src/armnnDeserializeParser/DeserializeParser.hpp index ddd02abede..1edb5a9f23 100644 --- a/src/armnnDeserializeParser/DeserializeParser.hpp +++ b/src/armnnDeserializeParser/DeserializeParser.hpp @@ -17,6 +17,7 @@ public: // Shorthands for deserializer types using GraphPtr = const armnn::armnnSerializer::SerializedGraph *; using TensorRawPtr = const armnn::armnnSerializer::TensorInfo *; + using PoolingDescriptor = const armnn::armnnSerializer::Pooling2dDescriptor *; using TensorRawPtrVector = std::vector<TensorRawPtr>; using LayerRawPtr = const armnn::armnnSerializer::LayerBase *; using LayerBaseRawPtr = const armnn::armnnSerializer::LayerBase *; @@ -50,6 +51,8 @@ public: static LayerBaseRawPtrVector GetGraphOutputs(const GraphPtr& graphPtr); static LayerBaseRawPtr GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex); static int32_t GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex); + armnn::Pooling2dDescriptor GetPoolingDescriptor(PoolingDescriptor pooling2dDescriptor, + unsigned int layerIndex); private: // No copying allowed until it is wanted and properly implemented @@ -65,6 +68,7 @@ private: void ParseUnsupportedLayer(unsigned int layerIndex); void ParseAdd(unsigned int layerIndex); void ParseMultiplication(unsigned int layerIndex); + void ParsePooling2d(unsigned int layerIndex); void ParseSoftmax(unsigned int layerIndex); void RegisterOutputSlotOfConnection(uint32_t connectionIndex, armnn::IOutputSlot* slot); @@ -82,6 +86,7 @@ private: armnn::INetworkPtr m_Network; GraphPtr m_Graph; std::vector<LayerParsingFunction> m_ParserFunctions; + std::string m_layerName; /// This holds the data of the file that was read in from CreateNetworkFromBinaryFile /// Needed for m_Graph to point to diff --git a/src/armnnDeserializeParser/test/DeserializePooling2d.cpp b/src/armnnDeserializeParser/test/DeserializePooling2d.cpp new file mode 100644 index 0000000000..70b96ba27b --- /dev/null +++ b/src/armnnDeserializeParser/test/DeserializePooling2d.cpp @@ -0,0 +1,162 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include <boost/test/unit_test.hpp> +#include "ParserFlatbuffersSerializeFixture.hpp" +#include "../DeserializeParser.hpp" + +#include <string> +#include <iostream> + +BOOST_AUTO_TEST_SUITE(DeserializeParser) + +struct Pooling2dFixture : public ParserFlatbuffersSerializeFixture +{ + explicit Pooling2dFixture(const std::string &inputShape, + const std::string &outputShape, + const std::string &dataType, + const std::string &dataLayout, + const std::string &poolingAlgorithm) + { + m_JsonString = R"( + { + inputIds: [0], + outputIds: [2], + layers: [ + { + layer_type: "InputLayer", + layer: { + base: { + layerBindingId: 0, + base: { + index: 0, + layerName: "InputLayer", + layerType: "Input", + inputSlots: [{ + index: 0, + connection: {sourceLayerIndex:0, outputSlotIndex:0 }, + }], + outputSlots: [ { + index: 0, + tensorInfo: { + dimensions: )" + inputShape + R"(, + dataType: )" + dataType + R"( + }}] + } + }}}, + { + layer_type: "Pooling2dLayer", + layer: { + base: { + index: 1, + layerName: "Pooling2dLayer", + layerType: "Pooling2d", + inputSlots: [{ + index: 0, + connection: {sourceLayerIndex:0, outputSlotIndex:0 }, + }], + outputSlots: [ { + index: 0, + tensorInfo: { + dimensions: )" + outputShape + R"(, + dataType: )" + dataType + R"( + + }}]}, + descriptor: { + poolType: )" + poolingAlgorithm + R"(, + outputShapeRounding: "Floor", + paddingMethod: Exclude, + dataLayout: )" + dataLayout + R"(, + padLeft: 0, + padRight: 0, + padTop: 0, + padBottom: 0, + poolWidth: 2, + poolHeight: 2, + strideX: 2, + strideY: 2 + } + }}, + { + layer_type: "OutputLayer", + layer: { + base:{ + layerBindingId: 0, + base: { + index: 2, + layerName: "OutputLayer", + layerType: "Output", + inputSlots: [{ + index: 0, + connection: {sourceLayerIndex:1, outputSlotIndex:0 }, + }], + outputSlots: [ { + index: 0, + tensorInfo: { + dimensions: )" + outputShape + R"(, + dataType: )" + dataType + R"( + }, + }], + }}}, + }] + } + )"; + SetupSingleInputSingleOutput("InputLayer", "OutputLayer"); + } +}; + +struct SimpleAvgPoolingFixture : Pooling2dFixture +{ + SimpleAvgPoolingFixture() : Pooling2dFixture("[ 1, 2, 2, 1 ]", "[ 1, 1, 1, 1 ]", + "Float32", "NHWC", "Average") {} +}; + +struct SimpleAvgPoolingFixture2 : Pooling2dFixture +{ + SimpleAvgPoolingFixture2() : Pooling2dFixture("[ 1, 2, 2, 1 ]", + "[ 1, 1, 1, 1 ]", + "QuantisedAsymm8", "NHWC", "Average") {} +}; + +struct SimpleMaxPoolingFixture : Pooling2dFixture +{ + SimpleMaxPoolingFixture() : Pooling2dFixture("[ 1, 1, 2, 2 ]", + "[ 1, 1, 1, 1 ]", + "Float32", "NCHW", "Max") {} +}; + +struct SimpleMaxPoolingFixture2 : Pooling2dFixture +{ + SimpleMaxPoolingFixture2() : Pooling2dFixture("[ 1, 1, 2, 2 ]", + "[ 1, 1, 1, 1 ]", + "QuantisedAsymm8", "NCHW", "Max") {} +}; + +BOOST_FIXTURE_TEST_CASE(PoolingQuantisedAsymm8Avg, SimpleAvgPoolingFixture) +{ + RunTest<4, armnn::DataType::Float32>(0, { 2, 3, 5, 2 }, { 3 }); +} + +BOOST_FIXTURE_TEST_CASE(PoolingFloat32Avg, SimpleAvgPoolingFixture2) +{ + RunTest<4, armnn::DataType::QuantisedAsymm8>(0, + { 20, 40, 60, 80 }, + { 50 }); +} + +BOOST_FIXTURE_TEST_CASE(PoolingQuantisedAsymm8Max, SimpleMaxPoolingFixture) +{ + RunTest<4, armnn::DataType::Float32>(0, { 2, 5, 5, 2 }, { 5 }); +} + +BOOST_FIXTURE_TEST_CASE(PoolingFloat32Max, SimpleMaxPoolingFixture2) +{ + RunTest<4, armnn::DataType::QuantisedAsymm8>(0, + { 20, 40, 60, 80 }, + { 80 }); +} + +BOOST_AUTO_TEST_SUITE_END() + |