ArmNN
 21.02
AddBroadcastReshapeLayerTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "../GraphUtils.hpp"
7 #include "../TestUtils.hpp"
8 
9 #include <Optimizer.hpp>
10 
11 #include <boost/test/unit_test.hpp>
12 
13 using namespace armnn;
14 
16 using namespace optimizations;
17 
19  const TensorInfo& info1,
20  const TensorInfo& outputInfo,
21  const std::string& reshapeLayerName,
22  const TensorShape& expectedReshapeShape,
23  const DataType expectedDataType)
24 {
25  Graph graph;
26 
27  auto input0 = graph.AddLayer<InputLayer>(0, "input0");
28  auto input1 = graph.AddLayer<InputLayer>(1, "input1");
29  auto add = graph.AddLayer<AdditionLayer>("add");
30  auto output = graph.AddLayer<OutputLayer>(0, "output");
31  input0->GetOutputSlot().SetTensorInfo(info0);
32  input1->GetOutputSlot().SetTensorInfo(info1);
33  add->GetOutputSlot().SetTensorInfo(outputInfo);
34 
35  input0->GetOutputSlot().Connect(add->GetInputSlot(0));
36  input1->GetOutputSlot().Connect(add->GetInputSlot(1));
37  add->GetOutputSlot().Connect(output->GetInputSlot(0));
38 
39  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
40  &IsLayerOfType<InputLayer>,
41  &IsLayerOfType<InputLayer>,
42  &IsLayerOfType<AdditionLayer>,
43  &IsLayerOfType<OutputLayer>));
44 
45  // Run optimizer
47 
48  // Broadcast reshape layer has been added to the graph correctly
49  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
50  &IsLayerOfType<InputLayer>,
51  &IsLayerOfType<InputLayer>,
52  &IsLayerOfType<ReshapeLayer>,
53  &IsLayerOfType<AdditionLayer>,
54  &IsLayerOfType<OutputLayer>));
55 
56  Layer* const reshapeLayer = GetFirstLayerWithName(graph, reshapeLayerName);
57  BOOST_TEST(reshapeLayer);
58  auto addedReshapeTensorInfo = reshapeLayer->GetOutputSlot().GetTensorInfo();
59 
60  // Tensorshape and the data type are correct
61  BOOST_TEST((addedReshapeTensorInfo.GetShape() == expectedReshapeShape));
62  BOOST_TEST((addedReshapeTensorInfo.GetDataType() == expectedDataType));
63 }
64 
65 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayerSimpleTest)
66 {
67  const TensorInfo info0({ 1, 2, 3, 5 }, DataType::Float32);
68  const TensorInfo info1({ 1 }, DataType::Float32);
69  AddBroadcastReshapeLayerOptimizerTest(info0, info1, info0, "Reshape_for:add-1",
70  TensorShape({ 1, 1, 1, 1 }),
72 }
73 
74 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayer1DTest)
75 {
76  const TensorInfo info0({ 1, 2, 3, 5 }, DataType::Float32);
77  const TensorInfo info1({ 5 }, DataType::Float32);
78  const TensorInfo outputInfo({ 1, 1, 1, 5 }, DataType::Float32);
79  AddBroadcastReshapeLayerOptimizerTest(info0, info1, outputInfo, "Reshape_for:add-1",
80  TensorShape({ 1, 1, 1, 5 }),
82 }
83 
84 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayer2DTest)
85 {
86  const TensorInfo info0({ 1, 2, 3, 5 }, DataType::Float32);
87  const TensorInfo info1({ 3, 5 }, DataType::Float32);
88  const TensorInfo outputInfo({ 1, 2, 3, 5 }, DataType::Float32);
89  AddBroadcastReshapeLayerOptimizerTest(info0, info1, outputInfo, "Reshape_for:add-1",
90  TensorShape({ 1, 1, 3, 5 }),
92 }
93 
94 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayer3DTest)
95 {
96  const TensorInfo info0({ 2, 1, 1, 1 }, DataType::Float32);
97  const TensorInfo info1({ 3, 4, 5 }, DataType::Float32);
98  const TensorInfo outputInfo({ 2, 3, 4, 5 }, DataType::Float32);
99  AddBroadcastReshapeLayerOptimizerTest(info0, info1, outputInfo, "Reshape_for:add-1",
100  TensorShape({ 1, 3, 4, 5 }),
102 }
103 
104 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayer3DMergedTest)
105 {
106  const TensorInfo info0({ 2, 3, 1, 1 }, DataType::Float32);
107  const TensorInfo info1({ 3, 4, 5 }, DataType::Float32);
108  const TensorInfo outputInfo({ 2, 3, 4, 5 }, DataType::Float32);
109  AddBroadcastReshapeLayerOptimizerTest(info0, info1, outputInfo, "Reshape_for:add-1",
110  TensorShape({ 1, 3, 4, 5 }),
112 }
113 
114 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayerSubtractionTest)
115 {
116  Graph graph;
117  const TensorInfo info0({ 5 }, DataType::Float32);
118  const TensorInfo info1({ 1, 2, 3, 5 }, DataType::Float32);
119  const TensorInfo outputInfo({ 1, 2, 3, 5 }, DataType::Float32);
120 
121  auto input0 = graph.AddLayer<InputLayer>(0, "input0");
122  auto input1 = graph.AddLayer<InputLayer>(1, "input1");
123  auto sub = graph.AddLayer<SubtractionLayer>("sub");
124  auto output = graph.AddLayer<OutputLayer>(0, "output");
125  input0->GetOutputSlot().SetTensorInfo(info0);
126  input1->GetOutputSlot().SetTensorInfo(info1);
127  sub->GetOutputSlot().SetTensorInfo(outputInfo);
128 
129  input0->GetOutputSlot().Connect(sub->GetInputSlot(0));
130  input1->GetOutputSlot().Connect(sub->GetInputSlot(1));
131  sub->GetOutputSlot().Connect(output->GetInputSlot(0));
132 
133  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
134  &IsLayerOfType<InputLayer>,
135  &IsLayerOfType<InputLayer>,
136  &IsLayerOfType<SubtractionLayer>,
137  &IsLayerOfType<OutputLayer>));
138 
139  // Run optimizer
141 
142  // Broadcast reshape layer has been added to the graph correctly
143  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
144  &IsLayerOfType<InputLayer>,
145  &IsLayerOfType<InputLayer>,
146  &IsLayerOfType<ReshapeLayer>,
147  &IsLayerOfType<SubtractionLayer>,
148  &IsLayerOfType<OutputLayer>));
149 
150  Layer* const reshapeLayer = GetFirstLayerWithName(graph, "Reshape_for:sub-0");
151  BOOST_TEST(reshapeLayer);
152  auto addedReshapeTensorInfo = reshapeLayer->GetOutputSlot().GetTensorInfo();
153 
154  // Tensorshape and the data type are correct
155  BOOST_TEST((addedReshapeTensorInfo.GetShape() == TensorShape({ 1, 1, 1, 5 })));
156  BOOST_TEST((addedReshapeTensorInfo.GetDataType() == DataType::Float32));
157 }
158 
159 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayerDivisionTest)
160 {
161  Graph graph;
162  const TensorInfo info0({ 1, 4, 5 }, DataType::QAsymmS8);
163  const TensorInfo info1({ 1, 2, 4, 5 }, DataType::QAsymmS8);
164  const TensorInfo outputInfo({ 1, 2, 4, 5 }, DataType::QAsymmS8);
165 
166  auto input0 = graph.AddLayer<InputLayer>(0, "input0");
167  auto input1 = graph.AddLayer<InputLayer>(1, "input1");
168  auto div = graph.AddLayer<DivisionLayer>("div");
169  auto output = graph.AddLayer<OutputLayer>(0, "output");
170  input0->GetOutputSlot().SetTensorInfo(info0);
171  input1->GetOutputSlot().SetTensorInfo(info1);
172  div->GetOutputSlot().SetTensorInfo(outputInfo);
173 
174  input0->GetOutputSlot().Connect(div->GetInputSlot(0));
175  input1->GetOutputSlot().Connect(div->GetInputSlot(1));
176  div->GetOutputSlot().Connect(output->GetInputSlot(0));
177 
178  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
179  &IsLayerOfType<InputLayer>,
180  &IsLayerOfType<InputLayer>,
181  &IsLayerOfType<DivisionLayer>,
182  &IsLayerOfType<OutputLayer>));
183 
184  // Run optimizer
186 
187  // Broadcast reshape layer has been added to the graph correctly
188  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
189  &IsLayerOfType<InputLayer>,
190  &IsLayerOfType<InputLayer>,
191  &IsLayerOfType<ReshapeLayer>,
192  &IsLayerOfType<DivisionLayer>,
193  &IsLayerOfType<OutputLayer>));
194 
195  Layer* const reshapeLayer = GetFirstLayerWithName(graph, "Reshape_for:div-0");
196  BOOST_TEST(reshapeLayer);
197  auto addedReshapeTensorInfo = reshapeLayer->GetOutputSlot().GetTensorInfo();
198 
199  // Tensorshape and the data type are correct
200  BOOST_TEST((addedReshapeTensorInfo.GetShape() == TensorShape({ 1, 1, 4, 5 })));
201  BOOST_TEST((addedReshapeTensorInfo.GetDataType() == DataType::QAsymmS8));
202 }
203 
204 BOOST_AUTO_TEST_CASE(AddBroadcastReshapeLayerMultiplicationTest)
205 {
206  Graph graph;
207  const TensorInfo info0({ 3, 5 }, DataType::QAsymmU8);
208  const TensorInfo info1({ 1, 2, 3, 5 }, DataType::QAsymmU8);
209  const TensorInfo outputInfo({ 1, 2, 3, 5 }, DataType::QAsymmU8);
210 
211  auto input0 = graph.AddLayer<InputLayer>(0, "input0");
212  auto input1 = graph.AddLayer<InputLayer>(1, "input1");
213  auto mul = graph.AddLayer<MultiplicationLayer>("mul");
214  auto output = graph.AddLayer<OutputLayer>(0, "output");
215  input0->GetOutputSlot().SetTensorInfo(info0);
216  input1->GetOutputSlot().SetTensorInfo(info1);
217  mul->GetOutputSlot().SetTensorInfo(outputInfo);
218 
219  input0->GetOutputSlot().Connect(mul->GetInputSlot(0));
220  input1->GetOutputSlot().Connect(mul->GetInputSlot(1));
221  mul->GetOutputSlot().Connect(output->GetInputSlot(0));
222 
223  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
224  &IsLayerOfType<InputLayer>,
225  &IsLayerOfType<InputLayer>,
226  &IsLayerOfType<MultiplicationLayer>,
227  &IsLayerOfType<OutputLayer>));
228 
229  // Run optimizer
231 
232  // Broadcast reshape layer has been added to the graph correctly
233  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
234  &IsLayerOfType<InputLayer>,
235  &IsLayerOfType<InputLayer>,
236  &IsLayerOfType<ReshapeLayer>,
237  &IsLayerOfType<MultiplicationLayer>,
238  &IsLayerOfType<OutputLayer>));
239 
240  Layer* const reshapeLayer = GetFirstLayerWithName(graph, "Reshape_for:mul-0");
241  BOOST_TEST(reshapeLayer);
242  auto addedReshapeTensorInfo = reshapeLayer->GetOutputSlot().GetTensorInfo();
243 
244  // Tensorshape and the data type are correct
245  BOOST_TEST((addedReshapeTensorInfo.GetShape() == TensorShape({ 1, 1, 3, 5 })));
246  BOOST_TEST((addedReshapeTensorInfo.GetDataType() == DataType::QAsymmU8));
247 }
248 
249 BOOST_AUTO_TEST_CASE(AddNoBroadcastReshapeLayerTest)
250 {
251  Graph graph;
252  const TensorInfo info0({ 1, 1, 1, 1 }, DataType::QAsymmU8);
253  const TensorInfo info1({ 1, 2, 3, 5 }, DataType::QAsymmU8);
254  const TensorInfo outputInfo({ 1, 2, 3, 5 }, DataType::QAsymmU8);
255 
256  auto input0 = graph.AddLayer<InputLayer>(0, "input0");
257  auto input1 = graph.AddLayer<InputLayer>(1, "input1");
258  auto mul = graph.AddLayer<MultiplicationLayer>("mul");
259  auto output = graph.AddLayer<OutputLayer>(0, "output");
260  input0->GetOutputSlot().SetTensorInfo(info0);
261  input1->GetOutputSlot().SetTensorInfo(info1);
262  mul->GetOutputSlot().SetTensorInfo(outputInfo);
263 
264  input0->GetOutputSlot().Connect(mul->GetInputSlot(0));
265  input1->GetOutputSlot().Connect(mul->GetInputSlot(1));
266  mul->GetOutputSlot().Connect(output->GetInputSlot(0));
267 
268  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
269  &IsLayerOfType<InputLayer>,
270  &IsLayerOfType<InputLayer>,
271  &IsLayerOfType<MultiplicationLayer>,
272  &IsLayerOfType<OutputLayer>));
273 
274  // Run optimizer
276 
277  // Broadcast reshape layer has not been added to the graph
278  BOOST_TEST(CheckSequence(graph.cbegin(), graph.cend(),
279  &IsLayerOfType<InputLayer>,
280  &IsLayerOfType<InputLayer>,
281  &IsLayerOfType<MultiplicationLayer>,
282  &IsLayerOfType<OutputLayer>));
283 
284  Layer* const reshapeLayer = GetFirstLayerWithName(graph, "Reshape_for:mul-0");
285  BOOST_TEST(!reshapeLayer);
286 }
287 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
Optimizer::Optimizations MakeOptimizations(Args &&... args)
Definition: Optimizer.hpp:43
armnn::Layer * GetFirstLayerWithName(armnn::Graph &graph, const std::string &name)
Definition: GraphUtils.cpp:22
void AddBroadcastReshapeLayerOptimizerTest(const TensorInfo &info0, const TensorInfo &info1, const TensorInfo &outputInfo, const std::string &reshapeLayerName, const TensorShape &expectedReshapeShape, const DataType expectedDataType)
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
Definition: Graph.hpp:402
ConstIterator cbegin() const
Returns const iterator pointing to the beginning of the list. Lowercase for range-based for loops...
Definition: Graph.hpp:172
int Connect(InputSlot &destination)
Definition: Layer.cpp:83
static void Pass(Graph &graph, const Optimizations &optimizations)
Definition: Optimizer.cpp:16
Copyright (c) 2021 ARM Limited and Contributors.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:316
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: OutputLayer.hpp:13
DataType
Definition: Types.hpp:32
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
This layer represents an addition operation.
BOOST_AUTO_TEST_SUITE_END()
This layer represents a subtraction operation.
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: InputLayer.hpp:13
bool CheckSequence(const armnn::Graph::ConstIterator first, const armnn::Graph::ConstIterator last)
Definition: TestUtils.hpp:21
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:58
This layer represents a division operation.
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:318
ConstIterator cend() const
Returns const iterator pointing to the end of the list. Lowercase for range-based for loops...
Definition: Graph.hpp:174
OptimizeForType< Layer, AddBroadcastReshapeLayerImpl > AddBroadcastReshapeLayer
This layer represents a multiplication operation.
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63