blob: 8b3e3fdc99be7b128d3cc0ef066f09e05fc6d8e9 [file] [log] [blame]
Narumol Prangnawarat1a268962020-07-27 15:52:13 +01001//
2// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
Sadik Armagan76615a52020-08-04 14:01:05 +01005
6#include <Graph.hpp>
7#include <Network.hpp>
8
Narumol Prangnawarat1a268962020-07-27 15:52:13 +01009#include <neon/NeonTensorHandle.hpp>
10#include <neon/NeonTensorHandleFactory.hpp>
11
Sadik Armagan76615a52020-08-04 14:01:05 +010012#include <armnn/utility/PolymorphicDowncast.hpp>
13
14#include <test/GraphUtils.hpp>
15
Narumol Prangnawarat1a268962020-07-27 15:52:13 +010016#include <boost/test/unit_test.hpp>
17
18BOOST_AUTO_TEST_SUITE(NeonTensorHandleTests)
19using namespace armnn;
20
21BOOST_AUTO_TEST_CASE(NeonTensorHandleGetCapabilitiesNoPadding)
22{
23 std::shared_ptr<NeonMemoryManager> memoryManager = std::make_shared<NeonMemoryManager>();
24 NeonTensorHandleFactory handleFactory(memoryManager);
25
26 INetworkPtr network(INetwork::Create());
27
28 // Add the layers
29 IConnectableLayer* input = network->AddInputLayer(0);
30 SoftmaxDescriptor descriptor;
31 descriptor.m_Beta = 1.0f;
32 IConnectableLayer* softmax = network->AddSoftmaxLayer(descriptor);
33 IConnectableLayer* output = network->AddOutputLayer(2);
34
35 // Establish connections
36 input->GetOutputSlot(0).Connect(softmax->GetInputSlot(0));
37 softmax->GetOutputSlot(0).Connect(output->GetInputSlot(0));
38
39 // No padding required for input
40 std::vector<Capability> capabilities = handleFactory.GetCapabilities(input,
41 softmax,
42 CapabilityClass::PaddingRequired);
43 BOOST_TEST(capabilities.empty());
44
45 // No padding required for Softmax
46 capabilities = handleFactory.GetCapabilities(softmax, output, CapabilityClass::PaddingRequired);
47 BOOST_TEST(capabilities.empty());
48
49 // No padding required for output
50 capabilities = handleFactory.GetCapabilities(output, nullptr, CapabilityClass::PaddingRequired);
51 BOOST_TEST(capabilities.empty());
52}
53
54BOOST_AUTO_TEST_CASE(NeonTensorHandleGetCapabilitiesPadding)
55{
56 std::shared_ptr<NeonMemoryManager> memoryManager = std::make_shared<NeonMemoryManager>();
57 NeonTensorHandleFactory handleFactory(memoryManager);
58
59 INetworkPtr network(INetwork::Create());
60
61 // Add the layers
62 IConnectableLayer* input = network->AddInputLayer(0);
63 Pooling2dDescriptor descriptor;
64 IConnectableLayer* pooling = network->AddPooling2dLayer(descriptor);
65 IConnectableLayer* output = network->AddOutputLayer(2);
66
67 // Establish connections
68 input->GetOutputSlot(0).Connect(pooling->GetInputSlot(0));
69 pooling->GetOutputSlot(0).Connect(output->GetInputSlot(0));
70
71 // No padding required for input
72 std::vector<Capability> capabilities = handleFactory.GetCapabilities(input,
73 pooling,
74 CapabilityClass::PaddingRequired);
75 BOOST_TEST(capabilities.empty());
76
77 // No padding required for output
78 capabilities = handleFactory.GetCapabilities(output, nullptr, CapabilityClass::PaddingRequired);
79 BOOST_TEST(capabilities.empty());
80
81 // Padding required for Pooling2d
82 capabilities = handleFactory.GetCapabilities(pooling, output, CapabilityClass::PaddingRequired);
83 BOOST_TEST(capabilities.size() == 1);
84 BOOST_TEST((capabilities[0].m_CapabilityClass == CapabilityClass::PaddingRequired));
85 BOOST_TEST(capabilities[0].m_Value);
86}
87
Sadik Armagan76615a52020-08-04 14:01:05 +010088BOOST_AUTO_TEST_CASE(ConcatOnXorYSubTensorsNoPaddinRequiredTest)
89{
90 armnn::INetworkPtr net(armnn::INetwork::Create());
91
92 // Set up tensor infos
93 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
94 const armnn::TensorInfo intermediateInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
95 const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 3, 4, 2}, armnn::DataType::Float32);
96
97 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs);
98
99 // Create the network
100 armnn::IConnectableLayer* const input0Layer = net->AddInputLayer(0, "input_0");
101 input0Layer->GetOutputSlot(0).SetTensorInfo(inputInfo);
102 armnn::IConnectableLayer* elementwiseUnaryLayer0 = net->AddElementwiseUnaryLayer(descriptor, "elementwiseUnary_0");
103 elementwiseUnaryLayer0->GetOutputSlot(0).SetTensorInfo(intermediateInfo);
104 input0Layer->GetOutputSlot(0).Connect(elementwiseUnaryLayer0->GetInputSlot(0));
105
106 armnn::IConnectableLayer* const input1Layer = net->AddInputLayer(1, "input_1");
107 input1Layer->GetOutputSlot(0).SetTensorInfo(inputInfo);
108 armnn::IConnectableLayer* elementwiseUnaryLayer1 = net->AddElementwiseUnaryLayer(descriptor, "elementwiseUnary_1");
109 elementwiseUnaryLayer1->GetOutputSlot(0).SetTensorInfo(intermediateInfo);
110 input1Layer->GetOutputSlot(0).Connect(elementwiseUnaryLayer1->GetInputSlot(0));
111
112 std::array<armnn::TensorShape, 2> concatInputShapes = { intermediateInfo.GetShape(), intermediateInfo.GetShape() };
113 armnn::IConnectableLayer* const concatLayer = net->AddConcatLayer(armnn::CreateDescriptorForConcatenation(
114 concatInputShapes.begin(), concatInputShapes.end(), 2), "concatenation");
115 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
116 elementwiseUnaryLayer0->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
117 elementwiseUnaryLayer1->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
118
119 armnn::IConnectableLayer* const outputLayer = net->AddOutputLayer(0, "output");
120 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
121
122 armnn::IRuntime::CreationOptions options;
123 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
124
125 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc };
126 armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
127
128 const armnn::Graph& theGraph = static_cast<armnn::OptimizedNetwork*>(optimizedNet.get())->GetGraph();
129
130 // Load graph into runtime
131 armnn::NetworkId networkIdentifier;
132 runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet));
133
134 // now check the concat how many sub-tensors it is using..
135 auto TraceSubTensorHandleAncestry = [](armnn::ITensorHandle* const subTensorHandle)
136 {
137 if (subTensorHandle && subTensorHandle->GetParent())
138 {
139 return true;
140 }
141 return false;
142 };
143
144 for (auto&& layer : theGraph)
145 {
146 if(layer->GetType() == armnn::LayerType::Concat)
147 {
148 unsigned int numberOfSubTensors = 0;
149 for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
150 {
151 const armnn::OutputSlot* slot = layer->GetInputSlot(i).GetConnectedOutputSlot();
152 if (TraceSubTensorHandleAncestry(slot->GetOutputHandler().GetData()))
153 {
154 ++numberOfSubTensors;
155 }
156 }
157 // sub-tensors should be supported in this configuration
158 BOOST_CHECK(numberOfSubTensors > 0);
159 }
160 }
161}
162
Narumol Prangnawarat1a268962020-07-27 15:52:13 +0100163BOOST_AUTO_TEST_SUITE_END()