aboutsummaryrefslogtreecommitdiff
path: root/src/backends/tosaCommon/test
diff options
context:
space:
mode:
authorMatthew Sloyan <matthew.sloyan@arm.com>2022-11-25 16:10:00 +0000
committerMatthew Sloyan <matthew.sloyan@arm.com>2022-12-08 12:57:47 +0000
commitc5fe6e71cd39096af7c2523ec2afe96008c51b0c (patch)
tree1486349bc36e17c1577465aab81d9eb3ca64e861 /src/backends/tosaCommon/test
parent3106c7f1714aea556d06d9f1e8c7faaeaeca996d (diff)
downloadarmnn-c5fe6e71cd39096af7c2523ec2afe96008c51b0c.tar.gz
IVGCVSW-7168 Add Conv2d and Constant support to TOSA Reference Backend
* Added TOSA Conv2d and Constant mappings. * Added unique naming to mappings based on previous and following layers, so they are connected correctly. * Updated existing mappings with new naming convention. * Added all mappings to one main block in OptimizeSubgraphView. * Removed isMain from mapping functions. * Added Conv2d EndToEnd test. Signed-off-by: Matthew Sloyan <matthew.sloyan@arm.com> Change-Id: I27c3e238407c32379ce25a1f01dad11523ef5d2b
Diffstat (limited to 'src/backends/tosaCommon/test')
-rw-r--r--src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp12
-rw-r--r--src/backends/tosaCommon/test/OneToManyMappingTests.cpp4
-rw-r--r--src/backends/tosaCommon/test/OneToOneMappingTests.cpp136
-rw-r--r--src/backends/tosaCommon/test/TosaTestUtils.hpp51
4 files changed, 181 insertions, 22 deletions
diff --git a/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp b/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp
index 8869b3a8ff..a38f66b466 100644
--- a/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp
+++ b/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp
@@ -17,10 +17,8 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
{
uint32_t numInputs = static_cast<uint32_t>(inputShape.size());
uint32_t numOutputs = static_cast<uint32_t>(outputShape.size());
- std::string operatorString0 = TosaOpToString(Op_PAD);
- std::string operatorString1 = TosaOpToString(Op_AVG_POOL2D);
- std::string blockStr = operatorString1 + "_block_";
+ std::string blockStr = TosaOpToString(Op_AVG_POOL2D) + "_block_";
CHECK(basicBlock->GetName().find(blockStr) != std::string::npos);
CHECK(basicBlock->GetInputs().size() == numInputs);
CHECK(basicBlock->GetOutputs().size() == numOutputs);
@@ -41,7 +39,7 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
std::basic_string<char> blockInputName = basicBlock->GetInputs()[i];
std::basic_string<char> operatorInputName = padOp->GetInputTensorNames()[i];
- std::string opStr = operatorString0 + "_input" + std::to_string(i) + "_";
+ std::string opStr = "input" + std::to_string(i) + "_";
CHECK(blockInputName == operatorInputName);
CHECK(basicBlock->GetTensorByName(blockInputName));
@@ -56,7 +54,7 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
for (uint32_t i = 0; i < padOpOutputs; i++)
{
std::basic_string<char> operatorOutputName = padOp->GetOutputTensorNames()[i];
- std::string opStr = operatorString0 + "_intermediate" + std::to_string(i) + "_";
+ std::string opStr = "intermediate" + std::to_string(i) + "_";
CHECK(basicBlock->GetTensorByName(operatorOutputName));
CHECK(operatorOutputName.find(opStr) != std::string::npos);
@@ -86,7 +84,7 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
for (uint32_t i = 0; i < poolOpInputs; i++)
{
std::basic_string<char> operatorInputName = poolOp->GetInputTensorNames()[i];
- std::string opStr = operatorString0 + "_intermediate" + std::to_string(i) + "_";
+ std::string opStr = "intermediate" + std::to_string(i) + "_";
CHECK(basicBlock->GetTensorByName(operatorInputName));
CHECK(operatorInputName.find(opStr) != std::string::npos);
@@ -102,7 +100,7 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
std::basic_string<char> blockOutputName = basicBlock->GetOutputs()[i];
std::basic_string<char> operatorOutputName = poolOp->GetOutputTensorNames()[i];
- std::string opStr = operatorString1 + "_output" + std::to_string(i) + "_";
+ std::string opStr = "output" + std::to_string(i) + "_";
CHECK(blockOutputName == operatorOutputName);
CHECK(basicBlock->GetTensorByName(blockOutputName));
diff --git a/src/backends/tosaCommon/test/OneToManyMappingTests.cpp b/src/backends/tosaCommon/test/OneToManyMappingTests.cpp
index 98fd563da1..dd61ba8191 100644
--- a/src/backends/tosaCommon/test/OneToManyMappingTests.cpp
+++ b/src/backends/tosaCommon/test/OneToManyMappingTests.cpp
@@ -30,7 +30,7 @@ TEST_CASE("GetTosaMapping_AvgPool2DIgnoreValueLayer")
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
TosaSerializationBasicBlock* basicBlock =
- GetTosaMapping(LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor, false);
+ GetTosaMapping(nullptr, LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor);
VerifyAvgPool2DIgnoreValue(basicBlock,
inputShape,
outputShape,
@@ -74,7 +74,7 @@ TEST_CASE("GetTosaMappingFromLayer_AvgPool2DIgnoreValueLayer")
pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
TosaSerializationBasicBlock* basicBlock =
- GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool), false);
+ GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool));
VerifyAvgPool2DIgnoreValue(basicBlock,
inputShape,
outputShape,
diff --git a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
index 04d1eb46aa..af9f9e26df 100644
--- a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
+++ b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
@@ -4,6 +4,7 @@
//
#include "TosaTestUtils.hpp"
+#include "CommonTestUtils.hpp"
using namespace armnn;
using namespace tosa;
@@ -18,7 +19,7 @@ TEST_CASE("GetTosaMapping_AdditionLayer")
std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }};
TosaSerializationBasicBlock* basicBlock =
- GetTosaMapping(LayerType::Addition, {&info, &info}, {&info}, BaseDescriptor(), false);
+ GetTosaMapping(nullptr, LayerType::Addition, {&info, &info}, {&info}, BaseDescriptor());
AssertTosaOneToOneMappingBasicBlock(
basicBlock, inputShape, outputShape, Op_ADD, Attribute_NONE, BaseDescriptor(), LayerType::Addition);
}
@@ -50,11 +51,132 @@ TEST_CASE("GetTosaMappingFromLayer_AdditionLayer")
std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }};
TosaSerializationBasicBlock* basicBlock =
- GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(add), false);
+ GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(add));
AssertTosaOneToOneMappingBasicBlock(
basicBlock, inputShape, outputShape, Op_ADD, Attribute_NONE, BaseDescriptor(), LayerType::Addition);
}
+TEST_CASE("GetTosaMapping_ConstantLayer")
+{
+ TensorInfo outputInfo = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true);
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }};
+
+ TosaSerializationBasicBlock* basicBlock =
+ GetTosaMapping(nullptr, LayerType::Constant, {}, {&outputInfo}, BaseDescriptor());
+ AssertTosaOneToOneMappingBasicBlock(
+ basicBlock, {}, outputShape, Op_CONST, Attribute_NONE, BaseDescriptor(), LayerType::Constant);
+}
+
+TEST_CASE("GetTosaMappingFromLayer_ConstantLayer")
+{
+ IRuntime::CreationOptions options;
+ IRuntimePtr runtime(IRuntime::Create(options));
+
+ // Builds up the structure of the network.
+ INetworkPtr net(INetwork::Create());
+
+ TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true);
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }};
+
+ std::vector<float> data = GenerateRandomData<float>(info.GetNumElements());
+ armnn::ConstTensor constTensor(info, data);
+
+ IConnectableLayer* constant = net->AddConstantLayer(constTensor, "constant");
+ IConnectableLayer* output = net->AddOutputLayer(0, "output");
+
+ constant->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+ constant->GetOutputSlot(0).SetTensorInfo(info);
+
+ TosaSerializationBasicBlock* basicBlock =
+ GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(constant));
+ AssertTosaOneToOneMappingBasicBlock(
+ basicBlock, {}, outputShape, Op_CONST, Attribute_NONE, BaseDescriptor(), LayerType::Constant);
+}
+
+TEST_CASE("GetTosaMapping_Conv2dLayer")
+{
+ armnn::Convolution2dDescriptor descriptor;
+ descriptor.m_PadLeft = 1;
+ descriptor.m_PadRight = 1;
+ descriptor.m_PadTop = 1;
+ descriptor.m_PadBottom = 1;
+ descriptor.m_StrideX = 2;
+ descriptor.m_StrideY = 2;
+ descriptor.m_DilationX = 2;
+ descriptor.m_DilationY = 2;
+ descriptor.m_BiasEnabled = true;
+
+ const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
+ const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
+ const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+ const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 1, 5, 5, 1 }, { 1, 3, 3, 1 }, { 1 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 3, 3, 1 }};
+
+ TosaSerializationBasicBlock* basicBlock = GetTosaMapping(nullptr,
+ LayerType::Convolution2d,
+ {&inputInfo, &weightsInfo, &biasesInfo},
+ {&outputInfo},
+ descriptor);
+ AssertTosaOneToOneMappingBasicBlock(
+ basicBlock, inputShape, outputShape, Op_CONV2D, Attribute_ConvAttribute, descriptor, LayerType::Convolution2d);
+}
+
+TEST_CASE("GetTosaMappingFromLayer_Conv2dLayer")
+{
+ IRuntime::CreationOptions options;
+ IRuntimePtr runtime(IRuntime::Create(options));
+
+ // Builds up the structure of the network.
+ INetworkPtr net(INetwork::Create());
+
+ armnn::Convolution2dDescriptor descriptor;
+ descriptor.m_PadLeft = 1;
+ descriptor.m_PadRight = 1;
+ descriptor.m_PadTop = 1;
+ descriptor.m_PadBottom = 1;
+ descriptor.m_StrideX = 2;
+ descriptor.m_StrideY = 2;
+ descriptor.m_DilationX = 2;
+ descriptor.m_DilationY = 2;
+ descriptor.m_BiasEnabled = true;
+
+ const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
+ const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
+ const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+ const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 1, 5, 5, 1 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 3, 3, 1 }};
+
+ std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
+ armnn::ConstTensor weights(weightsInfo, weightsData);
+
+ std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
+ armnn::ConstTensor biases(biasesInfo, biasesData);
+
+ armnn::IConnectableLayer* const inputLayer = net->AddInputLayer(0, "input0");
+ armnn::IConnectableLayer* const weightsLayer = net->AddConstantLayer(weights, "weights");
+ armnn::IConnectableLayer* const biasesLayer = net->AddConstantLayer(biases, "biases");
+ armnn::IConnectableLayer* const convLayer = net->AddConvolution2dLayer(descriptor, "conv2d");
+ armnn::IConnectableLayer* const outputLayer = net->AddOutputLayer(0);
+
+ inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
+ weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
+ biasesLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
+ convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+ inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
+ weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
+ biasesLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
+ convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+ TosaSerializationBasicBlock* basicBlock = GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(convLayer));
+ AssertTosaOneToOneMappingBasicBlock(
+ basicBlock, inputShape, outputShape, Op_CONV2D, Attribute_ConvAttribute, descriptor, LayerType::Convolution2d);
+}
+
TEST_CASE("GetTosaMapping_MaxPool2DLayer")
{
armnn::Pooling2dDescriptor descriptor;
@@ -74,7 +196,7 @@ TEST_CASE("GetTosaMapping_MaxPool2DLayer")
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
TosaSerializationBasicBlock* basicBlock =
- GetTosaMapping(LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor, false);
+ GetTosaMapping(nullptr, LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor);
AssertTosaOneToOneMappingBasicBlock(
basicBlock, inputShape, outputShape, Op_MAX_POOL2D, Attribute_PoolAttribute, descriptor, LayerType::Pooling2d);
}
@@ -114,7 +236,7 @@ TEST_CASE("GetTosaMappingFromLayer_MaxPool2DLayer")
pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
TosaSerializationBasicBlock* basicBlock =
- GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool), false);
+ GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool));
AssertTosaOneToOneMappingBasicBlock(
basicBlock, inputShape, outputShape, Op_MAX_POOL2D, Attribute_PoolAttribute, descriptor, LayerType::Pooling2d);
}
@@ -138,7 +260,7 @@ TEST_CASE("GetTosaMapping_AvgPool2DLayer")
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
TosaSerializationBasicBlock* basicBlock =
- GetTosaMapping(LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor, false);
+ GetTosaMapping(nullptr, LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor);
AssertTosaOneToOneMappingBasicBlock(basicBlock,
inputShape,
outputShape,
@@ -183,7 +305,7 @@ TEST_CASE("GetTosaMappingFromLayer_AvgPool2DLayer")
pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
TosaSerializationBasicBlock* basicBlock =
- GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool), false);
+ GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool));
AssertTosaOneToOneMappingBasicBlock(basicBlock,
inputShape,
outputShape,
@@ -196,7 +318,7 @@ TEST_CASE("GetTosaMappingFromLayer_AvgPool2DLayer")
TEST_CASE("GetTosaMapping_Unimplemented")
{
TosaSerializationBasicBlock* basicBlock =
- GetTosaMapping(LayerType::UnidirectionalSequenceLstm, {}, {}, BaseDescriptor(), false);
+ GetTosaMapping(nullptr, LayerType::UnidirectionalSequenceLstm, {}, {}, BaseDescriptor());
CHECK(basicBlock->GetName() == "");
CHECK(basicBlock->GetTensors().size() == 0);
diff --git a/src/backends/tosaCommon/test/TosaTestUtils.hpp b/src/backends/tosaCommon/test/TosaTestUtils.hpp
index a362bde10d..dd63c0efdf 100644
--- a/src/backends/tosaCommon/test/TosaTestUtils.hpp
+++ b/src/backends/tosaCommon/test/TosaTestUtils.hpp
@@ -21,6 +21,24 @@ inline void VerifyTosaAttributeFromDescriptor(const BaseDescriptor& descriptor,
{
switch (type)
{
+ case LayerType::Convolution2d:
+ {
+ auto conv2dDesc = PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor);
+ std::vector<int> pad = {static_cast<int>(conv2dDesc->m_PadTop),
+ static_cast<int>(conv2dDesc->m_PadBottom),
+ static_cast<int>(conv2dDesc->m_PadLeft),
+ static_cast<int>(conv2dDesc->m_PadRight)};
+
+ std::vector<int> dilation = {static_cast<int>(conv2dDesc->m_DilationY),
+ static_cast<int>(conv2dDesc->m_DilationX)};
+ std::vector<int> stride = {static_cast<int>(conv2dDesc->m_StrideY),
+ static_cast<int>(conv2dDesc->m_StrideX)};
+ TosaConvAttribute convAttribute(attribute);
+ CHECK(pad == convAttribute.pad());
+ CHECK(dilation == convAttribute.dilation());
+ CHECK(stride == convAttribute.stride());
+ break;
+ }
case LayerType::Pooling2d:
{
auto poolDesc = PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor);
@@ -80,6 +98,7 @@ inline void VerifyTosaAttributeFromDescriptor(const BaseDescriptor& descriptor,
CHECK(pad == poolAttribute.pad());
CHECK(kernel == poolAttribute.kernel());
CHECK(stride == poolAttribute.stride());
+ break;
}
default:
break;
@@ -97,18 +116,30 @@ inline void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* bas
DType dataType = DType_FP32)
{
uint32_t numInputs = static_cast<uint32_t>(inputShape.size());
+ uint32_t numInputTensors = static_cast<uint32_t>(inputShape.size());
uint32_t numOutputs = static_cast<uint32_t>(outputShape.size());
std::string operatorString = TosaOpToString(tosaOp);
+ // The number of tensors in the block can be different if there are constant layers, as they are created separately.
+ if(type == LayerType::Convolution2d)
+ {
+ numInputTensors = 2;
+ auto conv2dDesc = PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor);
+ if(conv2dDesc->m_BiasEnabled)
+ {
+ numInputTensors = 3;
+ }
+ }
+
std::string blockStr = operatorString + "_block_";
CHECK(basicBlock->GetName().find(blockStr) != std::string::npos);
- CHECK(basicBlock->GetInputs().size() == numInputs);
+ CHECK(basicBlock->GetInputs().size() == numInputTensors);
CHECK(basicBlock->GetOutputs().size() == numOutputs);
CHECK(basicBlock->GetOperators().size() == 1);
CHECK(basicBlock->GetTensors().size() == (numInputs + numOutputs));
TosaSerializationOperator* op = basicBlock->GetOperators().at(0);
- CHECK(op->GetInputTensorNames().size() == numInputs);
+ CHECK(op->GetInputTensorNames().size() == numInputTensors);
CHECK(op->GetOutputTensorNames().size() == numOutputs);
for (uint32_t i = 0; i < numInputs; i++)
@@ -117,11 +148,11 @@ inline void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* bas
std::basic_string<char> operatorInputName = op->GetInputTensorNames()[i];
std::basic_string<char> tensorName = basicBlock->GetTensors()[i]->GetName();
- std::string opStr = operatorString + "_input" + std::to_string(i) + "_";
+ std::string opStr = "input" + std::to_string(i) + "_";
CHECK(blockInputName == operatorInputName);
CHECK(tensorName == operatorInputName);
- CHECK(blockInputName.find(opStr) != std::string::npos);
+ CHECK(blockInputName.find(opStr) != std::string::npos);
}
for (uint32_t i = 0; i < numOutputs; i++)
@@ -130,7 +161,11 @@ inline void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* bas
std::basic_string<char> operatorOutputName = op->GetOutputTensorNames()[i];
std::basic_string<char> tensorName = basicBlock->GetTensors()[numInputs + i]->GetName();
- std::string opStr = operatorString + "_output" + std::to_string(i) + "_";
+ std::string opStr = "output" + std::to_string(i) + "_";
+ if (tosaOp == Op_CONST)
+ {
+ opStr = "constant_";
+ }
CHECK(blockOutputName == operatorOutputName);
CHECK(tensorName == operatorOutputName);
@@ -152,8 +187,12 @@ inline void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* bas
{
TosaSerializationTensor* tensor = basicBlock->GetTensors()[i + inputShape.size()];
CHECK(tensor->GetDtype() == dataType);
- CHECK(tensor->GetData().size() == 0);
CHECK(tensor->GetShape() == outputShape[static_cast<unsigned long int>(i)]);
+ if (tosaOp != Op_CONST)
+ {
+ // Const tensors contain data.
+ CHECK(tensor->GetData().size() == 0);
+ }
}
VerifyTosaAttributeFromDescriptor(descriptor,