aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkevmay01 <kevin.may@arm.com>2019-01-24 14:05:09 +0000
committerkevmay01 <kevin.may@arm.com>2019-01-24 14:05:09 +0000
commit2b4d88e34ac1f965417fd236fd4786f26bae2042 (patch)
tree4518b52c6a22e33c4b467588a2843c9d5f1a9ee6
parent94412aff782472be54dce4328e2ecee0225b3e97 (diff)
downloadarmnn-2b4d88e34ac1f965417fd236fd4786f26bae2042.tar.gz
IVGCVSW-2503 Refactor RefElementwiseWorkload around Equal and Greater
* Remove Equal and Greater from RefElementwiseWorkload * Create RefComparisonWorkload and add Equal and Greater * Update ElementwiseFunction for different input/output types * Update TfParser to create Equal/Greater with Boolean output * Update relevant tests to check for Boolean comparison Change-Id: I299b7f2121769c960ac0c6139764a5f3c89c9c32
-rw-r--r--src/armnn/LayerSupportCommon.hpp6
-rw-r--r--src/armnn/test/TensorHelpers.hpp21
-rw-r--r--src/armnn/test/UnitTests.hpp2
-rwxr-xr-xsrc/armnnTfParser/TfParser.cpp31
-rw-r--r--src/armnnTfParser/TfParser.hpp6
-rw-r--r--src/armnnTfParser/test/Equal.cpp32
-rw-r--r--src/armnnTfParser/test/Greater.cpp32
-rw-r--r--src/armnnUtils/ParserPrototxtFixture.hpp38
-rw-r--r--src/backends/backendsCommon/MakeWorkloadHelper.hpp20
-rw-r--r--src/backends/backendsCommon/Workload.hpp13
-rw-r--r--src/backends/backendsCommon/WorkloadData.cpp10
-rw-r--r--src/backends/backendsCommon/test/ArithmeticTestImpl.hpp50
-rw-r--r--src/backends/backendsCommon/test/EndToEndTestImpl.hpp12
-rw-r--r--src/backends/backendsCommon/test/LayerTests.cpp194
-rw-r--r--src/backends/backendsCommon/test/LayerTests.hpp14
-rw-r--r--src/backends/backendsCommon/test/MergerTestImpl.hpp2
-rw-r--r--src/backends/cl/ClLayerSupport.cpp16
-rw-r--r--src/backends/cl/ClWorkloadFactory.cpp3
-rw-r--r--src/backends/neon/NeonLayerSupport.cpp16
-rw-r--r--src/backends/neon/NeonTensorHandle.hpp4
-rw-r--r--src/backends/neon/NeonWorkloadFactory.cpp3
-rw-r--r--src/backends/reference/RefLayerSupport.cpp38
-rw-r--r--src/backends/reference/RefWorkloadFactory.cpp10
-rw-r--r--src/backends/reference/backend.mk1
-rw-r--r--src/backends/reference/test/RefEndToEndTests.cpp48
-rw-r--r--src/backends/reference/workloads/CMakeLists.txt2
-rw-r--r--src/backends/reference/workloads/ElementwiseFunction.cpp32
-rw-r--r--src/backends/reference/workloads/ElementwiseFunction.hpp8
-rw-r--r--src/backends/reference/workloads/RefComparisonWorkload.cpp65
-rw-r--r--src/backends/reference/workloads/RefComparisonWorkload.hpp92
-rw-r--r--src/backends/reference/workloads/RefElementwiseWorkload.cpp20
-rw-r--r--src/backends/reference/workloads/RefElementwiseWorkload.hpp24
-rw-r--r--src/backends/reference/workloads/RefWorkloads.hpp1
33 files changed, 601 insertions, 265 deletions
diff --git a/src/armnn/LayerSupportCommon.hpp b/src/armnn/LayerSupportCommon.hpp
index 109728cd81..70b5f182f4 100644
--- a/src/armnn/LayerSupportCommon.hpp
+++ b/src/armnn/LayerSupportCommon.hpp
@@ -12,13 +12,15 @@
namespace armnn
{
-template<typename Float16Func, typename Float32Func, typename Uint8Func, typename Int32Func, typename ... Params>
+template<typename Float16Func, typename Float32Func, typename Uint8Func, typename Int32Func, typename BooleanFunc,
+ typename ... Params>
bool IsSupportedForDataTypeGeneric(Optional<std::string&> reasonIfUnsupported,
DataType dataType,
Float16Func float16FuncPtr,
Float32Func float32FuncPtr,
Uint8Func uint8FuncPtr,
Int32Func int32FuncPtr,
+ BooleanFunc booleanFuncPtr,
Params&&... params)
{
switch(dataType)
@@ -31,6 +33,8 @@ bool IsSupportedForDataTypeGeneric(Optional<std::string&> reasonIfUnsupported,
return uint8FuncPtr(reasonIfUnsupported, std::forward<Params>(params)...);
case DataType::Signed32:
return int32FuncPtr(reasonIfUnsupported, std::forward<Params>(params)...);
+ case DataType::Boolean:
+ return booleanFuncPtr(reasonIfUnsupported, std::forward<Params>(params)...);
default:
return false;
}
diff --git a/src/armnn/test/TensorHelpers.hpp b/src/armnn/test/TensorHelpers.hpp
index 06818d3918..fcaa0772a0 100644
--- a/src/armnn/test/TensorHelpers.hpp
+++ b/src/armnn/test/TensorHelpers.hpp
@@ -67,11 +67,16 @@ bool SelectiveCompare(T a, T b)
return SelectiveComparer<T, armnn::IsQuantizedType<T>()>::Compare(a, b);
};
-
+template<typename T>
+bool SelectiveCompareBoolean(T a, T b)
+{
+ return (((a == 0) && (b == 0)) || ((a != 0) && (b != 0)));
+};
template <typename T, std::size_t n>
boost::test_tools::predicate_result CompareTensors(const boost::multi_array<T, n>& a,
- const boost::multi_array<T, n>& b)
+ const boost::multi_array<T, n>& b,
+ bool compareBoolean = false)
{
// Checks they are same shape.
for (unsigned int i=0; i<n; i++)
@@ -103,7 +108,17 @@ boost::test_tools::predicate_result CompareTensors(const boost::multi_array<T, n
while (true)
{
- bool comparison = SelectiveCompare(a(indices), b(indices));
+ bool comparison;
+ // As true for uint8_t is non-zero (1-255) we must have a dedicated compare for Booleans.
+ if(compareBoolean)
+ {
+ comparison = SelectiveCompareBoolean(a(indices), b(indices));
+ }
+ else
+ {
+ comparison = SelectiveCompare(a(indices), b(indices));
+ }
+
if (!comparison)
{
++numFailedElements;
diff --git a/src/armnn/test/UnitTests.hpp b/src/armnn/test/UnitTests.hpp
index f489ca030c..04e91ad85e 100644
--- a/src/armnn/test/UnitTests.hpp
+++ b/src/armnn/test/UnitTests.hpp
@@ -41,7 +41,7 @@ void CompareTestResultIfSupported(const std::string& testName, const LayerTestRe
"The test name does not match the supportedness it is reporting");
if (testResult.supported)
{
- BOOST_TEST(CompareTensors(testResult.output, testResult.outputExpected));
+ BOOST_TEST(CompareTensors(testResult.output, testResult.outputExpected, testResult.compareBoolean));
}
}
diff --git a/src/armnnTfParser/TfParser.cpp b/src/armnnTfParser/TfParser.cpp
index 43b0d86000..80962748ce 100755
--- a/src/armnnTfParser/TfParser.cpp
+++ b/src/armnnTfParser/TfParser.cpp
@@ -1741,6 +1741,33 @@ std::pair<armnn::IOutputSlot*, armnn::IOutputSlot*> TfParser::ProcessElementwise
return {input0Slot, input1Slot};
}
+ParsedTfOperationPtr TfParser::ProcessComparisonLayer(
+ IOutputSlot* input0Slot,
+ IOutputSlot* input1Slot,
+ IConnectableLayer* const layer,
+ const tensorflow::NodeDef& nodeDef)
+{
+ input0Slot->Connect(layer->GetInputSlot(0));
+ input1Slot->Connect(layer->GetInputSlot(1));
+
+ TensorInfo outputInfo = input0Slot->GetTensorInfo();
+ outputInfo.SetDataType(DataType::Boolean);
+ std::vector<unsigned int> outputShape;
+
+ const TensorShape& input0Shape = input0Slot->GetTensorInfo().GetShape();
+ const TensorShape& input1Shape = input1Slot->GetTensorInfo().GetShape();
+
+ for (unsigned int i = 0; i < input0Shape.GetNumDimensions(); i++)
+ {
+ outputShape.push_back(std::max(input0Shape[i], input1Shape[i]));
+ }
+
+ outputInfo.SetShape(TensorShape(input0Shape.GetNumDimensions(), outputShape.data()));
+ layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+ return std::make_unique<SingleLayerParsedTfOperation>(this, nodeDef, layer);
+}
+
ParsedTfOperationPtr TfParser::ProcessElementwiseLayer(
IOutputSlot* input0Slot,
IOutputSlot* input1Slot,
@@ -1812,7 +1839,7 @@ ParsedTfOperationPtr TfParser::ParseGreater(const tensorflow::NodeDef& nodeDef,
IConnectableLayer* const layer = m_Network->AddGreaterLayer(nodeDef.name().c_str());
- return ProcessElementwiseLayer(input0Slot, input1Slot, layer, nodeDef);
+ return ProcessComparisonLayer(input0Slot, input1Slot, layer, nodeDef);
}
ParsedTfOperationPtr TfParser::ParseEqual(const tensorflow::NodeDef& nodeDef,
@@ -1824,7 +1851,7 @@ ParsedTfOperationPtr TfParser::ParseEqual(const tensorflow::NodeDef& nodeDef,
IConnectableLayer* const layer = m_Network->AddEqualLayer(nodeDef.name().c_str());
- return ProcessElementwiseLayer(input0Slot, input1Slot, layer, nodeDef);
+ return ProcessComparisonLayer(input0Slot, input1Slot, layer, nodeDef);
}
ParsedTfOperationPtr TfParser::ParseMinimum(const tensorflow::NodeDef& nodeDef,
diff --git a/src/armnnTfParser/TfParser.hpp b/src/armnnTfParser/TfParser.hpp
index 9a7d7827c3..2b809419de 100644
--- a/src/armnnTfParser/TfParser.hpp
+++ b/src/armnnTfParser/TfParser.hpp
@@ -187,6 +187,12 @@ private:
std::pair<armnn::IOutputSlot*, armnn::IOutputSlot*> ProcessElementwiseInputSlots(
const tensorflow::NodeDef& nodeDef, const std::string& layerName);
+ ParsedTfOperationPtr ProcessComparisonLayer(
+ armnn::IOutputSlot* input0Slot,
+ armnn::IOutputSlot* input1Slot,
+ armnn::IConnectableLayer* const layer,
+ const tensorflow::NodeDef& nodeDef);
+
ParsedTfOperationPtr ProcessElementwiseLayer(
armnn::IOutputSlot* input0Slot,
armnn::IOutputSlot* input1Slot,
diff --git a/src/armnnTfParser/test/Equal.cpp b/src/armnnTfParser/test/Equal.cpp
index 43a1c6abb5..2dce822b0f 100644
--- a/src/armnnTfParser/test/Equal.cpp
+++ b/src/armnnTfParser/test/Equal.cpp
@@ -91,9 +91,9 @@ struct EqualTwoByTwo : public EqualFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseEqualTwoByTwo, EqualTwoByTwo)
{
- RunTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } },
- { "input1", { 1.0f, 5.0f, 2.0f, 2.0f } } },
- { { "output", { 1.0f, 0.0f, 0.0f, 1.0f } } });
+ RunComparisonTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } },
+ { "input1", { 1.0f, 5.0f, 2.0f, 2.0f } } },
+ { { "output", { 1, 0, 0, 1 } } });
}
struct EqualBroadcast1DAnd4D : public EqualFixtureAutoSetup
@@ -103,9 +103,9 @@ struct EqualBroadcast1DAnd4D : public EqualFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseEqualBroadcast1DToTwoByTwo, EqualBroadcast1DAnd4D)
{
- RunTest<4>({ { "input0", { 2.0f } },
- { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } },
- { { "output", { 0.0f, 1.0f, 0.0f, 1.0f } } });
+ RunComparisonTest<4>({ { "input0", { 2.0f } },
+ { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } },
+ { { "output", { 0, 1, 0, 1 } } });
}
struct EqualBroadcast4DAnd1D : public EqualFixtureAutoSetup
@@ -115,9 +115,9 @@ struct EqualBroadcast4DAnd1D : public EqualFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseEqualBroadcast4DAnd1D, EqualBroadcast4DAnd1D)
{
- RunTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } },
- { "input1", { 3.0f } } },
- { { "output", { 0.0f, 0.0f, 1.0f, 0.0f } } });
+ RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } },
+ { "input1", { 3.0f } } },
+ { { "output", { 0, 0, 1, 0 } } });
}
struct EqualMultiDimBroadcast : public EqualFixtureAutoSetup
@@ -127,13 +127,13 @@ struct EqualMultiDimBroadcast : public EqualFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseEqualMultiDimBroadcast, EqualMultiDimBroadcast)
{
- RunTest<4>({ { "input0", { 1.0f, 2.0f } },
- { "input1", { 1.0f, 2.0f, 3.0f,
- 3.0f, 2.0f, 2.0f } } },
- { { "output", { 1.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 1.0f } } });
+ RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f } },
+ { "input1", { 1.0f, 2.0f, 3.0f,
+ 3.0f, 2.0f, 2.0f } } },
+ { { "output", { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 1 } } });
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/armnnTfParser/test/Greater.cpp b/src/armnnTfParser/test/Greater.cpp
index f11c199599..d1e793987b 100644
--- a/src/armnnTfParser/test/Greater.cpp
+++ b/src/armnnTfParser/test/Greater.cpp
@@ -91,9 +91,9 @@ struct GreaterFixtureTwoByTwo : public GreaterFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseGreaterTwoByTwo, GreaterFixtureTwoByTwo)
{
- RunTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 4.0f} },
- { "input1", { 1.0f, 5.0f, 2.0f, 2.0f} } },
- { { "output", { 0.0f, 0.0f, 1.0f, 1.0f} } });
+ RunComparisonTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 4.0f} },
+ { "input1", { 1.0f, 5.0f, 2.0f, 2.0f} } },
+ { { "output", { 0, 0, 1, 1} } });
}
struct GreaterBroadcast1DAnd4D : public GreaterFixtureAutoSetup
@@ -103,9 +103,9 @@ struct GreaterBroadcast1DAnd4D : public GreaterFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseGreaterBroadcast1DToTwoByTwo, GreaterBroadcast1DAnd4D)
{
- RunTest<4>({ { "input0", { 2.0f } },
- { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } },
- { { "output", { 1.0f, 0.0f, 0.0f, 0.0f } } });
+ RunComparisonTest<4>({ { "input0", { 2.0f } },
+ { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } },
+ { { "output", { 1, 0, 0, 0 } } });
}
struct GreaterBroadcast4DAnd1D : public GreaterFixtureAutoSetup
@@ -115,9 +115,9 @@ struct GreaterBroadcast4DAnd1D : public GreaterFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseGreaterBroadcast4DAnd1D, GreaterBroadcast4DAnd1D)
{
- RunTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } },
- { "input1", { 3.0f } } },
- { { "output", { 0.0f, 0.0f, 0.0f, 0.0f } } });
+ RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } },
+ { "input1", { 3.0f } } },
+ { { "output", { 0, 0, 0, 0 } } });
}
struct GreaterMultiDimBroadcast : public GreaterFixtureAutoSetup
@@ -127,13 +127,13 @@ struct GreaterMultiDimBroadcast : public GreaterFixtureAutoSetup
BOOST_FIXTURE_TEST_CASE(ParseGreaterMultiDimBroadcast, GreaterMultiDimBroadcast)
{
- RunTest<4>({ { "input0", { 1.0f, 2.0f } },
- { "input1", { 1.0f, 2.0f, 3.0f,
- 3.0f, 2.0f, 2.0f } } },
- { { "output", { 0.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f } } });
+ RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f } },
+ { "input1", { 1.0f, 2.0f, 3.0f,
+ 3.0f, 2.0f, 2.0f } } },
+ { { "output", { 0, 0, 0,
+ 1, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0 } } });
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/armnnUtils/ParserPrototxtFixture.hpp b/src/armnnUtils/ParserPrototxtFixture.hpp
index be35e460cf..7ae0742b8e 100644
--- a/src/armnnUtils/ParserPrototxtFixture.hpp
+++ b/src/armnnUtils/ParserPrototxtFixture.hpp
@@ -53,11 +53,17 @@ struct ParserPrototxtFixture
template <std::size_t NumOutputDimensions>
void RunTest(const std::vector<float>& inputData, const std::vector<float>& expectedOutputData);
+ /// Executes the network with the given input tensor and checks the result against the given output tensor.
+ /// Calls RunTest with output type of uint8_t for checking comparison operators.
+ template <std::size_t NumOutputDimensions>
+ void RunComparisonTest(const std::map<std::string, std::vector<float>>& inputData,
+ const std::map<std::string, std::vector<uint8_t>>& expectedOutputData);
+
/// Executes the network with the given input tensors and checks the results against the given output tensors.
/// This overload supports multiple inputs and multiple outputs, identified by name.
- template <std::size_t NumOutputDimensions>
+ template <std::size_t NumOutputDimensions, typename T = float>
void RunTest(const std::map<std::string, std::vector<float>>& inputData,
- const std::map<std::string, std::vector<float>>& expectedOutputData);
+ const std::map<std::string, std::vector<T>>& expectedOutputData);
std::string m_Prototext;
std::unique_ptr<TParser, void(*)(TParser* parser)> m_Parser;
@@ -162,15 +168,24 @@ armnn::IOptimizedNetworkPtr ParserPrototxtFixture<TParser>::SetupOptimizedNetwor
template<typename TParser>
template <std::size_t NumOutputDimensions>
void ParserPrototxtFixture<TParser>::RunTest(const std::vector<float>& inputData,
- const std::vector<float>& expectedOutputData)
+ const std::vector<float>& expectedOutputData)
{
RunTest<NumOutputDimensions>({ { m_SingleInputName, inputData } }, { { m_SingleOutputName, expectedOutputData } });
}
template<typename TParser>
template <std::size_t NumOutputDimensions>
+void ParserPrototxtFixture<TParser>::RunComparisonTest(const std::map<std::string, std::vector<float>>& inputData,
+ const std::map<std::string, std::vector<uint8_t>>&
+ expectedOutputData)
+{
+ RunTest<NumOutputDimensions, uint8_t>(inputData, expectedOutputData);
+}
+
+template<typename TParser>
+template <std::size_t NumOutputDimensions, typename T>
void ParserPrototxtFixture<TParser>::RunTest(const std::map<std::string, std::vector<float>>& inputData,
- const std::map<std::string, std::vector<float>>& expectedOutputData)
+ const std::map<std::string, std::vector<T>>& expectedOutputData)
{
using BindingPointInfo = std::pair<armnn::LayerBindingId, armnn::TensorInfo>;
@@ -183,12 +198,12 @@ void ParserPrototxtFixture<TParser>::RunTest(const std::map<std::string, std::ve
}
// Allocates storage for the output tensors to be written to and sets up the armnn output tensors.
- std::map<std::string, boost::multi_array<float, NumOutputDimensions>> outputStorage;
+ std::map<std::string, boost::multi_array<T, NumOutputDimensions>> outputStorage;
armnn::OutputTensors outputTensors;
for (auto&& it : expectedOutputData)
{
BindingPointInfo bindingInfo = m_Parser->GetNetworkOutputBindingInfo(it.first);
- outputStorage.emplace(it.first, MakeTensor<float, NumOutputDimensions>(bindingInfo.second));
+ outputStorage.emplace(it.first, MakeTensor<T, NumOutputDimensions>(bindingInfo.second));
outputTensors.push_back(
{ bindingInfo.first, armnn::Tensor(bindingInfo.second, outputStorage.at(it.first).data()) });
}
@@ -243,8 +258,15 @@ void ParserPrototxtFixture<TParser>::RunTest(const std::map<std::string, std::ve
}
}
- auto outputExpected = MakeTensor<float, NumOutputDimensions>(bindingInfo.second, it.second);
- BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first]));
+ auto outputExpected = MakeTensor<T, NumOutputDimensions>(bindingInfo.second, it.second);
+ if (std::is_same<T, uint8_t>::value)
+ {
+ BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first], true));
+ }
+ else
+ {
+ BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first]));
+ }
}
}
diff --git a/src/backends/backendsCommon/MakeWorkloadHelper.hpp b/src/backends/backendsCommon/MakeWorkloadHelper.hpp
index 7784cc6d4d..2d54335355 100644
--- a/src/backends/backendsCommon/MakeWorkloadHelper.hpp
+++ b/src/backends/backendsCommon/MakeWorkloadHelper.hpp
@@ -38,7 +38,7 @@ struct MakeWorkloadForType<NullWorkload>
// Makes a workload for one the specified types based on the data type requirements of the tensorinfo.
// Specify type void as the WorkloadType for unsupported DataType/WorkloadType combos.
template <typename Float16Workload, typename Float32Workload, typename Uint8Workload, typename Int32Workload,
- typename QueueDescriptorType, typename... Args>
+ typename BooleanWorkload, typename QueueDescriptorType, typename... Args>
std::unique_ptr<IWorkload> MakeWorkloadHelper(const QueueDescriptorType& descriptor,
const WorkloadInfo& info,
Args&&... args)
@@ -47,8 +47,10 @@ std::unique_ptr<IWorkload> MakeWorkloadHelper(const QueueDescriptorType& descrip
info.m_InputTensorInfos[0].GetDataType()
: info.m_OutputTensorInfos[0].GetDataType();
- BOOST_ASSERT(info.m_InputTensorInfos.empty() || info.m_OutputTensorInfos.empty()
- || info.m_InputTensorInfos[0].GetDataType() == info.m_OutputTensorInfos[0].GetDataType());
+ BOOST_ASSERT(info.m_InputTensorInfos.empty() ||
+ info.m_OutputTensorInfos.empty() ||
+ ((info.m_InputTensorInfos[0].GetDataType() == info.m_OutputTensorInfos[0].GetDataType()) ||
+ info.m_OutputTensorInfos[0].GetDataType() == armnn::DataType::Boolean));
switch (dataType)
{
@@ -60,6 +62,8 @@ std::unique_ptr<IWorkload> MakeWorkloadHelper(const QueueDescriptorType& descrip
return MakeWorkloadForType<Uint8Workload>::Func(descriptor, info, std::forward<Args>(args)...);
case DataType::Signed32:
return MakeWorkloadForType<Int32Workload>::Func(descriptor, info, std::forward<Args>(args)...);
+ case DataType::Boolean:
+ return MakeWorkloadForType<BooleanWorkload>::Func(descriptor, info, std::forward<Args>(args)...);
default:
BOOST_ASSERT_MSG(false, "Unknown DataType.");
return nullptr;
@@ -67,16 +71,18 @@ std::unique_ptr<IWorkload> MakeWorkloadHelper(const QueueDescriptorType& descrip
}
// Makes a workload for one the specified types based on the data type requirements of the tensorinfo.
-// Calling this method is the equivalent of calling the three typed MakeWorkload method with <FloatWorkload,
-// FloatWorkload, Uint8Workload>.
+// Calling this method is the equivalent of calling the five typed MakeWorkload method with <FloatWorkload,
+// FloatWorkload, Uint8Workload, NullWorkload, NullWorkload>.
// Specify type void as the WorkloadType for unsupported DataType/WorkloadType combos.
template <typename FloatWorkload, typename Uint8Workload, typename QueueDescriptorType, typename... Args>
std::unique_ptr<IWorkload> MakeWorkloadHelper(const QueueDescriptorType& descriptor,
const WorkloadInfo& info,
Args&&... args)
{
- return MakeWorkloadHelper<FloatWorkload, FloatWorkload, Uint8Workload, NullWorkload>(descriptor, info,
- std::forward<Args>(args)...);
+ return MakeWorkloadHelper<FloatWorkload, FloatWorkload, Uint8Workload, NullWorkload, NullWorkload>(
+ descriptor,
+ info,
+ std::forward<Args>(args)...);
}
} //namespace
diff --git a/src/backends/backendsCommon/Workload.hpp b/src/backends/backendsCommon/Workload.hpp
index 34d13635ba..4d14adbf54 100644
--- a/src/backends/backendsCommon/Workload.hpp
+++ b/src/backends/backendsCommon/Workload.hpp
@@ -165,6 +165,19 @@ template <typename QueueDescriptor>
using Int32Workload = TypedWorkload<QueueDescriptor, armnn::DataType::Signed32>;
template <typename QueueDescriptor>
+using BooleanWorkload = TypedWorkload<QueueDescriptor, armnn::DataType::Boolean>;
+
+template <typename QueueDescriptor>
+using BaseFloat32ComparisonWorkload = MultiTypedWorkload<QueueDescriptor,
+ armnn::DataType::Float32,
+ armnn::DataType::Boolean>;
+
+template <typename QueueDescriptor>
+using BaseUint8ComparisonWorkload = MultiTypedWorkload<QueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>;
+
+template <typename QueueDescriptor>
using Float16ToFloat32Workload = MultiTypedWorkload<QueueDescriptor,
armnn::DataType::Float16,
armnn::DataType::Float32>;
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index 05f4e317a9..9714b02a80 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -1025,6 +1025,11 @@ void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
"EqualQueueDescriptor",
"first input",
"second input");
+
+ if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Boolean)
+ {
+ throw InvalidArgumentException("EqualQueueDescriptor: Output tensor type must be Boolean.");
+ }
}
void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
@@ -1038,6 +1043,11 @@ void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
"GreaterQueueDescriptor",
"first input",
"second input");
+
+ if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Boolean)
+ {
+ throw InvalidArgumentException("GreaterQueueDescriptor: Output tensor type must be Boolean.");
+ }
}
void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
diff --git a/src/backends/backendsCommon/test/ArithmeticTestImpl.hpp b/src/backends/backendsCommon/test/ArithmeticTestImpl.hpp
index 1d6cf1d99b..6f685ebb42 100644
--- a/src/backends/backendsCommon/test/ArithmeticTestImpl.hpp
+++ b/src/backends/backendsCommon/test/ArithmeticTestImpl.hpp
@@ -17,7 +17,7 @@
namespace
{
-template<typename armnn::DataType DataType>
+template<armnn::DataType ArmnnTypeInput, armnn::DataType ArmnnTypeOutput>
INetworkPtr CreateArithmeticNetwork(const std::vector<TensorShape>& inputShapes,
const TensorShape& outputShape,
const LayerType type,
@@ -39,22 +39,25 @@ INetworkPtr CreateArithmeticNetwork(const std::vector<TensorShape>& inputShapes,
for (unsigned int i = 0; i < inputShapes.size(); ++i)
{
- TensorInfo inputTensorInfo(inputShapes[i], DataType, qScale, qOffset);
+ TensorInfo inputTensorInfo(inputShapes[i], ArmnnTypeInput, qScale, qOffset);
IConnectableLayer* input = net->AddInputLayer(boost::numeric_cast<LayerBindingId>(i));
Connect(input, arithmeticLayer, inputTensorInfo, 0, i);
}
- TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset);
+ TensorInfo outputTensorInfo(outputShape, ArmnnTypeOutput, qScale, qOffset);
IConnectableLayer* output = net->AddOutputLayer(0, "output");
Connect(arithmeticLayer, output, outputTensorInfo, 0, 0);
return net;
}
-template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+template<armnn::DataType ArmnnInputType,
+ armnn::DataType ArmnnOutputType,
+ typename TInput = armnn::ResolveType<ArmnnInputType>,
+ typename TOutput = armnn::ResolveType<ArmnnOutputType>>
void ArithmeticSimpleEndToEnd(const std::vector<BackendId>& backends,
const LayerType type,
- const std::vector<T> expectedOutput)
+ const std::vector<TOutput> expectedOutput)
{
using namespace armnn;
@@ -62,26 +65,29 @@ void ArithmeticSimpleEndToEnd(const std::vector<BackendId>& backends,
const TensorShape& outputShape = { 2, 2, 2, 2 };
// Builds up the structure of the network
- INetworkPtr net = CreateArithmeticNetwork<ArmnnType>(inputShapes, outputShape, type);
+ INetworkPtr net = CreateArithmeticNetwork<ArmnnInputType, ArmnnOutputType>(inputShapes, outputShape, type);
BOOST_TEST_CHECKPOINT("create a network");
- const std::vector<T> input0({ 1, 1, 1, 1, 5, 5, 5, 5,
- 3, 3, 3, 3, 4, 4, 4, 4 });
+ const std::vector<TInput> input0({ 1, 1, 1, 1, 5, 5, 5, 5,
+ 3, 3, 3, 3, 4, 4, 4, 4 });
- const std::vector<T> input1({ 1, 1, 1, 1, 3, 3, 3, 3,
- 5, 5, 5, 5, 4, 4, 4, 4 });
+ const std::vector<TInput> input1({ 1, 1, 1, 1, 3, 3, 3, 3,
+ 5, 5, 5, 5, 4, 4, 4, 4 });
- std::map<int, std::vector<T>> inputTensorData = {{ 0, input0 }, { 1, input1 }};
- std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput }};
+ std::map<int, std::vector<TInput>> inputTensorData = {{ 0, input0 }, { 1, input1 }};
+ std::map<int, std::vector<TOutput>> expectedOutputData = {{ 0, expectedOutput }};
- EndToEndLayerTestImpl<T>(move(net), inputTensorData, expectedOutputData, backends);
+ EndToEndLayerTestImpl<TInput, TOutput>(move(net), inputTensorData, expectedOutputData, backends);
}
-template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+template<armnn::DataType ArmnnInputType,
+ armnn::DataType ArmnnOutputType,
+ typename TInput = armnn::ResolveType<ArmnnInputType>,
+ typename TOutput = armnn::ResolveType<ArmnnOutputType>>
void ArithmeticBroadcastEndToEnd(const std::vector<BackendId>& backends,
const LayerType type,
- const std::vector<T> expectedOutput)
+ const std::vector<TOutput> expectedOutput)
{
using namespace armnn;
@@ -89,19 +95,19 @@ void ArithmeticBroadcastEndToEnd(const std::vector<BackendId>& backends,
const TensorShape& outputShape = { 1, 2, 2, 3 };
// Builds up the structure of the network
- INetworkPtr net = CreateArithmeticNetwork<ArmnnType>(inputShapes, outputShape, type);
+ INetworkPtr net = CreateArithmeticNetwork<ArmnnInputType, ArmnnOutputType>(inputShapes, outputShape, type);
BOOST_TEST_CHECKPOINT("create a network");
- const std::vector<T> input0({ 1, 2, 3, 1, 0, 6,
- 7, 8, 9, 10, 11, 12 });
+ const std::vector<TInput> input0({ 1, 2, 3, 1, 0, 6,
+ 7, 8, 9, 10, 11, 12 });
- const std::vector<T> input1({ 1, 1, 3 });
+ const std::vector<TInput> input1({ 1, 1, 3 });
- std::map<int, std::vector<T>> inputTensorData = {{ 0, input0 }, { 1, input1 }};
- std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput }};
+ std::map<int, std::vector<TInput>> inputTensorData = {{ 0, input0 }, { 1, input1 }};
+ std::map<int, std::vector<TOutput>> expectedOutputData = {{ 0, expectedOutput }};
- EndToEndLayerTestImpl<T>(move(net), inputTensorData, expectedOutputData, backends);
+ EndToEndLayerTestImpl<TInput, TOutput>(move(net), inputTensorData, expectedOutputData, backends);
}
} // anonymous namespace
diff --git a/src/backends/backendsCommon/test/EndToEndTestImpl.hpp b/src/backends/backendsCommon/test/EndToEndTestImpl.hpp
index 15a3937aca..7d2b091e42 100644
--- a/src/backends/backendsCommon/test/EndToEndTestImpl.hpp
+++ b/src/backends/backendsCommon/test/EndToEndTestImpl.hpp
@@ -102,10 +102,10 @@ inline bool ConstantUsageUint8Test(const std::vector<BackendId>& backends)
);
}
-template<typename T>
+template<typename TInput, typename TOutput>
void EndToEndLayerTestImpl(INetworkPtr network,
- const std::map<int, std::vector<T>>& inputTensorData,
- const std::map<int, std::vector<T>>& expectedOutputData,
+ const std::map<int, std::vector<TInput>>& inputTensorData,
+ const std::map<int, std::vector<TOutput>>& expectedOutputData,
std::vector<BackendId> backends)
{
// Create runtime in which test will run
@@ -128,10 +128,10 @@ void EndToEndLayerTestImpl(INetworkPtr network,
}
OutputTensors outputTensors;
outputTensors.reserve(expectedOutputData.size());
- std::map<int, std::vector<T>> outputStorage;
+ std::map<int, std::vector<TOutput>> outputStorage;
for (auto&& it : expectedOutputData)
{
- std::vector<T> out(it.second.size());
+ std::vector<TOutput> out(it.second.size());
outputStorage.emplace(it.first, out);
outputTensors.push_back({it.first,
Tensor(runtime->GetOutputTensorInfo(netId, it.first),
@@ -144,7 +144,7 @@ void EndToEndLayerTestImpl(INetworkPtr network,
// Checks the results.
for (auto&& it : expectedOutputData)
{
- std::vector<T> out = outputStorage.at(it.first);
+ std::vector<TOutput> out = outputStorage.at(it.first);
BOOST_TEST(it.second == out);
}
}
diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp
index 95fa50b89c..6060b30928 100644
--- a/src/backends/backendsCommon/test/LayerTests.cpp
+++ b/src/backends/backendsCommon/test/LayerTests.cpp
@@ -1783,66 +1783,98 @@ std::unique_ptr<armnn::IWorkload> CreateWorkload<armnn::GreaterQueueDescriptor>(
}
namespace {
- template <typename Descriptor, armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
- LayerTestResult<T, 4> ElementwiseTestHelper
- (armnn::IWorkloadFactory & workloadFactory,
- const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,
- const unsigned int shape0[4], std::vector<T> values0,
- const unsigned int shape1[4], std::vector<T> values1,
- const unsigned int outShape[4], std::vector<T> outValues,
- float qScale = 0.0f, int qOffset = 0)
- {
- const size_t dimensionCount = 4;
- armnn::TensorInfo inputTensorInfo0{dimensionCount, shape0, ArmnnType};
- armnn::TensorInfo inputTensorInfo1{dimensionCount, shape1, ArmnnType};
- armnn::TensorInfo outputTensorInfo{dimensionCount, outShape, ArmnnType};
- auto input0 = MakeTensor<T, 4>(inputTensorInfo0, values0);
- auto input1 = MakeTensor<T, 4>(inputTensorInfo1, values1);
+template <typename Descriptor,
+ armnn::DataType ArmnnTypeInput,
+ armnn::DataType ArmnnTypeOutput,
+ typename TInput = armnn::ResolveType<ArmnnTypeInput>,
+ typename TOutput = armnn::ResolveType<ArmnnTypeOutput>>
+LayerTestResult<TOutput, 4> ElementwiseTestHelper(
+ armnn::IWorkloadFactory & workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,
+ const unsigned int shape0[4], std::vector<TInput> values0,
+ const unsigned int shape1[4], std::vector<TInput> values1,
+ const unsigned int outShape[4], std::vector<TOutput> outValues,
+ float qScale = 0.0f, int qOffset = 0)
+{
+ const size_t dimensionCount = 4;
+ armnn::TensorInfo inputTensorInfo0{dimensionCount, shape0, ArmnnTypeInput};
+ armnn::TensorInfo inputTensorInfo1{dimensionCount, shape1, ArmnnTypeInput};
+ armnn::TensorInfo outputTensorInfo{dimensionCount, outShape, ArmnnTypeOutput};
- if (armnn::IsQuantizedType<T>())
- {
- inputTensorInfo0.SetQuantizationScale(qScale);
- inputTensorInfo0.SetQuantizationOffset(qOffset);
+ auto input0 = MakeTensor<TInput, 4>(inputTensorInfo0, values0);
+ auto input1 = MakeTensor<TInput, 4>(inputTensorInfo1, values1);
- inputTensorInfo1.SetQuantizationScale(qScale);
- inputTensorInfo1.SetQuantizationOffset(qOffset);
+ if (armnn::IsQuantizedType<TInput>())
+ {
+ inputTensorInfo0.SetQuantizationScale(qScale);
+ inputTensorInfo0.SetQuantizationOffset(qOffset);
- outputTensorInfo.SetQuantizationScale(qScale);
- outputTensorInfo.SetQuantizationOffset(qOffset);
- }
+ inputTensorInfo1.SetQuantizationScale(qScale);
+ inputTensorInfo1.SetQuantizationOffset(qOffset);
- LayerTestResult<T,4> ret(outputTensorInfo);
+ outputTensorInfo.SetQuantizationScale(qScale);
+ outputTensorInfo.SetQuantizationOffset(qOffset);
+ }
- std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
- std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
- std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
+ LayerTestResult<TOutput,4> ret(outputTensorInfo);
- Descriptor data;
- armnn::WorkloadInfo info;
- AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get());
- AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
- AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
- auto workload = CreateWorkload<Descriptor>(workloadFactory, info, data);
+ if(ArmnnTypeOutput == armnn::DataType::Boolean)
+ {
+ ret.compareBoolean = true;
+ }
- inputHandle0->Allocate();
- inputHandle1->Allocate();
- outputHandle->Allocate();
+ std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
+ std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
+ std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
- CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
- CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
+ Descriptor data;
+ armnn::WorkloadInfo info;
+ AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get());
+ AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
+ AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
+ auto workload = CreateWorkload<Descriptor>(workloadFactory, info, data);
+
+ inputHandle0->Allocate();
+ inputHandle1->Allocate();
+ outputHandle->Allocate();
- ExecuteWorkload(*workload, memoryManager);
+ CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
+ CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
- CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
+ ExecuteWorkload(*workload, memoryManager);
- ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outValues);
- return ret;
- }
+ CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
+
+ ret.outputExpected = MakeTensor<TOutput, 4>(outputTensorInfo, outValues);
+ return ret;
}
-LayerTestResult<float, 4> EqualSimpleTest(armnn::IWorkloadFactory& workloadFactory,
- const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+template <typename Descriptor, armnn::DataType ArmnnT, typename T = armnn::ResolveType<ArmnnT>>
+LayerTestResult<T, 4> ElementwiseTestHelper(
+ armnn::IWorkloadFactory & workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,
+ const unsigned int shape0[4], std::vector<T> values0,
+ const unsigned int shape1[4], std::vector<T> values1,
+ const unsigned int outShape[4], std::vector<T> outValues,
+ float qScale = 0.0f, int qOffset = 0)
+{
+ return ElementwiseTestHelper<Descriptor, ArmnnT, ArmnnT>
+ (workloadFactory,
+ memoryManager,
+ shape0,
+ values0,
+ shape1,
+ values1,
+ outShape,
+ outValues,
+ qScale,
+ qOffset);
+}
+}
+
+LayerTestResult<uint8_t, 4> EqualSimpleTest(armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
const unsigned int width = 2;
const unsigned int height = 2;
@@ -1857,10 +1889,10 @@ LayerTestResult<float, 4> EqualSimpleTest(armnn::IWorkloadFactory& workloadFacto
std::vector<float> input1({ 1, 1, 1, 1, 3, 3, 3, 3,
5, 5, 5, 5, 4, 4, 4, 4 });
- std::vector<float> output({ 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 1 });
+ std::vector<uint8_t> output({ 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1 });
- return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32>(
+ return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape,
@@ -1871,7 +1903,7 @@ LayerTestResult<float, 4> EqualSimpleTest(armnn::IWorkloadFactory& workloadFacto
output);
}
-LayerTestResult<float, 4> EqualBroadcast1ElementTest(
+LayerTestResult<uint8_t, 4> EqualBroadcast1ElementTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
@@ -1881,9 +1913,9 @@ LayerTestResult<float, 4> EqualBroadcast1ElementTest(
unsigned int shape1[] = { 1, 1, 1, 1 };
std::vector<float> input1({ 1 });
- std::vector<float> output({ 1, 0, 0, 0, 0, 0, 0, 0});
+ std::vector<uint8_t> output({ 1, 0, 0, 0, 0, 0, 0, 0});
- return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32>(
+ return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -1894,7 +1926,7 @@ LayerTestResult<float, 4> EqualBroadcast1ElementTest(
output);
}
-LayerTestResult<float, 4> EqualBroadcast1DVectorTest(
+LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
@@ -1906,10 +1938,10 @@ LayerTestResult<float, 4> EqualBroadcast1DVectorTest(
std::vector<float> input1({ 1, 2, 3});
- std::vector<float> output({ 1, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0 });
+ std::vector<uint8_t> output({ 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0 });
- return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32>(
+ return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -1928,7 +1960,7 @@ LayerTestResult<uint8_t, 4> EqualUint8Test(
// See dequantized values to the right.
std::vector<uint8_t> input0({ 1, 1, 1, 1, 6, 6, 6, 6,
- 3, 3, 3, 3, 5, 5, 5, 5 });
+ 3, 3, 3, 3, 7, 7, 7, 7 });
std::vector<uint8_t> input1({ 2, 2, 2, 2, 6, 6, 6, 6,
3, 3, 3, 3, 5, 5, 5, 5 });
@@ -1936,7 +1968,9 @@ LayerTestResult<uint8_t, 4> EqualUint8Test(
std::vector<uint8_t> output({ 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0 });
- return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
+ return ElementwiseTestHelper<armnn::EqualQueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape,
@@ -1964,7 +1998,9 @@ LayerTestResult<uint8_t, 4> EqualBroadcast1ElementUint8Test(
std::vector<uint8_t> output({ 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 });
- return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
+ return ElementwiseTestHelper<armnn::EqualQueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -1992,7 +2028,9 @@ LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorUint8Test(
std::vector<uint8_t> output({ 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0 });
- return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
+ return ElementwiseTestHelper<armnn::EqualQueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -2005,7 +2043,7 @@ LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorUint8Test(
0);
}
-LayerTestResult<float, 4> GreaterSimpleTest(armnn::IWorkloadFactory& workloadFactory,
+LayerTestResult<uint8_t, 4> GreaterSimpleTest(armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
const unsigned int width = 2;
@@ -2021,10 +2059,10 @@ LayerTestResult<float, 4> GreaterSimpleTest(armnn::IWorkloadFactory& workloadFac
std::vector<float> input1({ 1, 1, 1, 1, 3, 3, 3, 3,
5, 5, 5, 5, 4, 4, 4, 4 });
- std::vector<float> output({ 0, 0, 0, 0, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0 });
+ std::vector<uint8_t> output({ 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0 });
- return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32>(
+ return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape,
@@ -2035,7 +2073,7 @@ LayerTestResult<float, 4> GreaterSimpleTest(armnn::IWorkloadFactory& workloadFac
output);
}
-LayerTestResult<float, 4> GreaterBroadcast1ElementTest(
+LayerTestResult<uint8_t, 4> GreaterBroadcast1ElementTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
@@ -2045,9 +2083,9 @@ LayerTestResult<float, 4> GreaterBroadcast1ElementTest(
unsigned int shape1[] = { 1, 1, 1, 1 };
std::vector<float> input1({ 1 });
- std::vector<float> output({ 0, 1, 1, 1, 1, 1, 1, 1});
+ std::vector<uint8_t> output({ 0, 1, 1, 1, 1, 1, 1, 1});
- return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32>(
+ return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -2058,7 +2096,7 @@ LayerTestResult<float, 4> GreaterBroadcast1ElementTest(
output);
}
-LayerTestResult<float, 4> GreaterBroadcast1DVectorTest(
+LayerTestResult<uint8_t, 4> GreaterBroadcast1DVectorTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
@@ -2070,10 +2108,10 @@ LayerTestResult<float, 4> GreaterBroadcast1DVectorTest(
std::vector<float> input1({ 1, 3, 2});
- std::vector<float> output({ 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1 });
+ std::vector<uint8_t> output({ 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1 });
- return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32>(
+ return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -2100,7 +2138,9 @@ LayerTestResult<uint8_t, 4> GreaterUint8Test(
std::vector<uint8_t> output({ 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0 });
- return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
+ return ElementwiseTestHelper<armnn::GreaterQueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape,
@@ -2128,7 +2168,9 @@ LayerTestResult<uint8_t, 4> GreaterBroadcast1ElementUint8Test(
std::vector<uint8_t> output({ 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1 });
- return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
+ return ElementwiseTestHelper<armnn::GreaterQueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -2156,7 +2198,9 @@ LayerTestResult<uint8_t, 4> GreaterBroadcast1DVectorUint8Test(
std::vector<uint8_t> output({ 0, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1 });
- return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
+ return ElementwiseTestHelper<armnn::GreaterQueueDescriptor,
+ armnn::DataType::QuantisedAsymm8,
+ armnn::DataType::Boolean>(
workloadFactory,
memoryManager,
shape0,
@@ -2235,7 +2279,7 @@ LayerTestResult<float, 4> MaximumBroadcast1DVectorTest(
std::vector<float> input1({ 1, 2, 3});
std::vector<float> output({ 1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12 });
+ 7, 8, 9, 10, 11, 12 });
return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::Float32>(
workloadFactory,
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index 16fe43212b..05d510e78e 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -47,11 +47,13 @@ struct LayerTestResult
output.resize(shape);
outputExpected.resize(shape);
supported = true;
+ compareBoolean = false;
}
boost::multi_array<T, n> output;
boost::multi_array<T, n> outputExpected;
bool supported;
+ bool compareBoolean;
};
LayerTestResult<float, 4> SimpleConvolution2d3x5Test(
@@ -909,15 +911,15 @@ LayerTestResult<uint8_t, 3> Concatenation3dDim2DiffInputDimsUint8Test(
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
bool useSubtensor);
-LayerTestResult<float, 4> EqualSimpleTest(
+LayerTestResult<uint8_t, 4> EqualSimpleTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
-LayerTestResult<float, 4> EqualBroadcast1ElementTest(
+LayerTestResult<uint8_t, 4> EqualBroadcast1ElementTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
-LayerTestResult<float, 4> EqualBroadcast1DVectorTest(
+LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
@@ -933,15 +935,15 @@ LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
-LayerTestResult<float, 4> GreaterSimpleTest(
+LayerTestResult<uint8_t, 4> GreaterSimpleTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
-LayerTestResult<float, 4> GreaterBroadcast1ElementTest(
+LayerTestResult<uint8_t, 4> GreaterBroadcast1ElementTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
-LayerTestResult<float, 4> GreaterBroadcast1DVectorTest(
+LayerTestResult<uint8_t, 4> GreaterBroadcast1DVectorTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
diff --git a/src/backends/backendsCommon/test/MergerTestImpl.hpp b/src/backends/backendsCommon/test/MergerTestImpl.hpp
index 2bdfe286c9..ec42b09ada 100644
--- a/src/backends/backendsCommon/test/MergerTestImpl.hpp
+++ b/src/backends/backendsCommon/test/MergerTestImpl.hpp
@@ -110,7 +110,7 @@ void MergerDim0EndToEnd(const std::vector<BackendId>& backends)
std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }, { 1,inputData }};
std::map<int, std::vector<T>> expectedOutputData = {{ 0,expectedOutput }};
- EndToEndLayerTestImpl<T>(move(net), inputTensorData, expectedOutputData, backends);
+ EndToEndLayerTestImpl<T, T>(move(net), inputTensorData, expectedOutputData, backends);
}
template<armnn::DataType ArmnnType>
diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp
index 3e35f9d52d..410cb04288 100644
--- a/src/backends/cl/ClLayerSupport.cpp
+++ b/src/backends/cl/ClLayerSupport.cpp
@@ -122,6 +122,7 @@ bool IsSupportedForDataTypeCl(Optional<std::string&> reasonIfUnsupported,
floatFuncPtr,
uint8FuncPtr,
&FalseFunc<>,
+ &FalseFunc<>,
std::forward<Params>(params)...);
}
@@ -267,7 +268,8 @@ bool ClLayerSupport::IsFloorSupported(const TensorInfo& input,
&FalseFuncF16<>,
&TrueFunc<>,
&FalseFuncU8<>,
- &FalseFuncI32<>);
+ &FalseFuncI32<>,
+ &FalseFuncU8<>);
}
bool ClLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
@@ -453,10 +455,14 @@ bool ClLayerSupport::IsNormalizationSupported(const TensorInfo& input,
bool ClLayerSupport::IsOutputSupported(const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported) const
{
- return IsSupportedForDataTypeCl(reasonIfUnsupported,
- output.GetDataType(),
- &TrueFunc<>,
- &TrueFunc<>);
+ return IsClBackendSupported(reasonIfUnsupported) &&
+ IsSupportedForDataTypeGeneric(reasonIfUnsupported,
+ output.GetDataType(),
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &FalseFuncI32<>,
+ &TrueFunc<>);
}
bool ClLayerSupport::IsPadSupported(const TensorInfo& input,
diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp
index 71c1b89c09..7a53257af1 100644
--- a/src/backends/cl/ClWorkloadFactory.cpp
+++ b/src/backends/cl/ClWorkloadFactory.cpp
@@ -126,7 +126,8 @@ std::unique_ptr<IWorkload> ClWorkloadFactory::CreateInput(const InputQueueDescri
std::unique_ptr<IWorkload> ClWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
const WorkloadInfo& info) const
{
- return MakeWorkload<CopyMemGenericWorkload, CopyMemGenericWorkload>(descriptor, info);
+ return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload, CopyMemGenericWorkload, NullWorkload,
+ CopyMemGenericWorkload>(descriptor, info);
}
std::unique_ptr<IWorkload> ClWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
diff --git a/src/backends/neon/NeonLayerSupport.cpp b/src/backends/neon/NeonLayerSupport.cpp
index 2f83c8f82a..9db7354e9e 100644
--- a/src/backends/neon/NeonLayerSupport.cpp
+++ b/src/backends/neon/NeonLayerSupport.cpp
@@ -72,6 +72,7 @@ bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
floatFuncPtr,
uint8FuncPtr,
&FalseFunc<>,
+ &FalseFunc<>,
std::forward<Params>(params)...);
}
@@ -214,7 +215,8 @@ bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
&FalseFuncF16<>,
&TrueFunc<>,
&FalseFuncU8<>,
- &FalseFuncI32<>);
+ &FalseFuncI32<>,
+ &FalseFuncU8<>);
}
bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
@@ -344,10 +346,14 @@ bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported) const
{
- return IsSupportedForDataTypeNeon(reasonIfUnsupported,
- output.GetDataType(),
- &TrueFunc<>,
- &TrueFunc<>);
+ return IsNeonBackendSupported(reasonIfUnsupported) &&
+ IsSupportedForDataTypeGeneric(reasonIfUnsupported,
+ output.GetDataType(),
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &FalseFuncI32<>,
+ &TrueFunc<>);
}
bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
diff --git a/src/backends/neon/NeonTensorHandle.hpp b/src/backends/neon/NeonTensorHandle.hpp
index 7206b6fc5a..b972043827 100644
--- a/src/backends/neon/NeonTensorHandle.hpp
+++ b/src/backends/neon/NeonTensorHandle.hpp
@@ -94,6 +94,7 @@ private:
armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
static_cast<float*>(memory));
break;
+ case arm_compute::DataType::U8:
case arm_compute::DataType::QASYMM8:
armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
static_cast<uint8_t*>(memory));
@@ -114,6 +115,7 @@ private:
armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
this->GetTensor());
break;
+ case arm_compute::DataType::U8:
case arm_compute::DataType::QASYMM8:
armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
this->GetTensor());
@@ -181,6 +183,7 @@ private:
armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
static_cast<float*>(memory));
break;
+ case arm_compute::DataType::U8:
case arm_compute::DataType::QASYMM8:
armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
static_cast<uint8_t*>(memory));
@@ -201,6 +204,7 @@ private:
armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
this->GetTensor());
break;
+ case arm_compute::DataType::U8:
case arm_compute::DataType::QASYMM8:
armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
this->GetTensor());
diff --git a/src/backends/neon/NeonWorkloadFactory.cpp b/src/backends/neon/NeonWorkloadFactory.cpp
index e7fac97c2c..e8a00d6b14 100644
--- a/src/backends/neon/NeonWorkloadFactory.cpp
+++ b/src/backends/neon/NeonWorkloadFactory.cpp
@@ -91,7 +91,8 @@ std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInput(const InputQueueDesc
std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
const WorkloadInfo& info) const
{
- return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload>(descriptor, info);
+ return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload,
+ CopyMemGenericWorkload, NullWorkload, CopyMemGenericWorkload>(descriptor, info);
}
std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index 45f108c2f8..78e44bd6a3 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -35,6 +35,7 @@ bool IsSupportedForDataTypeRef(Optional<std::string&> reasonIfUnsupported,
floatFuncPtr,
uint8FuncPtr,
&FalseFunc<Params...>,
+ &FalseFunc<Params...>,
std::forward<Params>(params)...);
}
@@ -111,7 +112,8 @@ bool RefLayerSupport::IsConstantSupported(const TensorInfo& output,
&FalseFunc<>,
&TrueFunc<>,
&TrueFunc<>,
- &TrueFunc<>);
+ &TrueFunc<>,
+ &FalseFunc<>);
}
bool RefLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
@@ -123,13 +125,15 @@ bool RefLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
&TrueFunc<>,
&FalseInputFuncF32<>,
&FalseFuncU8<>,
- &FalseFuncI32<>) &&
+ &FalseFuncI32<>,
+ &FalseFuncU8<>) &&
IsSupportedForDataTypeGeneric(reasonIfUnsupported,
output.GetDataType(),
&FalseOutputFuncF16<>,
&TrueFunc<>,
&FalseFuncU8<>,
- &FalseFuncI32<>));
+ &FalseFuncI32<>,
+ &FalseFuncU8<>));
}
bool RefLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
@@ -141,13 +145,15 @@ bool RefLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
&FalseInputFuncF16<>,
&TrueFunc<>,
&FalseFuncU8<>,
- &FalseFuncI32<>) &&
+ &FalseFuncI32<>,
+ &FalseFuncU8<>) &&
IsSupportedForDataTypeGeneric(reasonIfUnsupported,
output.GetDataType(),
&TrueFunc<>,
&FalseOutputFuncF32<>,
&FalseFuncU8<>,
- &FalseFuncI32<>));
+ &FalseFuncI32<>,
+ &FalseFuncU8<>));
}
bool RefLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
@@ -415,10 +421,13 @@ bool RefLayerSupport::IsMemCopySupported(const TensorInfo &input,
Optional<std::string &> reasonIfUnsupported) const
{
ignore_unused(output);
- return IsSupportedForDataTypeRef(reasonIfUnsupported,
- input.GetDataType(),
- &TrueFunc<>,
- &TrueFunc<>);
+ return IsSupportedForDataTypeGeneric(reasonIfUnsupported,
+ input.GetDataType(),
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &FalseFuncI32<>,
+ &TrueFunc<>);
}
bool RefLayerSupport::IsMinimumSupported(const TensorInfo& input0,
@@ -463,10 +472,13 @@ bool RefLayerSupport::IsNormalizationSupported(const TensorInfo& input,
bool RefLayerSupport::IsOutputSupported(const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported) const
{
- return IsSupportedForDataTypeRef(reasonIfUnsupported,
- output.GetDataType(),
- &TrueFunc<>,
- &TrueFunc<>);
+ return IsSupportedForDataTypeGeneric(reasonIfUnsupported,
+ output.GetDataType(),
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &TrueFunc<>,
+ &FalseFuncI32<>,
+ &TrueFunc<>);
}
bool RefLayerSupport::IsPadSupported(const TensorInfo& input,
diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp
index b112e9dd6a..75a9efd70f 100644
--- a/src/backends/reference/RefWorkloadFactory.cpp
+++ b/src/backends/reference/RefWorkloadFactory.cpp
@@ -24,7 +24,8 @@ template <typename F32Workload, typename U8Workload, typename QueueDescriptorTyp
std::unique_ptr<IWorkload> RefWorkloadFactory::MakeWorkload(const QueueDescriptorType& descriptor,
const WorkloadInfo& info) const
{
- return armnn::MakeWorkloadHelper<NullWorkload, F32Workload, U8Workload, NullWorkload>(descriptor, info);
+ return armnn::MakeWorkloadHelper<NullWorkload, F32Workload, U8Workload, NullWorkload, NullWorkload>(descriptor,
+ info);
}
RefWorkloadFactory::RefWorkloadFactory()
@@ -90,7 +91,8 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::CreateOutput(const OutputQueueDes
throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: data input and output differ in byte count.");
}
- return MakeWorkload<CopyMemGenericWorkload, CopyMemGenericWorkload>(descriptor, info);
+ return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload,
+ CopyMemGenericWorkload, NullWorkload, CopyMemGenericWorkload>(descriptor, info);
}
std::unique_ptr<IWorkload> RefWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
@@ -127,7 +129,7 @@ std::unique_ptr<armnn::IWorkload> RefWorkloadFactory::CreatePermute(const Permut
const WorkloadInfo& info) const
{
return MakeWorkloadHelper<RefPermuteFloat16Workload, RefPermuteFloat32Workload, RefPermuteUint8Workload,
- NullWorkload>(descriptor, info);
+ NullWorkload, NullWorkload>(descriptor, info);
}
std::unique_ptr<armnn::IWorkload> RefWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor,
@@ -206,7 +208,7 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::CreateConstant(const ConstantQueu
const WorkloadInfo& info) const
{
return MakeWorkloadHelper<NullWorkload, RefConstantFloat32Workload, RefConstantUint8Workload,
- RefConstantInt32Workload>(descriptor, info);
+ RefConstantInt32Workload, NullWorkload>(descriptor, info);
}
std::unique_ptr<IWorkload> RefWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor,
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index 763f26e18c..3ee07913dc 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -28,6 +28,7 @@ BACKEND_SOURCES := \
workloads/RefBatchNormalizationUint8Workload.cpp \
workloads/RefBatchToSpaceNdFloat32Workload.cpp \
workloads/RefBatchToSpaceNdUint8Workload.cpp \
+ workloads/RefComparisonWorkload.cpp \
workloads/RefConstantWorkload.cpp \
workloads/RefConvertFp16ToFp32Workload.cpp \
workloads/RefConvertFp32ToFp16Workload.cpp \
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index 330f406265..802167a3a0 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -315,18 +315,22 @@ BOOST_AUTO_TEST_CASE(TrivialMin)
BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndTest)
{
- const std::vector<float > expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 1 });
+ const std::vector<uint8_t> expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1 });
- ArithmeticSimpleEndToEnd<armnn::DataType::Float32>(defaultBackends, LayerType::Equal, expectedOutput);
+ ArithmeticSimpleEndToEnd<armnn::DataType::Float32, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Equal,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefGreaterSimpleEndToEndTest)
{
- const std::vector<float> expectedOutput({ 0, 0, 0, 0, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0 });
+ const std::vector<uint8_t> expectedOutput({ 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0 });
- ArithmeticSimpleEndToEnd<armnn::DataType::Float32>(defaultBackends, LayerType::Greater, expectedOutput);
+ ArithmeticSimpleEndToEnd<armnn::DataType::Float32, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Greater,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndUint8Test)
@@ -334,7 +338,9 @@ BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndUint8Test)
const std::vector<uint8_t> expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1 });
- ArithmeticSimpleEndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends, LayerType::Equal, expectedOutput);
+ ArithmeticSimpleEndToEnd<armnn::DataType::QuantisedAsymm8, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Equal,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefGreaterSimpleEndToEndUint8Test)
@@ -342,23 +348,29 @@ BOOST_AUTO_TEST_CASE(RefGreaterSimpleEndToEndUint8Test)
const std::vector<uint8_t> expectedOutput({ 0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0 });
- ArithmeticSimpleEndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends, LayerType::Greater, expectedOutput);
+ ArithmeticSimpleEndToEnd<armnn::DataType::QuantisedAsymm8, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Greater,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefEqualBroadcastEndToEndTest)
{
- const std::vector<float > expectedOutput({ 1, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0 });
+ const std::vector<uint8_t> expectedOutput({ 1, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0 });
- ArithmeticBroadcastEndToEnd<armnn::DataType::Float32>(defaultBackends, LayerType::Equal, expectedOutput);
+ ArithmeticBroadcastEndToEnd<armnn::DataType::Float32, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Equal,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefGreaterBroadcastEndToEndTest)
{
- const std::vector<float> expectedOutput({ 0, 1, 0, 0, 0, 1,
- 1, 1, 1, 1, 1, 1 });
+ const std::vector<uint8_t> expectedOutput({ 0, 1, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1 });
- ArithmeticBroadcastEndToEnd<armnn::DataType::Float32>(defaultBackends, LayerType::Greater, expectedOutput);
+ ArithmeticBroadcastEndToEnd<armnn::DataType::Float32, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Greater,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefEqualBroadcastEndToEndUint8Test)
@@ -366,7 +378,9 @@ BOOST_AUTO_TEST_CASE(RefEqualBroadcastEndToEndUint8Test)
const std::vector<uint8_t > expectedOutput({ 1, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0 });
- ArithmeticBroadcastEndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends, LayerType::Equal, expectedOutput);
+ ArithmeticBroadcastEndToEnd<armnn::DataType::QuantisedAsymm8, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Equal,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefGreaterBroadcastEndToEndUint8Test)
@@ -374,7 +388,9 @@ BOOST_AUTO_TEST_CASE(RefGreaterBroadcastEndToEndUint8Test)
const std::vector<uint8_t> expectedOutput({ 0, 1, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1 });
- ArithmeticBroadcastEndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends, LayerType::Greater, expectedOutput);
+ ArithmeticBroadcastEndToEnd<armnn::DataType::QuantisedAsymm8, armnn::DataType::Boolean>(defaultBackends,
+ LayerType::Greater,
+ expectedOutput);
}
BOOST_AUTO_TEST_CASE(RefMergerEndToEndDim0Test)
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt
index f95fda08d1..57e89fa456 100644
--- a/src/backends/reference/workloads/CMakeLists.txt
+++ b/src/backends/reference/workloads/CMakeLists.txt
@@ -40,6 +40,8 @@ list(APPEND armnnRefBackendWorkloads_sources
RefBatchToSpaceNdFloat32Workload.hpp
RefBatchToSpaceNdUint8Workload.cpp
RefBatchToSpaceNdUint8Workload.hpp
+ RefComparisonWorkload.cpp
+ RefComparisonWorkload.hpp
RefConstantWorkload.cpp
RefConstantWorkload.hpp
RefConvertFp16ToFp32Workload.cpp
diff --git a/src/backends/reference/workloads/ElementwiseFunction.cpp b/src/backends/reference/workloads/ElementwiseFunction.cpp
index cb8aa7089c..c8c25ef9e9 100644
--- a/src/backends/reference/workloads/ElementwiseFunction.cpp
+++ b/src/backends/reference/workloads/ElementwiseFunction.cpp
@@ -13,24 +13,26 @@
namespace armnn
{
-template <typename Functor>
-ElementwiseFunction<Functor>::ElementwiseFunction(const TensorShape& inShape0,
- const TensorShape& inShape1,
- const TensorShape& outShape,
- const float* inData0,
- const float* inData1,
- float* outData)
+template <typename Functor, typename dataTypeInput, typename dataTypeOutput>
+ElementwiseFunction<Functor, dataTypeInput, dataTypeOutput>::ElementwiseFunction(const TensorShape& inShape0,
+ const TensorShape& inShape1,
+ const TensorShape& outShape,
+ const dataTypeInput* inData0,
+ const dataTypeInput* inData1,
+ dataTypeOutput* outData)
{
BroadcastLoop(inShape0, inShape1, outShape).Unroll(Functor(), 0, inData0, inData1, outData);
}
} //namespace armnn
-template struct armnn::ElementwiseFunction<std::plus<float>>;
-template struct armnn::ElementwiseFunction<std::minus<float>>;
-template struct armnn::ElementwiseFunction<std::multiplies<float>>;
-template struct armnn::ElementwiseFunction<std::divides<float>>;
-template struct armnn::ElementwiseFunction<armnn::maximum<float>>;
-template struct armnn::ElementwiseFunction<armnn::minimum<float>>;
-template struct armnn::ElementwiseFunction<std::equal_to<float>>;
-template struct armnn::ElementwiseFunction<std::greater<float>>;
+template struct armnn::ElementwiseFunction<std::plus<float>, float, float>;
+template struct armnn::ElementwiseFunction<std::minus<float>, float, float>;
+template struct armnn::ElementwiseFunction<std::multiplies<float>, float, float>;
+template struct armnn::ElementwiseFunction<std::divides<float>, float, float>;
+template struct armnn::ElementwiseFunction<armnn::maximum<float>, float, float>;
+template struct armnn::ElementwiseFunction<armnn::minimum<float>, float, float>;
+template struct armnn::ElementwiseFunction<std::equal_to<float>, float ,uint8_t>;
+template struct armnn::ElementwiseFunction<std::equal_to<uint8_t>, uint8_t, uint8_t>;
+template struct armnn::ElementwiseFunction<std::greater<float>, float, uint8_t>;
+template struct armnn::ElementwiseFunction<std::greater<uint8_t>, uint8_t, uint8_t>;
diff --git a/src/backends/reference/workloads/ElementwiseFunction.hpp b/src/backends/reference/workloads/ElementwiseFunction.hpp
index 0ac136466c..8099f3279a 100644
--- a/src/backends/reference/workloads/ElementwiseFunction.hpp
+++ b/src/backends/reference/workloads/ElementwiseFunction.hpp
@@ -10,15 +10,15 @@
namespace armnn
{
-template <typename Functor>
+template <typename Functor, typename dataTypeInput, typename dataTypeOutput>
struct ElementwiseFunction
{
ElementwiseFunction(const TensorShape& inShape0,
const TensorShape& inShape1,
const TensorShape& outShape,
- const float* inData0,
- const float* inData1,
- float* outData);
+ const dataTypeInput* inData0,
+ const dataTypeInput* inData1,
+ dataTypeOutput* outData);
};
} //namespace armnn
diff --git a/src/backends/reference/workloads/RefComparisonWorkload.cpp b/src/backends/reference/workloads/RefComparisonWorkload.cpp
new file mode 100644
index 0000000000..fe517ff51a
--- /dev/null
+++ b/src/backends/reference/workloads/RefComparisonWorkload.cpp
@@ -0,0 +1,65 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefComparisonWorkload.hpp"
+#include "ElementwiseFunction.hpp"
+#include "RefWorkloadUtils.hpp"
+#include "Profiling.hpp"
+#include <vector>
+
+namespace armnn {
+
+template<typename ParentDescriptor, typename Functor>
+void RefFloat32ComparisonWorkload<ParentDescriptor, Functor>::ExecuteImpl(const char* debugString) const
+{
+ ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, debugString);
+
+ auto data = BaseFloat32ComparisonWorkload<ParentDescriptor>::GetData();
+ const TensorShape& inShape0 = GetTensorInfo(data.m_Inputs[0]).GetShape();
+ const TensorShape& inShape1 = GetTensorInfo(data.m_Inputs[1]).GetShape();
+ const TensorShape& outputShape = GetTensorInfo(data.m_Outputs[0]).GetShape();
+
+ const float* inData0 = GetInputTensorDataFloat(0, data);
+ const float* inData1 = GetInputTensorDataFloat(1, data);
+ uint8_t* outData = GetOutputTensorData<uint8_t>(0, data);
+
+ ElementwiseFunction<Functor, float, uint8_t>(inShape0,
+ inShape1,
+ outputShape,
+ inData0,
+ inData1,
+ outData);
+
+}
+
+template<typename ParentDescriptor, typename Functor>
+void RefUint8ComparisonWorkload<ParentDescriptor, Functor>::ExecuteImpl(const char* debugString) const
+{
+ ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, debugString);
+
+ auto data = BaseUint8ComparisonWorkload<ParentDescriptor>::GetData();
+ const TensorShape& inputInfo0 = GetTensorInfo(data.m_Inputs[0]).GetShape();
+ const TensorShape& inputInfo1 = GetTensorInfo(data.m_Inputs[1]).GetShape();
+ const TensorShape& outputShape = GetTensorInfo(data.m_Outputs[0]).GetShape();
+
+ const uint8_t* inData0 = GetInputTensorData<uint8_t>(0, data);
+ const uint8_t* inData1 = GetInputTensorData<uint8_t>(1, data);
+ uint8_t* outData = GetOutputTensorData<uint8_t>(0, data);
+
+ ElementwiseFunction<Functor, uint8_t, uint8_t>(inputInfo0,
+ inputInfo1,
+ outputShape,
+ inData0,
+ inData1,
+ outData);
+}
+
+}
+
+template class armnn::RefFloat32ComparisonWorkload<armnn::EqualQueueDescriptor, std::equal_to<float>>;
+template class armnn::RefUint8ComparisonWorkload<armnn::EqualQueueDescriptor, std::equal_to<uint8_t>>;
+
+template class armnn::RefFloat32ComparisonWorkload<armnn::GreaterQueueDescriptor, std::greater<float>>;
+template class armnn::RefUint8ComparisonWorkload<armnn::GreaterQueueDescriptor, std::greater<uint8_t>>;
diff --git a/src/backends/reference/workloads/RefComparisonWorkload.hpp b/src/backends/reference/workloads/RefComparisonWorkload.hpp
new file mode 100644
index 0000000000..524d20625a
--- /dev/null
+++ b/src/backends/reference/workloads/RefComparisonWorkload.hpp
@@ -0,0 +1,92 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <armnn/Types.hpp>
+#include <backendsCommon/Workload.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+#include "StringMapping.hpp"
+
+namespace armnn
+{
+
+template <typename Functor,
+ typename armnn::DataType DataType,
+ typename ParentDescriptor,
+ typename armnn::StringMapping::Id DebugString>
+class RefComparisonWorkload
+{
+ // Needs specialization. The default is empty on purpose.
+};
+
+template <typename ParentDescriptor, typename Functor>
+class RefFloat32ComparisonWorkload : public BaseFloat32ComparisonWorkload<ParentDescriptor>
+{
+public:
+ using BaseFloat32ComparisonWorkload<ParentDescriptor>::BaseFloat32ComparisonWorkload;
+ void ExecuteImpl(const char * debugString) const;
+};
+
+template <typename Functor, typename ParentDescriptor, typename armnn::StringMapping::Id DebugString>
+class RefComparisonWorkload<Functor, armnn::DataType::Float32, ParentDescriptor, DebugString>
+ : public RefFloat32ComparisonWorkload<ParentDescriptor, Functor>
+{
+public:
+ using RefFloat32ComparisonWorkload<ParentDescriptor, Functor>::RefFloat32ComparisonWorkload;
+
+ virtual void Execute() const override
+ {
+ using Parent = RefFloat32ComparisonWorkload<ParentDescriptor, Functor>;
+ Parent::ExecuteImpl(StringMapping::Instance().Get(DebugString));
+ }
+};
+
+template <typename ParentDescriptor, typename Functor>
+class RefUint8ComparisonWorkload : public BaseUint8ComparisonWorkload<ParentDescriptor>
+{
+public:
+ using BaseUint8ComparisonWorkload<ParentDescriptor>::BaseUint8ComparisonWorkload;
+ void ExecuteImpl(const char * debugString) const;
+};
+
+template <typename Functor, typename ParentDescriptor, typename armnn::StringMapping::Id DebugString>
+class RefComparisonWorkload<Functor, armnn::DataType::QuantisedAsymm8, ParentDescriptor, DebugString>
+ : public RefUint8ComparisonWorkload<ParentDescriptor, Functor>
+{
+public:
+ using RefUint8ComparisonWorkload<ParentDescriptor, Functor>::RefUint8ComparisonWorkload;
+
+ virtual void Execute() const override
+ {
+ using Parent = RefUint8ComparisonWorkload<ParentDescriptor, Functor>;
+ Parent::ExecuteImpl(StringMapping::Instance().Get(DebugString));
+ }
+};
+
+using RefEqualFloat32Workload =
+ RefComparisonWorkload<std::equal_to<float>,
+ DataType::Float32,
+ EqualQueueDescriptor,
+ StringMapping::RefEqualWorkload_Execute>;
+
+using RefEqualUint8Workload =
+ RefComparisonWorkload<std::equal_to<uint8_t>,
+ DataType::QuantisedAsymm8,
+ EqualQueueDescriptor,
+ StringMapping::RefEqualWorkload_Execute>;
+
+using RefGreaterFloat32Workload =
+ RefComparisonWorkload<std::greater<float>,
+ DataType::Float32,
+ GreaterQueueDescriptor,
+ StringMapping::RefGreaterWorkload_Execute>;
+
+using RefGreaterUint8Workload =
+ RefComparisonWorkload<std::greater<uint8_t>,
+ DataType::QuantisedAsymm8,
+ GreaterQueueDescriptor,
+ StringMapping::RefGreaterWorkload_Execute>;
+} // armnn
diff --git a/src/backends/reference/workloads/RefElementwiseWorkload.cpp b/src/backends/reference/workloads/RefElementwiseWorkload.cpp
index 13d6e70a96..c9b93c8524 100644
--- a/src/backends/reference/workloads/RefElementwiseWorkload.cpp
+++ b/src/backends/reference/workloads/RefElementwiseWorkload.cpp
@@ -26,7 +26,7 @@ void BaseFloat32ElementwiseWorkload<ParentDescriptor, Functor>::ExecuteImpl(cons
const float* inData1 = GetInputTensorDataFloat(1, data);
float* outData = GetOutputTensorDataFloat(0, data);
- ElementwiseFunction<Functor>(inShape0, inShape1, outShape, inData0, inData1, outData);
+ ElementwiseFunction<Functor, float, float>(inShape0, inShape1, outShape, inData0, inData1, outData);
}
template <typename ParentDescriptor, typename Functor>
@@ -44,12 +44,12 @@ void BaseUint8ElementwiseWorkload<ParentDescriptor, Functor>::ExecuteImpl(const
std::vector<float> results(outputInfo.GetNumElements());
- ElementwiseFunction<Functor>(inputInfo0.GetShape(),
- inputInfo1.GetShape(),
- outputInfo.GetShape(),
- dequant0.data(),
- dequant1.data(),
- results.data());
+ ElementwiseFunction<Functor, float, float>(inputInfo0.GetShape(),
+ inputInfo1.GetShape(),
+ outputInfo.GetShape(),
+ dequant0.data(),
+ dequant1.data(),
+ results.data());
Quantize(GetOutputTensorDataU8(0, data), results.data(), outputInfo);
}
@@ -73,9 +73,3 @@ template class armnn::BaseUint8ElementwiseWorkload<armnn::MaximumQueueDescriptor
template class armnn::BaseFloat32ElementwiseWorkload<armnn::MinimumQueueDescriptor, armnn::minimum<float>>;
template class armnn::BaseUint8ElementwiseWorkload<armnn::MinimumQueueDescriptor, armnn::minimum<float>>;
-
-template class armnn::BaseFloat32ElementwiseWorkload<armnn::EqualQueueDescriptor, std::equal_to<float>>;
-template class armnn::BaseUint8ElementwiseWorkload<armnn::EqualQueueDescriptor, std::equal_to<float>>;
-
-template class armnn::BaseFloat32ElementwiseWorkload<armnn::GreaterQueueDescriptor, std::greater<float>>;
-template class armnn::BaseUint8ElementwiseWorkload<armnn::GreaterQueueDescriptor, std::greater<float>>;
diff --git a/src/backends/reference/workloads/RefElementwiseWorkload.hpp b/src/backends/reference/workloads/RefElementwiseWorkload.hpp
index 6dd6865f53..a5ff376673 100644
--- a/src/backends/reference/workloads/RefElementwiseWorkload.hpp
+++ b/src/backends/reference/workloads/RefElementwiseWorkload.hpp
@@ -144,28 +144,4 @@ using RefMinimumUint8Workload =
DataType::QuantisedAsymm8,
MinimumQueueDescriptor,
StringMapping::RefMinimumWorkload_Execute>;
-
-using RefEqualFloat32Workload =
- RefElementwiseWorkload<std::equal_to<float>,
- DataType::Float32,
- EqualQueueDescriptor,
- StringMapping::RefEqualWorkload_Execute>;
-
-using RefEqualUint8Workload =
- RefElementwiseWorkload<std::equal_to<float>,
- DataType::QuantisedAsymm8,
- EqualQueueDescriptor,
- StringMapping::RefEqualWorkload_Execute>;
-
-using RefGreaterFloat32Workload =
- RefElementwiseWorkload<std::greater<float>,
- DataType::Float32,
- GreaterQueueDescriptor,
- StringMapping::RefGreaterWorkload_Execute>;
-
-using RefGreaterUint8Workload =
- RefElementwiseWorkload<std::greater<float>,
- DataType::QuantisedAsymm8,
- GreaterQueueDescriptor,
- StringMapping::RefGreaterWorkload_Execute>;
} // armnn
diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp
index 1cbceb366b..d9f4dbb342 100644
--- a/src/backends/reference/workloads/RefWorkloads.hpp
+++ b/src/backends/reference/workloads/RefWorkloads.hpp
@@ -60,3 +60,4 @@
#include "RefBatchToSpaceNdFloat32Workload.hpp"
#include "RefDebugWorkload.hpp"
#include "RefRsqrtFloat32Workload.hpp"
+#include "RefComparisonWorkload.hpp"