diff options
Diffstat (limited to 'src/armnnUtils')
-rw-r--r-- | src/armnnUtils/ParserHelper.cpp | 49 | ||||
-rw-r--r-- | src/armnnUtils/ParserHelper.hpp | 5 | ||||
-rw-r--r-- | src/armnnUtils/ParserPrototxtFixture.hpp | 88 | ||||
-rw-r--r-- | src/armnnUtils/test/ParsePrototxtFixtureTest.cpp | 42 | ||||
-rw-r--r-- | src/armnnUtils/test/ParserHelperTest.cpp | 98 |
5 files changed, 275 insertions, 7 deletions
diff --git a/src/armnnUtils/ParserHelper.cpp b/src/armnnUtils/ParserHelper.cpp index bf5ffdf0ad..9d633cfc42 100644 --- a/src/armnnUtils/ParserHelper.cpp +++ b/src/armnnUtils/ParserHelper.cpp @@ -61,4 +61,53 @@ void ProcessConcatInputTensorInfo(armnn::TensorInfo& inputTensorInfo, armnn::Ori } } +void CalculateReducedOutputTensoInfo(const armnn::TensorInfo& inputTensorInfo, const armnn::TensorInfo& axisTensorInfo, + const std::set<unsigned int>& axisSet, bool keepDims, + armnn::TensorInfo& outputTensorInfo) +{ + std::vector<unsigned int> outputShapeVector; + bool dimensionFound = false; + unsigned int size = 1; + + for (unsigned int i = 0; i < inputTensorInfo.GetNumDimensions(); ++i) + { + dimensionFound = false; + for (unsigned int axis: axisSet) + { + if (axis == i) + { + dimensionFound = true; + break; + } + } + + if (!dimensionFound) + { + size *= inputTensorInfo.GetShape()[i]; + + if (keepDims) + { + outputShapeVector.push_back(inputTensorInfo.GetShape()[i]); + } + } + else + { + if (keepDims) + { + outputShapeVector.push_back(1); + } + } + } + + if (keepDims) + { + armnn::TensorShape outputTensorShape(inputTensorInfo.GetNumDimensions(), &outputShapeVector[0]); + outputTensorInfo = armnn::TensorInfo(outputTensorShape, inputTensorInfo.GetDataType()); + } + else + { + outputTensorInfo = armnn::TensorInfo({size}, inputTensorInfo.GetDataType()); + } +} + } // namespace armnnUtils diff --git a/src/armnnUtils/ParserHelper.hpp b/src/armnnUtils/ParserHelper.hpp index 93dfbf9360..24369dc521 100644 --- a/src/armnnUtils/ParserHelper.hpp +++ b/src/armnnUtils/ParserHelper.hpp @@ -14,4 +14,9 @@ void ProcessConcatInputTensorInfo(armnn::TensorInfo& inputTensorInfo, armnn::Ori const unsigned int& concatAxis, unsigned int inputIndex, std::vector<unsigned int>& mergeDimSizes, unsigned int& mergeDim); +/// Creates a tensor info after reducing the dimensions mentioned in axisData. +void CalculateReducedOutputTensoInfo(const armnn::TensorInfo& inputTensorInfo, const armnn::TensorInfo& axisTensorInfo, + const std::set<unsigned int>& axisSet, bool keepDims, + armnn::TensorInfo& outputTensorInfo); + } // namespace armnnUtils diff --git a/src/armnnUtils/ParserPrototxtFixture.hpp b/src/armnnUtils/ParserPrototxtFixture.hpp index acb8f82c4d..154f6bec2a 100644 --- a/src/armnnUtils/ParserPrototxtFixture.hpp +++ b/src/armnnUtils/ParserPrototxtFixture.hpp @@ -16,6 +16,7 @@ #include <boost/format.hpp> +#include <iomanip> #include <string> namespace armnnUtils @@ -37,6 +38,10 @@ struct ParserPrototxtFixture void SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape, const std::string& inputName, const std::string& outputName); + void SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape, + const armnn::TensorShape& outputTensorShape, + const std::string& inputName, + const std::string& outputName); void Setup(const std::map<std::string, armnn::TensorShape>& inputShapes, const std::vector<std::string>& requestedOutputs); void Setup(); @@ -56,6 +61,9 @@ struct ParserPrototxtFixture void RunTest(const std::map<std::string, std::vector<float>>& inputData, const std::map<std::string, std::vector<float>>& expectedOutputData); + /// Converts an int value into the Protobuf octal representation + std::string ConvertInt32ToOctalString(int value); + std::string m_Prototext; std::unique_ptr<TParser, void(*)(TParser* parser)> m_Parser; armnn::IRuntimePtr m_Runtime; @@ -67,6 +75,10 @@ struct ParserPrototxtFixture std::string m_SingleInputName; std::string m_SingleOutputName; /// @} + + /// This will store the output shape so it don't need to be passed to the single-input-single-output overload + /// of RunTest(). + armnn::TensorShape m_SingleOutputShape; }; template<typename TParser> @@ -91,6 +103,20 @@ void ParserPrototxtFixture<TParser>::SetupSingleInputSingleOutput(const armnn::T } template<typename TParser> +void ParserPrototxtFixture<TParser>::SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape, + const armnn::TensorShape& outputTensorShape, + const std::string& inputName, + const std::string& outputName) +{ + // Stores the input name, the output name and the output tensor shape + // so they don't need to be passed to the single-input-single-output RunTest(). + m_SingleInputName = inputName; + m_SingleOutputName = outputName; + m_SingleOutputShape = outputTensorShape; + Setup({ { inputName, inputTensorShape } }, { outputName }); +} + +template<typename TParser> void ParserPrototxtFixture<TParser>::Setup(const std::map<std::string, armnn::TensorShape>& inputShapes, const std::vector<std::string>& requestedOutputs) { @@ -181,17 +207,65 @@ void ParserPrototxtFixture<TParser>::RunTest(const std::map<std::string, std::ve if (bindingInfo.second.GetNumElements() != it.second.size()) { throw armnn::Exception( - boost::str( - boost::format("Output tensor %1% is expected to have %2% elements. " - "%3% elements supplied. %4%") % - it.first % - bindingInfo.second.GetNumElements() % - it.second.size() % - CHECK_LOCATION().AsString())); + boost::str(boost::format("Output tensor %1% is expected to have %2% elements. " + "%3% elements supplied. %4%") % + it.first % + bindingInfo.second.GetNumElements() % + it.second.size() % + CHECK_LOCATION().AsString())); } + + // If the expected output shape is set, the output tensor checks will be carried out. + if (m_SingleOutputShape.GetNumDimensions() != 0) + { + + if (bindingInfo.second.GetShape().GetNumDimensions() == NumOutputDimensions && + bindingInfo.second.GetShape().GetNumDimensions() == m_SingleOutputShape.GetNumDimensions()) + { + for (unsigned int i = 0; i < m_SingleOutputShape.GetNumDimensions(); ++i) + { + if (m_SingleOutputShape[i] != bindingInfo.second.GetShape()[i]) + { + throw armnn::Exception( + boost::str(boost::format("Output tensor %1% is expected to have %2% shape. " + "%3% shape supplied. %4%") % + it.first % + bindingInfo.second.GetShape() % + m_SingleOutputShape % + CHECK_LOCATION().AsString())); + } + } + } + else + { + throw armnn::Exception( + boost::str(boost::format("Output tensor %1% is expected to have %2% dimensions. " + "%3% dimensions supplied. %4%") % + it.first % + bindingInfo.second.GetShape().GetNumDimensions() % + NumOutputDimensions % + CHECK_LOCATION().AsString())); + } + } + auto outputExpected = MakeTensor<float, NumOutputDimensions>(bindingInfo.second, it.second); BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first])); } } +template<typename TParser> +std::string ParserPrototxtFixture<TParser>::ConvertInt32ToOctalString(int value) +{ + std::stringstream ss; + std::string returnString; + for (int i = 0; i < 4; ++i) + { + ss << "\\"; + ss << std::setw(3) << std::setfill('0') << std::oct << ((value >> (i * 8)) & 0xFF); + } + + ss >> returnString; + return returnString; +} + } // namespace armnnUtils diff --git a/src/armnnUtils/test/ParsePrototxtFixtureTest.cpp b/src/armnnUtils/test/ParsePrototxtFixtureTest.cpp new file mode 100644 index 0000000000..926658ed0c --- /dev/null +++ b/src/armnnUtils/test/ParsePrototxtFixtureTest.cpp @@ -0,0 +1,42 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include <ParserPrototxtFixture.hpp> + +#include <boost/test/unit_test.hpp> +#include "armnnTfParser/ITfParser.hpp" + +BOOST_AUTO_TEST_SUITE(ParsePrototxtFixtureSuite) + +using Fixture = armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>; + +BOOST_FIXTURE_TEST_CASE(ConvertInt32ToOctalStringTest, Fixture) +{ + std::string octalString = ConvertInt32ToOctalString(1); + BOOST_ASSERT(octalString.compare("\\\\001\\\\000\\\\000\\\\000")); + + octalString = ConvertInt32ToOctalString(256); + BOOST_ASSERT(octalString.compare("\\\\000\\\\100\\\\000\\\\000")); + + octalString = ConvertInt32ToOctalString(65536); + BOOST_ASSERT(octalString.compare("\\\\000\\\\000\\\\100\\\\000")); + + octalString = ConvertInt32ToOctalString(16777216); + BOOST_ASSERT(octalString.compare("\\\\000\\\\000\\\\000\\\\100")); + + octalString = ConvertInt32ToOctalString(-1); + BOOST_ASSERT(octalString.compare("\\\\377\\\\377\\\\377\\\\377")); + + octalString = ConvertInt32ToOctalString(-256); + BOOST_ASSERT(octalString.compare("\\\\000\\\\377\\\\377\\\\377")); + + octalString = ConvertInt32ToOctalString(-65536); + BOOST_ASSERT(octalString.compare("\\\\000\\\\000\\\\377\\\\377")); + + octalString = ConvertInt32ToOctalString(-16777216); + BOOST_ASSERT(octalString.compare("\\\\000\\\\000\\\\000\\\\377")); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/armnnUtils/test/ParserHelperTest.cpp b/src/armnnUtils/test/ParserHelperTest.cpp new file mode 100644 index 0000000000..122ad7649e --- /dev/null +++ b/src/armnnUtils/test/ParserHelperTest.cpp @@ -0,0 +1,98 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "../ParserHelper.hpp" + +#include <boost/test/unit_test.hpp> + +#include "armnn/Types.hpp" + +using namespace armnn; +using namespace armnnUtils; + +BOOST_AUTO_TEST_SUITE(ParserHelperSuite) + +BOOST_AUTO_TEST_CASE(CalculateReducedOutputTensoInfoTest) +{ + bool keepDims = false; + + unsigned int inputShape[] = { 2, 3, 4 }; + TensorInfo inputTensorInfo(3, &inputShape[0], DataType::Float32); + + // Reducing all dimensions results in one single output value (one dimension) + unsigned int axisShape1[] = { 3 }; + std::set<unsigned int> axisData1 = { 0, 1, 2 }; + TensorInfo axisTensorInfo1(1, &axisShape1[0], DataType::Signed32); + + TensorInfo outputTensorInfo1; + + CalculateReducedOutputTensoInfo(inputTensorInfo, axisTensorInfo1, axisData1, + keepDims, outputTensorInfo1); + + BOOST_ASSERT(outputTensorInfo1.GetNumDimensions() == 1); + BOOST_ASSERT(outputTensorInfo1.GetShape()[0] == 1); + + // Reducing dimension 0 results in a 3x4 size tensor (one dimension) + unsigned int axisShape2[] = { 1 }; + std::set<unsigned int> axisData2 = { 0 }; + TensorInfo axisTensorInfo2(1, &axisShape2[0], DataType::Signed32); + + TensorInfo outputTensorInfo2; + + CalculateReducedOutputTensoInfo(inputTensorInfo, axisTensorInfo2, axisData2, + keepDims, outputTensorInfo2); + + BOOST_ASSERT(outputTensorInfo2.GetNumDimensions() == 1); + BOOST_ASSERT(outputTensorInfo2.GetShape()[0] == 12); + + // Reducing dimensions 0,1 results in a 4 size tensor (one dimension) + unsigned int axisShape3[] = { 2 }; + std::set<unsigned int> axisData3 = { 0, 1 }; + TensorInfo axisTensorInfo3(1, &axisShape3[0], DataType::Signed32); + + TensorInfo outputTensorInfo3; + + CalculateReducedOutputTensoInfo(inputTensorInfo, axisTensorInfo3, axisData3, + keepDims, outputTensorInfo3); + + BOOST_ASSERT(outputTensorInfo3.GetNumDimensions() == 1); + BOOST_ASSERT(outputTensorInfo3.GetShape()[0] == 4); + + // Reducing dimension 0 results in a { 1, 3, 4 } dimension tensor + keepDims = true; + unsigned int axisShape4[] = { 1 }; + std::set<unsigned int> axisData4 = { 0 }; + TensorInfo axisTensorInfo4(1, &axisShape4[0], DataType::Signed32); + + TensorInfo outputTensorInfo4; + + CalculateReducedOutputTensoInfo(inputTensorInfo, axisTensorInfo4, axisData4, + keepDims, outputTensorInfo4); + + BOOST_ASSERT(outputTensorInfo4.GetNumDimensions() == 3); + BOOST_ASSERT(outputTensorInfo4.GetShape()[0] == 1); + BOOST_ASSERT(outputTensorInfo4.GetShape()[1] == 3); + BOOST_ASSERT(outputTensorInfo4.GetShape()[2] == 4); + + // Reducing dimension 1, 2 results in a { 2, 1, 1 } dimension tensor + keepDims = true; + unsigned int axisShape5[] = { 2 }; + std::set<unsigned int> axisData5 = { 1, 2 }; + TensorInfo axisTensorInfo5(1, &axisShape5[0], DataType::Signed32); + + TensorInfo outputTensorInfo5; + + CalculateReducedOutputTensoInfo(inputTensorInfo, axisTensorInfo5, axisData5, + keepDims, outputTensorInfo5); + + BOOST_ASSERT(outputTensorInfo5.GetNumDimensions() == 3); + BOOST_ASSERT(outputTensorInfo5.GetShape()[0] == 2); + BOOST_ASSERT(outputTensorInfo5.GetShape()[1] == 1); + BOOST_ASSERT(outputTensorInfo5.GetShape()[2] == 1); + +} + +BOOST_AUTO_TEST_SUITE_END() + |