aboutsummaryrefslogtreecommitdiff
path: root/src/armnnTfParser
diff options
context:
space:
mode:
authorsaoste01 <saoirse.stewart@arm.com>2018-08-28 15:41:51 +0100
committerMatthew Bentham <matthew.bentham@arm.com>2018-09-17 17:21:25 +0100
commitbbd4061da3094e1eec61fcdb6297f626ff025ba2 (patch)
treec51c1d2a62e6ccc86c913b5d20b9f3eba314d759 /src/armnnTfParser
parent8c5e3dc9f04ac15aa926d1a1214610760830dbe2 (diff)
downloadarmnn-bbd4061da3094e1eec61fcdb6297f626ff025ba2.tar.gz
IVGCVSW-1779: Updating TF Parser to include the RealDiv operator
Change-Id: I4b193d9119f5aaf41081335df043352953364c87
Diffstat (limited to 'src/armnnTfParser')
-rw-r--r--src/armnnTfParser/TfParser.cpp60
-rw-r--r--src/armnnTfParser/TfParser.hpp2
-rw-r--r--src/armnnTfParser/test/RealDiv.cpp169
3 files changed, 223 insertions, 8 deletions
diff --git a/src/armnnTfParser/TfParser.cpp b/src/armnnTfParser/TfParser.cpp
index 5bc2ad7d18..2d873c9b4d 100644
--- a/src/armnnTfParser/TfParser.cpp
+++ b/src/armnnTfParser/TfParser.cpp
@@ -266,8 +266,8 @@ TensorInfo PrepareReshape(const TensorInfo& input, const std::vector<int32_t>& t
}
// We need the input0Slot to guide the reshape for input1Slot.
-IOutputSlot* BroadcastForAddandMul(IOutputSlot* input0Slot, IOutputSlot* input1Slot, bool isNHWC, INetwork& m_Network,
- const tensorflow::NodeDef& nodeDef)
+IOutputSlot* AddBroadcastReshapeLayer(IOutputSlot* input0Slot, IOutputSlot* input1Slot, bool isNHWC,
+ INetwork& m_Network, const tensorflow::NodeDef& nodeDef)
{
const TensorInfo& input1Info = input1Slot->GetTensorInfo();
const TensorInfo inputTensorInfo = input0Slot->GetTensorInfo();
@@ -354,6 +354,7 @@ const std::map<std::string, TfParser::OperationParsingFunction> TfParser::ms_Ope
{ "MatMul", &TfParser::ParseMatMul },
{ "Mul", &TfParser::ParseMul },
{ "Placeholder", &TfParser::ParsePlaceholder },
+ { "RealDiv", &TfParser::ParseRealDiv },
{ "Relu", &TfParser::ParseRelu },
{ "Relu6", &TfParser::ParseRelu6 },
{ "Reshape", &TfParser::ParseReshape },
@@ -1893,6 +1894,12 @@ ParsedTfOperationPtr TfParser::ParsePlaceholder(const tensorflow::NodeDef& nodeD
return std::make_unique<SingleLayerParsedTfOperation>(this, nodeDef, layer);
}
+ParsedTfOperationPtr TfParser::ParseRealDiv(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef)
+{
+ boost::ignore_unused(graphDef);
+ return AddRealDivLayer(nodeDef);
+}
+
ParsedTfOperationPtr TfParser::ParseRelu(const tensorflow::NodeDef& nodeDef,
const tensorflow::GraphDef& graphDef)
{
@@ -2135,20 +2142,20 @@ ParsedTfOperationPtr TfParser::AddAdditionLayer(const tensorflow::NodeDef& nodeD
const std::string dataFormat = ReadMandatoryNodeStringAttribute(nodeDef, "data_format");
CHECK_DATA_FORMAT(nodeDef, dataFormat, "BiasAdd");
- input1Slot = BroadcastForAddandMul(input0Slot, input1Slot, dataFormat == "NHWC", *m_Network, nodeDef);
+ input1Slot = AddBroadcastReshapeLayer(input0Slot, input1Slot, dataFormat == "NHWC", *m_Network, nodeDef);
}
else
{
if (input0Info.GetNumDimensions() == 1)
{
const bool isNHWC = true;
- input0Slot = BroadcastForAddandMul(input1Slot, input0Slot, isNHWC, *m_Network, nodeDef);
+ input0Slot = AddBroadcastReshapeLayer(input1Slot, input0Slot, isNHWC, *m_Network, nodeDef);
}
if (input1Info.GetNumDimensions() == 1)
{
const bool isNHWC = true;
- input1Slot = BroadcastForAddandMul(input0Slot, input1Slot, isNHWC, *m_Network, nodeDef);
+ input1Slot = AddBroadcastReshapeLayer(input0Slot, input1Slot, isNHWC, *m_Network, nodeDef);
}
}
@@ -2169,6 +2176,44 @@ ParsedTfOperationPtr TfParser::AddAdditionLayer(const tensorflow::NodeDef& nodeD
return std::make_unique<SingleLayerParsedTfOperation>(this, nodeDef, layer);
}
+ParsedTfOperationPtr TfParser::AddRealDivLayer(const tensorflow::NodeDef& nodeDef)
+{
+ std::vector<OutputOfParsedTfOperation> inputs = GetInputParsedTfOperationsChecked(nodeDef, 2);
+
+ IConnectableLayer* const layer = m_Network->AddDivisionLayer(nodeDef.name().c_str());
+ IOutputSlot* input0Slot = &inputs[0].m_IndexedValue->ResolveArmnnOutputSlot(inputs[0].m_Index);
+ IOutputSlot* input1Slot = &inputs[1].m_IndexedValue->ResolveArmnnOutputSlot(inputs[1].m_Index);
+
+ auto const input0NumDims = input0Slot->GetTensorInfo().GetNumDimensions();
+ auto const input1NumDims = input1Slot->GetTensorInfo().GetNumDimensions();
+
+
+ if (input0NumDims < input1NumDims)
+ {
+ const bool isNHWC = true;
+ input0Slot = AddBroadcastReshapeLayer(input1Slot, input0Slot, isNHWC, *m_Network, nodeDef);
+ }
+ if (input1NumDims < input0NumDims)
+ {
+ const bool isNHWC = true;
+ input1Slot = AddBroadcastReshapeLayer(input0Slot, input1Slot, isNHWC, *m_Network, nodeDef);
+ }
+
+ input0Slot->Connect(layer->GetInputSlot(0));
+ input1Slot->Connect(layer->GetInputSlot(1));
+
+ if (input0NumDims < input1NumDims)
+ {
+ layer->GetOutputSlot(0).SetTensorInfo(input1Slot->GetTensorInfo());
+ }
+ else
+ {
+ layer->GetOutputSlot(0).SetTensorInfo(input0Slot->GetTensorInfo());
+
+ }
+ return std::make_unique<SingleLayerParsedTfOperation>(this, nodeDef, layer);
+}
+
IConnectableLayer* TfParser::AddMultiplicationLayer(const tensorflow::NodeDef& nodeDef)
{
std::vector<OutputOfParsedTfOperation> inputs = GetInputParsedTfOperationsChecked(nodeDef, 2);
@@ -2183,12 +2228,12 @@ IConnectableLayer* TfParser::AddMultiplicationLayer(const tensorflow::NodeDef& n
if (input0NumDims < input1NumDims)
{
const bool isNHWC = true;
- input0Slot = BroadcastForAddandMul(input1Slot, input0Slot, isNHWC, *m_Network, nodeDef);
+ input0Slot = AddBroadcastReshapeLayer(input1Slot, input0Slot, isNHWC, *m_Network, nodeDef);
}
if (input1NumDims < input0NumDims)
{
const bool isNHWC = true;
- input1Slot = BroadcastForAddandMul(input0Slot, input1Slot, isNHWC, *m_Network, nodeDef);
+ input1Slot = AddBroadcastReshapeLayer(input0Slot, input1Slot, isNHWC, *m_Network, nodeDef);
}
input0Slot->Connect(layer->GetInputSlot(0));
@@ -2205,7 +2250,6 @@ IConnectableLayer* TfParser::AddMultiplicationLayer(const tensorflow::NodeDef& n
return layer;
}
-
IConnectableLayer* TfParser::AddFullyConnectedLayer(const tensorflow::NodeDef& matMulNodeDef,
const tensorflow::NodeDef* addNodeDef, const char* armnnLayerName)
{
diff --git a/src/armnnTfParser/TfParser.hpp b/src/armnnTfParser/TfParser.hpp
index 75cd3a5bd0..534714cbee 100644
--- a/src/armnnTfParser/TfParser.hpp
+++ b/src/armnnTfParser/TfParser.hpp
@@ -136,6 +136,7 @@ private:
ParsedTfOperationPtr ParseMatMul(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
ParsedTfOperationPtr ParseMul(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
ParsedTfOperationPtr ParsePlaceholder(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
+ ParsedTfOperationPtr ParseRealDiv(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
ParsedTfOperationPtr ParseRelu(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
ParsedTfOperationPtr ParseRelu6(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
ParsedTfOperationPtr ParseReshape(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
@@ -153,6 +154,7 @@ private:
ParsedTfOperationPtr ParseMaximum(const tensorflow::NodeDef& nodeDef, const tensorflow::GraphDef& graphDef);
ParsedTfOperationPtr AddActivationLayer(const tensorflow::NodeDef& nodeDef, armnn::ActivationDescriptor& desc);
ParsedTfOperationPtr AddAdditionLayer(const tensorflow::NodeDef& nodeDef, bool isBiasAdd = false);
+ ParsedTfOperationPtr AddRealDivLayer(const tensorflow::NodeDef& nodeDef);
private:
armnn::IConnectableLayer* AddMultiplicationLayer(const tensorflow::NodeDef& nodeDef);
diff --git a/src/armnnTfParser/test/RealDiv.cpp b/src/armnnTfParser/test/RealDiv.cpp
new file mode 100644
index 0000000000..9151cf63ef
--- /dev/null
+++ b/src/armnnTfParser/test/RealDiv.cpp
@@ -0,0 +1,169 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// See LICENSE file in the project root for full license information.
+//
+
+#include <boost/test/unit_test.hpp>
+#include "armnnTfParser/ITfParser.hpp"
+#include "ParserPrototxtFixture.hpp"
+
+BOOST_AUTO_TEST_SUITE(TensorflowParser)
+
+struct DivisionFixture : public armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>
+{
+ DivisionFixture()
+ {
+ m_Prototext = "node { \n"
+ " name: \"graphInput\" \n"
+ " op: \"Placeholder\" \n"
+ " attr { \n"
+ " key: \"dtype\" \n"
+ " value { \n"
+ " type: DT_FLOAT \n"
+ " } \n"
+ " } \n"
+ " attr { \n"
+ " key: \"shape\" \n"
+ " value { \n"
+ " shape { \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ " node { \n"
+ " name: \"softmax1\" \n"
+ " op: \"Softmax\" \n"
+ " input: \"graphInput\" \n"
+ " attr { \n"
+ " key: \"T\" \n"
+ " value { \n"
+ " type: DT_FLOAT \n"
+ " } \n"
+ " } \n"
+ " }\n"
+ " node {\n"
+ " name: \"softmax2\"\n"
+ " op : \"Softmax\"\n"
+ " input: \"graphInput\"\n"
+ " attr { \n"
+ " key: \"T\" \n"
+ " value { \n"
+ " type: DT_FLOAT \n"
+ " } \n"
+ " } \n"
+ " }\n"
+ " node {\n"
+ " name: \"division\"\n"
+ " op : \"RealDiv\"\n"
+ " input: \"softmax1\"\n"
+ " input: \"softmax2\"\n"
+ " attr { \n"
+ " key: \"T\" \n"
+ " value { \n"
+ " type: DT_FLOAT \n"
+ " } \n"
+ " } \n"
+ " }\n";
+
+ SetupSingleInputSingleOutput({ 4, 1 }, "graphInput", "division");
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(ParseDivision, DivisionFixture)
+{
+ RunTest<2>({ 2, 1.0f, 3, 1 }, { 1, 1.0f, 1, 1});
+}
+
+struct DivisionBroadcastFixture : public armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>
+{
+ DivisionBroadcastFixture(const armnn::TensorShape& inputShape0, const armnn::TensorShape& inputShape1)
+ {
+ m_Prototext = R"(
+ node {
+ name: "input0"
+ op: "Placeholder"
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "shape"
+ value {
+ shape {
+ }
+ }
+ }
+ }
+ node {
+ name: "input1"
+ op: "Placeholder"
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "shape"
+ value {
+ shape {
+ }
+ }
+ }
+ }
+ node {
+ name: "output"
+ op: "RealDiv"
+ input: "input0"
+ input: "input1"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ }
+ )";
+
+ Setup({ { "input0", inputShape0 },
+ { "input1", inputShape1 } },
+ { "output" });
+ }
+};
+struct DivisionBroadcastFixture4D1D : public DivisionBroadcastFixture
+{
+ DivisionBroadcastFixture4D1D() : DivisionBroadcastFixture({ 1, 2, 2, 3 }, { 1 }) {}
+};
+
+BOOST_FIXTURE_TEST_CASE(ParseDivisionBroadcast4D1D, DivisionBroadcastFixture4D1D)
+{
+ RunTest<4>({ { "input0", { 0.0f, 100.0f, 2.0f,
+ 3.0f, 250.0f, 15.0f,
+ 33.0f, 60.0f, 5.0f,
+ 35.0f, 10.0f, 55.0f } },
+ { "input1", { 5.0f } } },
+ { { "output", { 0, 20.0f, 0.4f,
+ 0.6f, 50.0f, 3.0f,
+ 6.6f, 12.0f, 1.0f,
+ 7.0f, 2.0f, 11.0f } } });
+}
+
+BOOST_FIXTURE_TEST_CASE(ParseDivideByZeroBroadcast4D1D, DivisionBroadcastFixture4D1D)
+{
+ float Inf = std::numeric_limits<float>::infinity();
+ float NaN = std::numeric_limits<float>::quiet_NaN();
+
+ RunTest<4>({ { "input0", { 0.0f, -100.0f, 2.0f,
+ 3.0f, -250.0f, 15.0f,
+ 33.0f, -0, 5.0f,
+ 35.0f, -10.0f, 55.0f } },
+ { "input1", { 0 } } },
+ { { "output", { NaN, -Inf, Inf,
+ Inf, -Inf, Inf,
+ Inf, NaN, Inf,
+ Inf, -Inf, Inf } } });
+}
+
+BOOST_AUTO_TEST_SUITE_END()