blob: 812a4780f4de99413059542e8bd0974f45e76416 [file] [log] [blame]
Mike Kelly8c1701a2019-02-11 17:01:27 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Mike Kelly8c1701a2019-02-11 17:01:27 +00006#include "../Serializer.hpp"
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00007
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00008#include <armnn/ArmNN.hpp>
9#include <armnn/INetwork.hpp>
Derek Lamberti0028d1b2019-02-20 13:57:42 +000010#include <armnnDeserializer/IDeserializer.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000011
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +000012#include <random>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000013#include <vector>
14
Mike Kelly8c1701a2019-02-11 17:01:27 +000015#include <boost/test/unit_test.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000016
Derek Lamberti0028d1b2019-02-20 13:57:42 +000017using armnnDeserializer::IDeserializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000018
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000019namespace
20{
21
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000022struct DefaultLayerVerifierPolicy
23{
Les Belle0ca8612019-05-17 16:17:12 +010024 static void Apply(const std::string s = "")
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000025 {
26 BOOST_TEST_MESSAGE("Unexpected layer found in network");
27 BOOST_TEST(false);
28 }
29};
30
31class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
32{
33public:
34 LayerVerifierBase(const std::string& layerName,
35 const std::vector<armnn::TensorInfo>& inputInfos,
36 const std::vector<armnn::TensorInfo>& outputInfos)
37 : m_LayerName(layerName)
38 , m_InputTensorInfos(inputInfos)
39 , m_OutputTensorInfos(outputInfos) {}
40
41 void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
42
43 void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId id, const char*) override {}
44
45protected:
46 void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
47 {
48 BOOST_TEST(name == m_LayerName.c_str());
49
50 BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
51 BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
52
53 for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
54 {
55 const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
56 BOOST_CHECK(connectedOutput);
57
58 const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
59 BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
60 BOOST_TEST(
61 GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000062
63 BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
64 BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000065 }
66
67 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
68 {
69 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
70 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
71 BOOST_TEST(
72 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000073
74 BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
75 BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000076 }
77 }
78
79private:
80 std::string m_LayerName;
81 std::vector<armnn::TensorInfo> m_InputTensorInfos;
82 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
83};
84
85template<typename T>
86void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
87{
88 T typedData1 = static_cast<T>(data1);
89 T typedData2 = static_cast<T>(data2);
90 BOOST_CHECK(typedData1);
91 BOOST_CHECK(typedData2);
92
93 for (unsigned int i = 0; i < numElements; i++)
94 {
95 BOOST_TEST(typedData1[i] == typedData2[i]);
96 }
97}
98
99void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
100{
101 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
102 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
103
104 switch (tensor1.GetDataType())
105 {
106 case armnn::DataType::Float32:
107 CompareConstTensorData<const float*>(
108 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
109 break;
110 case armnn::DataType::QuantisedAsymm8:
111 case armnn::DataType::Boolean:
112 CompareConstTensorData<const uint8_t*>(
113 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
114 break;
115 case armnn::DataType::Signed32:
116 CompareConstTensorData<const int32_t*>(
117 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
118 break;
119 default:
120 // Note that Float16 is not yet implemented
121 BOOST_TEST_MESSAGE("Unexpected datatype");
122 BOOST_TEST(false);
123 }
124}
125
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000126armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
127{
128 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000129 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000130}
131
132std::string SerializeNetwork(const armnn::INetwork& network)
133{
134 armnnSerializer::Serializer serializer;
135 serializer.Serialize(network);
136
137 std::stringstream stream;
138 serializer.SaveSerializedToStream(stream);
139
140 std::string serializerString{stream.str()};
141 return serializerString;
142}
143
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000144template<typename DataType>
145static std::vector<DataType> GenerateRandomData(size_t size)
146{
147 constexpr bool isIntegerType = std::is_integral<DataType>::value;
148 using Distribution =
149 typename std::conditional<isIntegerType,
150 std::uniform_int_distribution<DataType>,
151 std::uniform_real_distribution<DataType>>::type;
152
153 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
154 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
155
156 static Distribution distribution(lowerLimit, upperLimit);
157 static std::default_random_engine generator;
158
159 std::vector<DataType> randomData(size);
160 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
161
162 return randomData;
163}
164
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000165} // anonymous namespace
166
167BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000168
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000169BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000170{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000171 class AdditionLayerVerifier : public LayerVerifierBase
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000172 {
173 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000174 AdditionLayerVerifier(const std::string& layerName,
175 const std::vector<armnn::TensorInfo>& inputInfos,
176 const std::vector<armnn::TensorInfo>& outputInfos)
177 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
178
179 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name) override
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000180 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000181 VerifyNameAndConnections(layer, name);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000182 }
183 };
184
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000185 const std::string layerName("addition");
186 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
187
Mike Kelly8c1701a2019-02-11 17:01:27 +0000188 armnn::INetworkPtr network = armnn::INetwork::Create();
189 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
190 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000191 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
192 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000193
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000194 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
195 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000196 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000197
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000198 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
199 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
200 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000201
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000202 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000203 BOOST_CHECK(deserializedNetwork);
204
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000205 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
206 deserializedNetwork->Accept(verifier);
207}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000208
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000209BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
210{
211 class BatchNormalizationLayerVerifier : public LayerVerifierBase
212 {
213 public:
214 BatchNormalizationLayerVerifier(const std::string& layerName,
215 const std::vector<armnn::TensorInfo>& inputInfos,
216 const std::vector<armnn::TensorInfo>& outputInfos,
217 const armnn::BatchNormalizationDescriptor& descriptor,
218 const armnn::ConstTensor& mean,
219 const armnn::ConstTensor& variance,
220 const armnn::ConstTensor& beta,
221 const armnn::ConstTensor& gamma)
222 : LayerVerifierBase(layerName, inputInfos, outputInfos)
223 , m_Descriptor(descriptor)
224 , m_Mean(mean)
225 , m_Variance(variance)
226 , m_Beta(beta)
227 , m_Gamma(gamma) {}
228
229 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
230 const armnn::BatchNormalizationDescriptor& descriptor,
231 const armnn::ConstTensor& mean,
232 const armnn::ConstTensor& variance,
233 const armnn::ConstTensor& beta,
234 const armnn::ConstTensor& gamma,
235 const char* name) override
236 {
237 VerifyNameAndConnections(layer, name);
238 VerifyDescriptor(descriptor);
239
240 CompareConstTensor(mean, m_Mean);
241 CompareConstTensor(variance, m_Variance);
242 CompareConstTensor(beta, m_Beta);
243 CompareConstTensor(gamma, m_Gamma);
244 }
245
246 private:
247 void VerifyDescriptor(const armnn::BatchNormalizationDescriptor& descriptor)
248 {
249 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
250 BOOST_TEST(static_cast<int>(descriptor.m_DataLayout) == static_cast<int>(m_Descriptor.m_DataLayout));
251 }
252
253 armnn::BatchNormalizationDescriptor m_Descriptor;
254 armnn::ConstTensor m_Mean;
255 armnn::ConstTensor m_Variance;
256 armnn::ConstTensor m_Beta;
257 armnn::ConstTensor m_Gamma;
258 };
259
260 const std::string layerName("batchNormalization");
261 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
262 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
263
264 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
265 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
266 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
267 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
268
269 armnn::BatchNormalizationDescriptor descriptor;
270 descriptor.m_Eps = 0.0010000000475f;
271 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
272
273 std::vector<float> meanData({5.0});
274 std::vector<float> varianceData({2.0});
275 std::vector<float> betaData({1.0});
276 std::vector<float> gammaData({0.0});
277
278 armnn::ConstTensor mean(meanInfo, meanData);
279 armnn::ConstTensor variance(varianceInfo, varianceData);
280 armnn::ConstTensor beta(betaInfo, betaData);
281 armnn::ConstTensor gamma(gammaInfo, gammaData);
282
283 armnn::INetworkPtr network = armnn::INetwork::Create();
284 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
285 armnn::IConnectableLayer* const batchNormalizationLayer =
286 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
287 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
288
289 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
290 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
291
292 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
293 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
294
295 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
296 BOOST_CHECK(deserializedNetwork);
297
298 BatchNormalizationLayerVerifier verifier(
299 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
300 deserializedNetwork->Accept(verifier);
301}
302
303BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
304{
305 class BatchToSpaceNdLayerVerifier : public LayerVerifierBase
306 {
307 public:
308 BatchToSpaceNdLayerVerifier(const std::string& layerName,
309 const std::vector<armnn::TensorInfo>& inputInfos,
310 const std::vector<armnn::TensorInfo>& outputInfos,
311 const armnn::BatchToSpaceNdDescriptor& descriptor)
312 : LayerVerifierBase(layerName, inputInfos, outputInfos)
313 , m_Descriptor(descriptor) {}
314
315 void VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
316 const armnn::BatchToSpaceNdDescriptor& descriptor,
317 const char* name) override
318 {
319 VerifyNameAndConnections(layer, name);
320 VerifyDescriptor(descriptor);
321 }
322
323 private:
324 void VerifyDescriptor(const armnn::BatchToSpaceNdDescriptor& descriptor)
325 {
326 BOOST_TEST(descriptor.m_Crops == m_Descriptor.m_Crops);
327 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
328 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
329 }
330
331 armnn::BatchToSpaceNdDescriptor m_Descriptor;
332 };
333
334 const std::string layerName("spaceToBatchNd");
335 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
336 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
337
338 armnn::BatchToSpaceNdDescriptor desc;
339 desc.m_DataLayout = armnn::DataLayout::NCHW;
340 desc.m_BlockShape = {2, 2};
341 desc.m_Crops = {{0, 0}, {0, 0}};
342
343 armnn::INetworkPtr network = armnn::INetwork::Create();
344 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
345 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
346 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
347
348 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
349 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
350
351 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
352 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
353
354 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
355 BOOST_CHECK(deserializedNetwork);
356
357 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
358 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000359}
360
Conor Kennedy76277882019-02-26 08:29:54 +0000361BOOST_AUTO_TEST_CASE(SerializeConstant)
362{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000363 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000364 {
365 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000366 ConstantLayerVerifier(const std::string& layerName,
367 const std::vector<armnn::TensorInfo>& inputInfos,
368 const std::vector<armnn::TensorInfo>& outputInfos,
369 const armnn::ConstTensor& layerInput)
370 : LayerVerifierBase(layerName, inputInfos, outputInfos)
371 , m_LayerInput(layerInput) {}
372
373 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
374 const armnn::ConstTensor& input,
375 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000376 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000377 VerifyNameAndConnections(layer, name);
378
379 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000380 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000381
382 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
383
384 private:
385 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000386 };
387
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000388 const std::string layerName("constant");
389 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000390
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000391 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
392 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000393
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000394 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000395 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000396 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000397 armnn::IConnectableLayer* add = network->AddAdditionLayer();
398 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000399
400 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
401 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
402 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
403
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000404 input->GetOutputSlot(0).SetTensorInfo(info);
405 constant->GetOutputSlot(0).SetTensorInfo(info);
406 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000407
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000408 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000409 BOOST_CHECK(deserializedNetwork);
410
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000411 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
412 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000413}
414
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000415BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000416{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000417 class Convolution2dLayerVerifier : public LayerVerifierBase
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000418 {
419 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000420 Convolution2dLayerVerifier(const std::string& layerName,
421 const std::vector<armnn::TensorInfo>& inputInfos,
422 const std::vector<armnn::TensorInfo>& outputInfos,
423 const armnn::Convolution2dDescriptor& descriptor,
424 const armnn::ConstTensor& weight,
425 const armnn::Optional<armnn::ConstTensor>& bias)
426 : LayerVerifierBase(layerName, inputInfos, outputInfos)
427 , m_Descriptor(descriptor)
428 , m_Weight(weight)
429 , m_Bias(bias) {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000430
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000431 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
432 const armnn::Convolution2dDescriptor& descriptor,
433 const armnn::ConstTensor& weight,
434 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000435 const char* name) override
436 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000437 VerifyNameAndConnections(layer, name);
438 VerifyDescriptor(descriptor);
439
440 CompareConstTensor(weight, m_Weight);
441
442 BOOST_TEST(bias.has_value() == m_Bias.has_value());
443 if (bias.has_value() && m_Bias.has_value())
444 {
445 CompareConstTensor(bias.value(), m_Bias.value());
446 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000447 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000448
449 private:
450 void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor)
451 {
452 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
453 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
454 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
455 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
456 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
457 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
458 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
459 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
460 }
461
462 armnn::Convolution2dDescriptor m_Descriptor;
463 armnn::ConstTensor m_Weight;
464 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000465 };
466
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000467 const std::string layerName("convolution2d");
468 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
469 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000470
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000471 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
472 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000473
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000474 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
475 armnn::ConstTensor weights(weightsInfo, weightsData);
476
477 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
478 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000479
480 armnn::Convolution2dDescriptor descriptor;
481 descriptor.m_PadLeft = 1;
482 descriptor.m_PadRight = 1;
483 descriptor.m_PadTop = 1;
484 descriptor.m_PadBottom = 1;
485 descriptor.m_StrideX = 2;
486 descriptor.m_StrideY = 2;
487 descriptor.m_BiasEnabled = true;
488 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
489
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000490 armnn::INetworkPtr network = armnn::INetwork::Create();
491 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000492 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100493 network->AddConvolution2dLayer(descriptor,
494 weights,
495 armnn::Optional<armnn::ConstTensor>(biases),
496 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000497 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000498
499 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000500 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000501
502 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000503 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
504
505 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
506 BOOST_CHECK(deserializedNetwork);
507
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000508 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
509 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000510}
511
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000512BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000513{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000514 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000515 {
516 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000517 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
518 const std::vector<armnn::TensorInfo>& inputInfos,
519 const std::vector<armnn::TensorInfo>& outputInfos,
520 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
521 const armnn::ConstTensor& weight,
522 const armnn::Optional<armnn::ConstTensor>& bias)
523 : LayerVerifierBase(layerName, inputInfos, outputInfos)
524 , m_Descriptor(descriptor)
525 , m_Weight(weight)
526 , m_Bias(bias) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000527
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000528 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
529 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
530 const armnn::ConstTensor& weight,
531 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000532 const char* name) override
533 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000534 VerifyNameAndConnections(layer, name);
535 VerifyDescriptor(descriptor);
536
537 CompareConstTensor(weight, m_Weight);
538
539 BOOST_TEST(bias.has_value() == m_Bias.has_value());
540 if (bias.has_value() && m_Bias.has_value())
541 {
542 CompareConstTensor(bias.value(), m_Bias.value());
543 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000544 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000545
546 private:
547 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
548 {
549 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
550 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
551 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
552 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
553 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
554 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
555 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
556 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
557 }
558
559 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
560 armnn::ConstTensor m_Weight;
561 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000562 };
563
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000564 const std::string layerName("depwiseConvolution2d");
565 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
566 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000567
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000568 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
569 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000570
571 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
572 armnn::ConstTensor weights(weightsInfo, weightsData);
573
574 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
575 armnn::ConstTensor biases(biasesInfo, biasesData);
576
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000577 armnn::DepthwiseConvolution2dDescriptor descriptor;
578 descriptor.m_StrideX = 1;
579 descriptor.m_StrideY = 1;
580 descriptor.m_BiasEnabled = true;
581 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
582
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000583 armnn::INetworkPtr network = armnn::INetwork::Create();
584 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
585 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100586 network->AddDepthwiseConvolution2dLayer(descriptor,
587 weights,
588 armnn::Optional<armnn::ConstTensor>(biases),
589 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000590 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
591
592 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000593 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000594
595 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000596 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
597
598 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
599 BOOST_CHECK(deserializedNetwork);
600
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000601 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
602 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000603}
604
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000605BOOST_AUTO_TEST_CASE(SerializeDequantize)
606{
607 class DequantizeLayerVerifier : public LayerVerifierBase
608 {
609 public:
610 DequantizeLayerVerifier(const std::string& layerName,
611 const std::vector<armnn::TensorInfo>& inputInfos,
612 const std::vector<armnn::TensorInfo>& outputInfos)
613 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
614
615 void VisitDequantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
616 {
617 VerifyNameAndConnections(layer, name);
618 }
619 };
620
621 const std::string layerName("dequantize");
622 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
623 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
624
625 armnn::INetworkPtr network = armnn::INetwork::Create();
626 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
627 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
628 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
629
630 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
631 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
632
633 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
634 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
635
636 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
637 BOOST_CHECK(deserializedNetwork);
638
639 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
640 deserializedNetwork->Accept(verifier);
641}
642
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000643BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
644{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000645 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000646 {
647 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000648 DetectionPostProcessLayerVerifier(const std::string& layerName,
649 const std::vector<armnn::TensorInfo>& inputInfos,
650 const std::vector<armnn::TensorInfo>& outputInfos,
651 const armnn::DetectionPostProcessDescriptor& descriptor,
652 const armnn::ConstTensor& anchors)
653 : LayerVerifierBase(layerName, inputInfos, outputInfos)
654 , m_Descriptor(descriptor)
655 , m_Anchors(anchors) {}
656
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000657 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
658 const armnn::DetectionPostProcessDescriptor& descriptor,
659 const armnn::ConstTensor& anchors,
660 const char* name) override
661 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000662 VerifyNameAndConnections(layer, name);
663 VerifyDescriptor(descriptor);
664
665 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000666 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000667
668 private:
669 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
670 {
671 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
672 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
673 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
674 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
675 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
676 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
677 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
678 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
679 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
680 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
681 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
682 }
683
684 armnn::DetectionPostProcessDescriptor m_Descriptor;
685 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000686 };
687
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000688 const std::string layerName("detectionPostProcess");
689
690 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000691 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
692 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000693 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000694
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000695 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000696 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
697 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
698 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
699 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000700 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000701
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000702 armnn::DetectionPostProcessDescriptor descriptor;
703 descriptor.m_UseRegularNms = true;
704 descriptor.m_MaxDetections = 3;
705 descriptor.m_MaxClassesPerDetection = 1;
706 descriptor.m_DetectionsPerClass =1;
707 descriptor.m_NmsScoreThreshold = 0.0;
708 descriptor.m_NmsIouThreshold = 0.5;
709 descriptor.m_NumClasses = 2;
710 descriptor.m_ScaleY = 10.0;
711 descriptor.m_ScaleX = 10.0;
712 descriptor.m_ScaleH = 5.0;
713 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000714
715 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
716 const std::vector<float> anchorsData({
717 0.5f, 0.5f, 1.0f, 1.0f,
718 0.5f, 0.5f, 1.0f, 1.0f,
719 0.5f, 0.5f, 1.0f, 1.0f,
720 0.5f, 10.5f, 1.0f, 1.0f,
721 0.5f, 10.5f, 1.0f, 1.0f,
722 0.5f, 100.5f, 1.0f, 1.0f
723 });
724 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
725
726 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000727 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000728 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000729
730 for (unsigned int i = 0; i < 2; i++)
731 {
732 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
733 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
734 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
735 }
736
737 for (unsigned int i = 0; i < 4; i++)
738 {
739 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
740 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
741 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
742 }
743
744 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
745 BOOST_CHECK(deserializedNetwork);
746
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000747 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
748 deserializedNetwork->Accept(verifier);
749}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000750
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000751BOOST_AUTO_TEST_CASE(SerializeDivision)
752{
753 class DivisionLayerVerifier : public LayerVerifierBase
754 {
755 public:
756 DivisionLayerVerifier(const std::string& layerName,
757 const std::vector<armnn::TensorInfo>& inputInfos,
758 const std::vector<armnn::TensorInfo>& outputInfos)
759 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
760
761 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
762 {
763 VerifyNameAndConnections(layer, name);
764 }
765 };
766
767 const std::string layerName("division");
768 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
769
770 armnn::INetworkPtr network = armnn::INetwork::Create();
771 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
772 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
773 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
774 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
775
776 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
777 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
778 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
779
780 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
781 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
782 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
783
784 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
785 BOOST_CHECK(deserializedNetwork);
786
787 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
788 deserializedNetwork->Accept(verifier);
789}
790
791BOOST_AUTO_TEST_CASE(SerializeEqual)
792{
793 class EqualLayerVerifier : public LayerVerifierBase
794 {
795 public:
796 EqualLayerVerifier(const std::string& layerName,
797 const std::vector<armnn::TensorInfo>& inputInfos,
798 const std::vector<armnn::TensorInfo>& outputInfos)
799 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
800
801 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
802 {
803 VerifyNameAndConnections(layer, name);
804 }
805 };
806
807 const std::string layerName("equal");
808 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
809 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
810 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
811
812 armnn::INetworkPtr network = armnn::INetwork::Create();
813 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
814 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
815 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
816 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
817
818 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
819 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
820 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
821
822 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
823 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
824 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
825
826 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
827 BOOST_CHECK(deserializedNetwork);
828
829 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
830 deserializedNetwork->Accept(verifier);
831}
832
833BOOST_AUTO_TEST_CASE(SerializeFloor)
834{
835 class FloorLayerVerifier : public LayerVerifierBase
836 {
837 public:
838 FloorLayerVerifier(const std::string& layerName,
839 const std::vector<armnn::TensorInfo>& inputInfos,
840 const std::vector<armnn::TensorInfo>& outputInfos)
841 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
842
843 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
844 {
845 VerifyNameAndConnections(layer, name);
846 }
847 };
848
849 const std::string layerName("floor");
850 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
851
852 armnn::INetworkPtr network = armnn::INetwork::Create();
853 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
854 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
855 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
856
857 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
858 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
859
860 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
861 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
862
863 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
864 BOOST_CHECK(deserializedNetwork);
865
866 FloorLayerVerifier verifier(layerName, {info}, {info});
867 deserializedNetwork->Accept(verifier);
868}
869
870BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
871{
872 class FullyConnectedLayerVerifier : public LayerVerifierBase
873 {
874 public:
875 FullyConnectedLayerVerifier(const std::string& layerName,
876 const std::vector<armnn::TensorInfo>& inputInfos,
877 const std::vector<armnn::TensorInfo>& outputInfos,
878 const armnn::FullyConnectedDescriptor& descriptor,
879 const armnn::ConstTensor& weight,
880 const armnn::Optional<armnn::ConstTensor>& bias)
881 : LayerVerifierBase(layerName, inputInfos, outputInfos)
882 , m_Descriptor(descriptor)
883 , m_Weight(weight)
884 , m_Bias(bias) {}
885
886 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
887 const armnn::FullyConnectedDescriptor& descriptor,
888 const armnn::ConstTensor& weight,
889 const armnn::Optional<armnn::ConstTensor>& bias,
890 const char* name) override
891 {
892 VerifyNameAndConnections(layer, name);
893 VerifyDescriptor(descriptor);
894
895 CompareConstTensor(weight, m_Weight);
896
897 BOOST_TEST(bias.has_value() == m_Bias.has_value());
898 if (bias.has_value() && m_Bias.has_value())
899 {
900 CompareConstTensor(bias.value(), m_Bias.value());
901 }
902 }
903
904 private:
905 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
906 {
907 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
908 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
909 }
910
911 armnn::FullyConnectedDescriptor m_Descriptor;
912 armnn::ConstTensor m_Weight;
913 armnn::Optional<armnn::ConstTensor> m_Bias;
914 };
915
916 const std::string layerName("fullyConnected");
917 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
918 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
919
920 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
921 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
922 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
923 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
924 armnn::ConstTensor weights(weightsInfo, weightsData);
925 armnn::ConstTensor biases(biasesInfo, biasesData);
926
927 armnn::FullyConnectedDescriptor descriptor;
928 descriptor.m_BiasEnabled = true;
929 descriptor.m_TransposeWeightMatrix = false;
930
931 armnn::INetworkPtr network = armnn::INetwork::Create();
932 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
933 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100934 network->AddFullyConnectedLayer(descriptor,
935 weights,
936 armnn::Optional<armnn::ConstTensor>(biases),
937 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000938 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
939
940 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
941 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
942
943 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
944 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
945
946 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
947 BOOST_CHECK(deserializedNetwork);
948
949 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
950 deserializedNetwork->Accept(verifier);
951}
952
953BOOST_AUTO_TEST_CASE(SerializeGather)
954{
955 class GatherLayerVerifier : public LayerVerifierBase
956 {
957 public:
958 GatherLayerVerifier(const std::string& layerName,
959 const std::vector<armnn::TensorInfo>& inputInfos,
960 const std::vector<armnn::TensorInfo>& outputInfos)
961 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
962
963 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
964 {
965 VerifyNameAndConnections(layer, name);
966 }
967
968 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
969 const armnn::ConstTensor& input,
970 const char *name) override {}
971 };
972
973 const std::string layerName("gather");
974 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
975 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
976 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
977
978 paramsInfo.SetQuantizationScale(1.0f);
979 paramsInfo.SetQuantizationOffset(0);
980 outputInfo.SetQuantizationScale(1.0f);
981 outputInfo.SetQuantizationOffset(0);
982
983 const std::vector<int32_t>& indicesData = {7, 6, 5};
984
985 armnn::INetworkPtr network = armnn::INetwork::Create();
986 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
987 armnn::IConnectableLayer *const constantLayer =
988 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
989 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
990 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
991
992 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
993 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
994 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
995
996 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
997 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
998 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
999
1000 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1001 BOOST_CHECK(deserializedNetwork);
1002
1003 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1004 deserializedNetwork->Accept(verifier);
1005}
1006
1007BOOST_AUTO_TEST_CASE(SerializeGreater)
1008{
1009 class GreaterLayerVerifier : public LayerVerifierBase
1010 {
1011 public:
1012 GreaterLayerVerifier(const std::string& layerName,
1013 const std::vector<armnn::TensorInfo>& inputInfos,
1014 const std::vector<armnn::TensorInfo>& outputInfos)
1015 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1016
1017 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1018 {
1019 VerifyNameAndConnections(layer, name);
1020 }
1021 };
1022
1023 const std::string layerName("greater");
1024 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1025 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1026 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
1027
1028 armnn::INetworkPtr network = armnn::INetwork::Create();
1029 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
1030 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
1031 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
1032 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1033
1034 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
1035 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
1036 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1037
1038 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
1039 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
1040 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1041
1042 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1043 BOOST_CHECK(deserializedNetwork);
1044
1045 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
1046 deserializedNetwork->Accept(verifier);
1047}
1048
1049BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1050{
1051 class L2NormalizationLayerVerifier : public LayerVerifierBase
1052 {
1053 public:
1054 L2NormalizationLayerVerifier(const std::string& layerName,
1055 const std::vector<armnn::TensorInfo>& inputInfos,
1056 const std::vector<armnn::TensorInfo>& outputInfos,
1057 const armnn::L2NormalizationDescriptor& descriptor)
1058 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1059 , m_Descriptor(descriptor) {}
1060
1061 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1062 const armnn::L2NormalizationDescriptor& descriptor,
1063 const char* name) override
1064 {
1065 VerifyNameAndConnections(layer, name);
1066 VerifyDescriptor(descriptor);
1067 }
1068 private:
1069 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1070 {
1071 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1072 }
1073
1074 armnn::L2NormalizationDescriptor m_Descriptor;
1075 };
1076
1077 const std::string l2NormLayerName("l2Normalization");
1078 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1079
1080 armnn::L2NormalizationDescriptor desc;
1081 desc.m_DataLayout = armnn::DataLayout::NCHW;
1082
1083 armnn::INetworkPtr network = armnn::INetwork::Create();
1084 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1085 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1086 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1087
1088 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1089 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1090
1091 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1092 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1093
1094 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1095 BOOST_CHECK(deserializedNetwork);
1096
1097 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1098 deserializedNetwork->Accept(verifier);
1099}
1100
1101BOOST_AUTO_TEST_CASE(SerializeMaximum)
1102{
1103 class MaximumLayerVerifier : public LayerVerifierBase
1104 {
1105 public:
1106 MaximumLayerVerifier(const std::string& layerName,
1107 const std::vector<armnn::TensorInfo>& inputInfos,
1108 const std::vector<armnn::TensorInfo>& outputInfos)
1109 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1110
1111 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1112 {
1113 VerifyNameAndConnections(layer, name);
1114 }
1115 };
1116
1117 const std::string layerName("maximum");
1118 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1119
1120 armnn::INetworkPtr network = armnn::INetwork::Create();
1121 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1122 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1123 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1124 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1125
1126 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1127 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1128 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1129
1130 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1131 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1132 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1133
1134 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1135 BOOST_CHECK(deserializedNetwork);
1136
1137 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1138 deserializedNetwork->Accept(verifier);
1139}
1140
1141BOOST_AUTO_TEST_CASE(SerializeMean)
1142{
1143 class MeanLayerVerifier : public LayerVerifierBase
1144 {
1145 public:
1146 MeanLayerVerifier(const std::string& layerName,
1147 const std::vector<armnn::TensorInfo>& inputInfos,
1148 const std::vector<armnn::TensorInfo>& outputInfos,
1149 const armnn::MeanDescriptor& descriptor)
1150 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1151 , m_Descriptor(descriptor) {}
1152
1153 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1154 const armnn::MeanDescriptor& descriptor,
1155 const char* name) override
1156 {
1157 VerifyNameAndConnections(layer, name);
1158 VerifyDescriptor(descriptor);
1159 }
1160
1161 private:
1162 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1163 {
1164 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1165 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1166 }
1167
1168 armnn::MeanDescriptor m_Descriptor;
1169 };
1170
1171 const std::string layerName("mean");
1172 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1173 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1174
1175 armnn::MeanDescriptor descriptor;
1176 descriptor.m_Axis = { 2 };
1177 descriptor.m_KeepDims = true;
1178
1179 armnn::INetworkPtr network = armnn::INetwork::Create();
1180 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1181 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1182 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1183
1184 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1185 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1186
1187 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1188 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1189
1190 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1191 BOOST_CHECK(deserializedNetwork);
1192
1193 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1194 deserializedNetwork->Accept(verifier);
1195}
1196
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001197BOOST_AUTO_TEST_CASE(SerializeMerge)
1198{
1199 class MergeLayerVerifier : public LayerVerifierBase
1200 {
1201 public:
1202 MergeLayerVerifier(const std::string& layerName,
1203 const std::vector<armnn::TensorInfo>& inputInfos,
1204 const std::vector<armnn::TensorInfo>& outputInfos)
1205 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1206
1207 void VisitMergeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1208 {
1209 VerifyNameAndConnections(layer, name);
1210 }
1211 };
1212
1213 const std::string layerName("merge");
1214 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1215
1216 armnn::INetworkPtr network = armnn::INetwork::Create();
1217 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1218 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1219 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1220 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1221
1222 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1223 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1224 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1225
1226 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1227 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1228 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1229
1230 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1231 BOOST_CHECK(deserializedNetwork);
1232
1233 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1234 deserializedNetwork->Accept(verifier);
1235}
1236
Jim Flynn5fa83932019-05-09 15:35:43 +01001237class MergerLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001238{
Jim Flynn5fa83932019-05-09 15:35:43 +01001239public:
1240 MergerLayerVerifier(const std::string& layerName,
1241 const std::vector<armnn::TensorInfo>& inputInfos,
1242 const std::vector<armnn::TensorInfo>& outputInfos,
1243 const armnn::OriginsDescriptor& descriptor)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001244 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1245 , m_Descriptor(descriptor) {}
1246
Jim Flynn5fa83932019-05-09 15:35:43 +01001247 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1248 const armnn::OriginsDescriptor& descriptor,
1249 const char* name) override
1250 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001251 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1252 }
1253
1254 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1255 const armnn::OriginsDescriptor& descriptor,
1256 const char* name) override
1257 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001258 VerifyNameAndConnections(layer, name);
1259 VerifyDescriptor(descriptor);
1260 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001261
Jim Flynn5fa83932019-05-09 15:35:43 +01001262private:
1263 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1264 {
1265 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1266 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1267 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001268
Jim Flynn5fa83932019-05-09 15:35:43 +01001269 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1270 {
1271 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001272 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001273 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001274 }
1275 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001276 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001277
Jim Flynn5fa83932019-05-09 15:35:43 +01001278 armnn::OriginsDescriptor m_Descriptor;
1279};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001280
Jim Flynne242f2d2019-05-22 14:24:13 +01001281// NOTE: until the deprecated AddMergerLayer disappears this test checks that calling
1282// AddMergerLayer places a ConcatLayer into the serialized format and that
1283// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001284BOOST_AUTO_TEST_CASE(SerializeMerger)
1285{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001286 const std::string layerName("merger");
1287 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1288 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1289
1290 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1291
1292 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001293 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001294
1295 armnn::INetworkPtr network = armnn::INetwork::Create();
1296 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1297 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001298 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001299 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001300 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001301 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1302
1303 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1304 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1305 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1306
1307 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1308 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1309 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1310
Jim Flynn5fa83932019-05-09 15:35:43 +01001311 std::string mergerLayerNetwork = SerializeNetwork(*network);
1312 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001313 BOOST_CHECK(deserializedNetwork);
1314
1315 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1316 deserializedNetwork->Accept(verifier);
1317}
1318
Jim Flynn5fa83932019-05-09 15:35:43 +01001319BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1320{
1321 // The hex array below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001322 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1323 //
1324 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001325 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Jim Flynn5fa83932019-05-09 15:35:43 +01001326 unsigned int size = 760;
1327 const unsigned char mergerModel[] = {
1328 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1329 0x0C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x02,0x00,0x00,
1330 0x8C,0x01,0x00,0x00,0x70,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1331 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF4,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0B,
1332 0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x9A,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,
1333 0x7E,0xFE,0xFF,0xFF,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1334 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1335 0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xFE,0xFF,0xFF,
1336 0x00,0x00,0x00,0x1F,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1337 0x68,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,
1338 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1339 0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1340 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,
1341 0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1342 0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,
1343 0x14,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x6D,0x65,0x72,0x67,0x65,0x72,0x00,0x00,
1344 0x02,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1345 0x34,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1346 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1347 0x02,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1348 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1349 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1350 0x00,0x00,0x00,0x09,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,
1351 0x0C,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
1352 0x01,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,
1353 0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1354 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1355 0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1356 0x66,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1357 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,
1358 0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,
1359 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1360 0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,
1361 0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1362 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,
1363 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,
1364 0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1365 0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
1366 std::stringstream ss;
1367 for (unsigned int i = 0; i < size; ++i)
1368 {
1369 ss << mergerModel[i];
1370 }
1371 std::string mergerLayerNetwork = ss.str();
1372 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1373 BOOST_CHECK(deserializedNetwork);
1374 const std::string layerName("merger");
1375 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1376 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1377
1378 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1379
1380 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001381 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001382
1383 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1384 deserializedNetwork->Accept(verifier);
1385}
1386
Jim Flynne242f2d2019-05-22 14:24:13 +01001387BOOST_AUTO_TEST_CASE(SerializeConcat)
1388{
1389 const std::string layerName("concat");
1390 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1391 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1392
1393 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1394
1395 armnn::OriginsDescriptor descriptor =
1396 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1397
1398 armnn::INetworkPtr network = armnn::INetwork::Create();
1399 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1400 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1401 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1402 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1403
1404 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1405 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1406 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1407
1408 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1409 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1410 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1411
1412 std::string concatLayerNetwork = SerializeNetwork(*network);
1413 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1414 BOOST_CHECK(deserializedNetwork);
1415
1416 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1417 // merger layer that gets placed into the graph.
1418 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1419 deserializedNetwork->Accept(verifier);
1420}
1421
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001422BOOST_AUTO_TEST_CASE(SerializeMinimum)
1423{
1424 class MinimumLayerVerifier : public LayerVerifierBase
1425 {
1426 public:
1427 MinimumLayerVerifier(const std::string& layerName,
1428 const std::vector<armnn::TensorInfo>& inputInfos,
1429 const std::vector<armnn::TensorInfo>& outputInfos)
1430 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1431
1432 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1433 {
1434 VerifyNameAndConnections(layer, name);
1435 }
1436 };
1437
1438 const std::string layerName("minimum");
1439 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1440
1441 armnn::INetworkPtr network = armnn::INetwork::Create();
1442 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1443 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1444 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1445 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1446
1447 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1448 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1449 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1450
1451 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1452 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1453 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1454
1455 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1456 BOOST_CHECK(deserializedNetwork);
1457
1458 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1459 deserializedNetwork->Accept(verifier);
1460}
1461
1462BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1463{
1464 class MultiplicationLayerVerifier : public LayerVerifierBase
1465 {
1466 public:
1467 MultiplicationLayerVerifier(const std::string& layerName,
1468 const std::vector<armnn::TensorInfo>& inputInfos,
1469 const std::vector<armnn::TensorInfo>& outputInfos)
1470 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1471
1472 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1473 {
1474 VerifyNameAndConnections(layer, name);
1475 }
1476 };
1477
1478 const std::string layerName("multiplication");
1479 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1480
1481 armnn::INetworkPtr network = armnn::INetwork::Create();
1482 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1483 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1484 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1485 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1486
1487 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1488 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1489 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1490
1491 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1492 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1493 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1494
1495 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1496 BOOST_CHECK(deserializedNetwork);
1497
1498 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1499 deserializedNetwork->Accept(verifier);
1500}
1501
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001502BOOST_AUTO_TEST_CASE(SerializePrelu)
1503{
1504 class PreluLayerVerifier : public LayerVerifierBase
1505 {
1506 public:
1507 PreluLayerVerifier(const std::string& layerName,
1508 const std::vector<armnn::TensorInfo>& inputInfos,
1509 const std::vector<armnn::TensorInfo>& outputInfos)
1510 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1511
1512 void VisitPreluLayer(const armnn::IConnectableLayer* layer, const char* name) override
1513 {
1514 VerifyNameAndConnections(layer, name);
1515 }
1516 };
1517
1518 const std::string layerName("prelu");
1519
1520 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1521 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1522 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1523
1524 armnn::INetworkPtr network = armnn::INetwork::Create();
1525 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1526 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1527 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1528 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1529
1530 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1531 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1532 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1533
1534 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1535 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1536 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1537
1538 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1539 BOOST_CHECK(deserializedNetwork);
1540
1541 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1542 deserializedNetwork->Accept(verifier);
1543}
1544
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001545BOOST_AUTO_TEST_CASE(SerializeNormalization)
1546{
1547 class NormalizationLayerVerifier : public LayerVerifierBase
1548 {
1549 public:
1550 NormalizationLayerVerifier(const std::string& layerName,
1551 const std::vector<armnn::TensorInfo>& inputInfos,
1552 const std::vector<armnn::TensorInfo>& outputInfos,
1553 const armnn::NormalizationDescriptor& descriptor)
1554 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1555 , m_Descriptor(descriptor) {}
1556
1557 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1558 const armnn::NormalizationDescriptor& descriptor,
1559 const char* name) override
1560 {
1561 VerifyNameAndConnections(layer, name);
1562 VerifyDescriptor(descriptor);
1563 }
1564
1565 private:
1566 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1567 {
1568 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1569 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1570 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1571 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1572 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1573 BOOST_TEST(
1574 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1575 BOOST_TEST(
1576 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1577 }
1578
1579 armnn::NormalizationDescriptor m_Descriptor;
1580 };
1581
1582 const std::string layerName("normalization");
1583 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1584
1585 armnn::NormalizationDescriptor desc;
1586 desc.m_DataLayout = armnn::DataLayout::NCHW;
1587 desc.m_NormSize = 3;
1588 desc.m_Alpha = 1;
1589 desc.m_Beta = 1;
1590 desc.m_K = 1;
1591
1592 armnn::INetworkPtr network = armnn::INetwork::Create();
1593 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1594 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1595 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1596
1597 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1598 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1599
1600 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1601 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1602
1603 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1604 BOOST_CHECK(deserializedNetwork);
1605
1606 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1607 deserializedNetwork->Accept(verifier);
1608}
1609
1610BOOST_AUTO_TEST_CASE(SerializePad)
1611{
1612 class PadLayerVerifier : public LayerVerifierBase
1613 {
1614 public:
1615 PadLayerVerifier(const std::string& layerName,
1616 const std::vector<armnn::TensorInfo>& inputInfos,
1617 const std::vector<armnn::TensorInfo>& outputInfos,
1618 const armnn::PadDescriptor& descriptor)
1619 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1620 , m_Descriptor(descriptor) {}
1621
1622 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1623 const armnn::PadDescriptor& descriptor,
1624 const char* name) override
1625 {
1626 VerifyNameAndConnections(layer, name);
1627 VerifyDescriptor(descriptor);
1628 }
1629
1630 private:
1631 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1632 {
1633 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
1634 }
1635
1636 armnn::PadDescriptor m_Descriptor;
1637 };
1638
1639 const std::string layerName("pad");
1640 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1641 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1642
1643 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1644
1645 armnn::INetworkPtr network = armnn::INetwork::Create();
1646 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1647 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1648 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1649
1650 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1651 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1652
1653 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1654 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1655
1656 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1657 BOOST_CHECK(deserializedNetwork);
1658
1659 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1660 deserializedNetwork->Accept(verifier);
1661}
1662
1663BOOST_AUTO_TEST_CASE(SerializePermute)
1664{
1665 class PermuteLayerVerifier : public LayerVerifierBase
1666 {
1667 public:
1668 PermuteLayerVerifier(const std::string& layerName,
1669 const std::vector<armnn::TensorInfo>& inputInfos,
1670 const std::vector<armnn::TensorInfo>& outputInfos,
1671 const armnn::PermuteDescriptor& descriptor)
1672 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1673 , m_Descriptor(descriptor) {}
1674
1675 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1676 const armnn::PermuteDescriptor& descriptor,
1677 const char* name) override
1678 {
1679 VerifyNameAndConnections(layer, name);
1680 VerifyDescriptor(descriptor);
1681 }
1682
1683 private:
1684 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1685 {
1686 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1687 }
1688
1689 armnn::PermuteDescriptor m_Descriptor;
1690 };
1691
1692 const std::string layerName("permute");
1693 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1694 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1695
1696 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1697
1698 armnn::INetworkPtr network = armnn::INetwork::Create();
1699 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1700 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1701 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1702
1703 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1704 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1705
1706 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1707 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1708
1709 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1710 BOOST_CHECK(deserializedNetwork);
1711
1712 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1713 deserializedNetwork->Accept(verifier);
1714}
1715
1716BOOST_AUTO_TEST_CASE(SerializePooling2d)
1717{
1718 class Pooling2dLayerVerifier : public LayerVerifierBase
1719 {
1720 public:
1721 Pooling2dLayerVerifier(const std::string& layerName,
1722 const std::vector<armnn::TensorInfo>& inputInfos,
1723 const std::vector<armnn::TensorInfo>& outputInfos,
1724 const armnn::Pooling2dDescriptor& descriptor)
1725 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1726 , m_Descriptor(descriptor) {}
1727
1728 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
1729 const armnn::Pooling2dDescriptor& descriptor,
1730 const char* name) override
1731 {
1732 VerifyNameAndConnections(layer, name);
1733 VerifyDescriptor(descriptor);
1734 }
1735
1736 private:
1737 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
1738 {
1739 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1740 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
1741 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
1742 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
1743 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
1744 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
1745 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
1746 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
1747 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
1748
1749 BOOST_TEST(
1750 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
1751 BOOST_TEST(
1752 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
1753 BOOST_TEST(
1754 static_cast<int>(descriptor.m_OutputShapeRounding) ==
1755 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
1756 }
1757
1758 armnn::Pooling2dDescriptor m_Descriptor;
1759 };
1760
1761 const std::string layerName("pooling2d");
1762 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1763 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1764
1765 armnn::Pooling2dDescriptor desc;
1766 desc.m_DataLayout = armnn::DataLayout::NHWC;
1767 desc.m_PadTop = 0;
1768 desc.m_PadBottom = 0;
1769 desc.m_PadLeft = 0;
1770 desc.m_PadRight = 0;
1771 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1772 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1773 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1774 desc.m_PoolHeight = 2;
1775 desc.m_PoolWidth = 2;
1776 desc.m_StrideX = 2;
1777 desc.m_StrideY = 2;
1778
1779 armnn::INetworkPtr network = armnn::INetwork::Create();
1780 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1781 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1782 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1783
1784 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1785 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1786
1787 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1788 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1789
1790 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1791 BOOST_CHECK(deserializedNetwork);
1792
1793 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1794 deserializedNetwork->Accept(verifier);
1795}
1796
Derek Lamberti87acb272019-03-27 16:51:31 +00001797BOOST_AUTO_TEST_CASE(SerializeQuantize)
1798{
1799 class QuantizeLayerVerifier : public LayerVerifierBase
1800 {
1801 public:
1802 QuantizeLayerVerifier(const std::string& layerName,
1803 const std::vector<armnn::TensorInfo>& inputInfos,
1804 const std::vector<armnn::TensorInfo>& outputInfos)
1805 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1806
1807 void VisitQuantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1808 {
1809 VerifyNameAndConnections(layer, name);
1810 }
1811 };
1812
1813 const std::string layerName("quantize");
1814 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1815
1816 armnn::INetworkPtr network = armnn::INetwork::Create();
1817 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1818 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1819 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1820
1821 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1822 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1823
1824 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1825 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1826
1827 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1828 BOOST_CHECK(deserializedNetwork);
1829
1830 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1831 deserializedNetwork->Accept(verifier);
1832}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001833BOOST_AUTO_TEST_CASE(SerializeReshape)
1834{
1835 class ReshapeLayerVerifier : public LayerVerifierBase
1836 {
1837 public:
1838 ReshapeLayerVerifier(const std::string& layerName,
1839 const std::vector<armnn::TensorInfo>& inputInfos,
1840 const std::vector<armnn::TensorInfo>& outputInfos,
1841 const armnn::ReshapeDescriptor& descriptor)
1842 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1843 , m_Descriptor(descriptor) {}
1844
1845 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
1846 const armnn::ReshapeDescriptor& descriptor,
1847 const char* name) override
1848 {
1849 VerifyNameAndConnections(layer, name);
1850 VerifyDescriptor(descriptor);
1851 }
1852
1853 private:
1854 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
1855 {
1856 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
1857 }
1858
1859 armnn::ReshapeDescriptor m_Descriptor;
1860 };
1861
1862 const std::string layerName("reshape");
1863 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
1864 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
1865
1866 armnn::ReshapeDescriptor descriptor({3, 3});
1867
1868 armnn::INetworkPtr network = armnn::INetwork::Create();
1869 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1870 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
1871 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1872
1873 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
1874 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1875
1876 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1877 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1878
1879 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1880 BOOST_CHECK(deserializedNetwork);
1881
1882 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1883 deserializedNetwork->Accept(verifier);
1884}
1885
1886BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
1887{
1888 class ResizeBilinearLayerVerifier : public LayerVerifierBase
1889 {
1890 public:
1891 ResizeBilinearLayerVerifier(const std::string& layerName,
1892 const std::vector<armnn::TensorInfo>& inputInfos,
1893 const std::vector<armnn::TensorInfo>& outputInfos,
1894 const armnn::ResizeBilinearDescriptor& descriptor)
1895 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1896 , m_Descriptor(descriptor) {}
1897
1898 void VisitResizeBilinearLayer(const armnn::IConnectableLayer* layer,
1899 const armnn::ResizeBilinearDescriptor& descriptor,
1900 const char* name) override
1901 {
1902 VerifyNameAndConnections(layer, name);
1903 VerifyDescriptor(descriptor);
1904 }
1905
1906 private:
1907 void VerifyDescriptor(const armnn::ResizeBilinearDescriptor& descriptor)
1908 {
1909 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1910 BOOST_TEST(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
1911 BOOST_TEST(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
1912 }
1913
1914 armnn::ResizeBilinearDescriptor m_Descriptor;
1915 };
1916
1917 const std::string layerName("resizeBilinear");
1918 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
1919 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
1920
1921 armnn::ResizeBilinearDescriptor desc;
1922 desc.m_TargetWidth = 4;
1923 desc.m_TargetHeight = 2;
1924
1925 armnn::INetworkPtr network = armnn::INetwork::Create();
1926 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1927 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
1928 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1929
1930 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
1931 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1932
1933 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1934 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1935
1936 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1937 BOOST_CHECK(deserializedNetwork);
1938
1939 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1940 deserializedNetwork->Accept(verifier);
1941}
1942
1943BOOST_AUTO_TEST_CASE(SerializeRsqrt)
1944{
1945 class RsqrtLayerVerifier : public LayerVerifierBase
1946 {
1947 public:
1948 RsqrtLayerVerifier(const std::string& layerName,
1949 const std::vector<armnn::TensorInfo>& inputInfos,
1950 const std::vector<armnn::TensorInfo>& outputInfos)
1951 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1952
1953 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
1954 {
1955 VerifyNameAndConnections(layer, name);
1956 }
1957 };
1958
1959 const std::string layerName("rsqrt");
1960 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
1961
1962 armnn::INetworkPtr network = armnn::INetwork::Create();
1963 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1964 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
1965 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1966
1967 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
1968 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1969
1970 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1971 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1972
1973 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1974 BOOST_CHECK(deserializedNetwork);
1975
1976 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
1977 deserializedNetwork->Accept(verifier);
1978}
1979
1980BOOST_AUTO_TEST_CASE(SerializeSoftmax)
1981{
1982 class SoftmaxLayerVerifier : public LayerVerifierBase
1983 {
1984 public:
1985 SoftmaxLayerVerifier(const std::string& layerName,
1986 const std::vector<armnn::TensorInfo>& inputInfos,
1987 const std::vector<armnn::TensorInfo>& outputInfos,
1988 const armnn::SoftmaxDescriptor& descriptor)
1989 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1990 , m_Descriptor(descriptor) {}
1991
1992 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
1993 const armnn::SoftmaxDescriptor& descriptor,
1994 const char* name) override
1995 {
1996 VerifyNameAndConnections(layer, name);
1997 VerifyDescriptor(descriptor);
1998 }
1999
2000 private:
2001 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
2002 {
2003 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
2004 }
2005
2006 armnn::SoftmaxDescriptor m_Descriptor;
2007 };
2008
2009 const std::string layerName("softmax");
2010 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2011
2012 armnn::SoftmaxDescriptor descriptor;
2013 descriptor.m_Beta = 1.0f;
2014
2015 armnn::INetworkPtr network = armnn::INetwork::Create();
2016 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2017 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2018 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2019
2020 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2021 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2022
2023 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2024 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2025
2026 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2027 BOOST_CHECK(deserializedNetwork);
2028
2029 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2030 deserializedNetwork->Accept(verifier);
2031}
2032
2033BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2034{
2035 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
2036 {
2037 public:
2038 SpaceToBatchNdLayerVerifier(const std::string& layerName,
2039 const std::vector<armnn::TensorInfo>& inputInfos,
2040 const std::vector<armnn::TensorInfo>& outputInfos,
2041 const armnn::SpaceToBatchNdDescriptor& descriptor)
2042 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2043 , m_Descriptor(descriptor) {}
2044
2045 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
2046 const armnn::SpaceToBatchNdDescriptor& descriptor,
2047 const char* name) override
2048 {
2049 VerifyNameAndConnections(layer, name);
2050 VerifyDescriptor(descriptor);
2051 }
2052
2053 private:
2054 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
2055 {
2056 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
2057 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
2058 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2059 }
2060
2061 armnn::SpaceToBatchNdDescriptor m_Descriptor;
2062 };
2063
2064 const std::string layerName("spaceToBatchNd");
2065 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2066 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2067
2068 armnn::SpaceToBatchNdDescriptor desc;
2069 desc.m_DataLayout = armnn::DataLayout::NCHW;
2070 desc.m_BlockShape = {2, 2};
2071 desc.m_PadList = {{0, 0}, {2, 0}};
2072
2073 armnn::INetworkPtr network = armnn::INetwork::Create();
2074 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2075 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2076 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2077
2078 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2079 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2080
2081 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2082 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2083
2084 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2085 BOOST_CHECK(deserializedNetwork);
2086
2087 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2088 deserializedNetwork->Accept(verifier);
2089}
2090
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002091BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2092{
2093 class SpaceToDepthLayerVerifier : public LayerVerifierBase
2094 {
2095 public:
2096 SpaceToDepthLayerVerifier(const std::string& layerName,
2097 const std::vector<armnn::TensorInfo>& inputInfos,
2098 const std::vector<armnn::TensorInfo>& outputInfos,
2099 const armnn::SpaceToDepthDescriptor& descriptor)
2100 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2101 , m_Descriptor(descriptor) {}
2102
2103 void VisitSpaceToDepthLayer(const armnn::IConnectableLayer* layer,
2104 const armnn::SpaceToDepthDescriptor& descriptor,
2105 const char* name) override
2106 {
2107 VerifyNameAndConnections(layer, name);
2108 VerifyDescriptor(descriptor);
2109 }
2110
2111 private:
2112 void VerifyDescriptor(const armnn::SpaceToDepthDescriptor& descriptor)
2113 {
2114 BOOST_TEST(descriptor.m_BlockSize == m_Descriptor.m_BlockSize);
2115 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2116 }
2117
2118 armnn::SpaceToDepthDescriptor m_Descriptor;
2119 };
2120
2121 const std::string layerName("spaceToDepth");
2122
2123 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2124 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2125
2126 armnn::SpaceToDepthDescriptor desc;
2127 desc.m_BlockSize = 2;
2128 desc.m_DataLayout = armnn::DataLayout::NHWC;
2129
2130 armnn::INetworkPtr network = armnn::INetwork::Create();
2131 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2132 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2133 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2134
2135 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2136 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2137
2138 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2139 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2140
2141 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2142 BOOST_CHECK(deserializedNetwork);
2143
2144 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2145 deserializedNetwork->Accept(verifier);
2146}
2147
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002148BOOST_AUTO_TEST_CASE(SerializeSplitter)
2149{
2150 class SplitterLayerVerifier : public LayerVerifierBase
2151 {
2152 public:
2153 SplitterLayerVerifier(const std::string& layerName,
2154 const std::vector<armnn::TensorInfo>& inputInfos,
2155 const std::vector<armnn::TensorInfo>& outputInfos,
2156 const armnn::ViewsDescriptor& descriptor)
2157 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2158 , m_Descriptor(descriptor) {}
2159
2160 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
2161 const armnn::ViewsDescriptor& descriptor,
2162 const char* name) override
2163 {
2164 VerifyNameAndConnections(layer, name);
2165 VerifyDescriptor(descriptor);
2166 }
2167
2168 private:
2169 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
2170 {
2171 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
2172 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
2173
2174 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
2175 {
2176 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
2177 {
2178 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
2179 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
2180 }
2181 }
2182 }
2183
2184 armnn::ViewsDescriptor m_Descriptor;
2185 };
2186
2187 const unsigned int numViews = 3;
2188 const unsigned int numDimensions = 4;
2189 const unsigned int inputShape[] = {1, 18, 4, 4};
2190 const unsigned int outputShape[] = {1, 6, 4, 4};
2191
2192 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2193 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2194 static_cast<unsigned int>(inputShape[1]),
2195 static_cast<unsigned int>(inputShape[2]),
2196 static_cast<unsigned int>(inputShape[3])};
2197 splitterDimSizes[1] /= numViews;
2198 armnn::ViewsDescriptor desc(numViews, numDimensions);
2199
2200 for (unsigned int g = 0; g < numViews; ++g)
2201 {
2202 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2203
2204 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2205 {
2206 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2207 }
2208 }
2209
2210 const std::string layerName("splitter");
2211 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2212 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2213
2214 armnn::INetworkPtr network = armnn::INetwork::Create();
2215 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2216 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2217 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2218 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2219 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2220
2221 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2222 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2223 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2224 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2225
2226 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2227 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2228 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2229 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2230
2231 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2232 BOOST_CHECK(deserializedNetwork);
2233
2234 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2235 deserializedNetwork->Accept(verifier);
2236}
2237
2238BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2239{
2240 class StridedSliceLayerVerifier : public LayerVerifierBase
2241 {
2242 public:
2243 StridedSliceLayerVerifier(const std::string& layerName,
2244 const std::vector<armnn::TensorInfo>& inputInfos,
2245 const std::vector<armnn::TensorInfo>& outputInfos,
2246 const armnn::StridedSliceDescriptor& descriptor)
2247 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2248 , m_Descriptor(descriptor) {}
2249
2250 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
2251 const armnn::StridedSliceDescriptor& descriptor,
2252 const char* name) override
2253 {
2254 VerifyNameAndConnections(layer, name);
2255 VerifyDescriptor(descriptor);
2256 }
2257
2258 private:
2259 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
2260 {
2261 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
2262 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
2263 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
2264 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2265 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2266 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2267 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2268 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2269 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2270 }
2271 armnn::StridedSliceDescriptor m_Descriptor;
2272 };
2273
2274 const std::string layerName("stridedSlice");
2275 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2276 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2277
2278 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2279 desc.m_EndMask = (1 << 4) - 1;
2280 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2281 desc.m_DataLayout = armnn::DataLayout::NCHW;
2282
2283 armnn::INetworkPtr network = armnn::INetwork::Create();
2284 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2285 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2286 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2287
2288 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2289 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2290
2291 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2292 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2293
2294 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2295 BOOST_CHECK(deserializedNetwork);
2296
2297 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2298 deserializedNetwork->Accept(verifier);
2299}
2300
2301BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2302{
2303 class SubtractionLayerVerifier : public LayerVerifierBase
2304 {
2305 public:
2306 SubtractionLayerVerifier(const std::string& layerName,
2307 const std::vector<armnn::TensorInfo>& inputInfos,
2308 const std::vector<armnn::TensorInfo>& outputInfos)
2309 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2310
2311 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2312 {
2313 VerifyNameAndConnections(layer, name);
2314 }
2315 };
2316
2317 const std::string layerName("subtraction");
2318 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2319
2320 armnn::INetworkPtr network = armnn::INetwork::Create();
2321 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2322 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2323 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2324 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2325
2326 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2327 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2328 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2329
2330 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2331 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2332 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2333
2334 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2335 BOOST_CHECK(deserializedNetwork);
2336
2337 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2338 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002339}
2340
Sadik Armaganeff363d2019-04-05 15:25:46 +01002341BOOST_AUTO_TEST_CASE(SerializeSwitch)
2342{
2343 class SwitchLayerVerifier : public LayerVerifierBase
2344 {
2345 public:
2346 SwitchLayerVerifier(const std::string& layerName,
2347 const std::vector<armnn::TensorInfo>& inputInfos,
2348 const std::vector<armnn::TensorInfo>& outputInfos)
2349 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2350
2351 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2352 {
2353 VerifyNameAndConnections(layer, name);
2354 }
2355
2356 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2357 const armnn::ConstTensor& input,
2358 const char *name) override {}
2359 };
2360
2361 const std::string layerName("switch");
2362 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2363
2364 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2365 armnn::ConstTensor constTensor(info, constantData);
2366
2367 armnn::INetworkPtr network = armnn::INetwork::Create();
2368 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2369 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2370 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2371 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2372 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2373
2374 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2375 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2376 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2377 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2378
2379 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2380 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2381 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2382 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2383
2384 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2385 BOOST_CHECK(deserializedNetwork);
2386
2387 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2388 deserializedNetwork->Accept(verifier);
2389}
2390
Sadik Armagandb059fd2019-03-20 12:28:32 +00002391BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2392{
2393 class ConstantLayerVerifier : public LayerVerifierBase
2394 {
2395 public:
2396 ConstantLayerVerifier(const std::string& layerName,
2397 const std::vector<armnn::TensorInfo>& inputInfos,
2398 const std::vector<armnn::TensorInfo>& outputInfos,
2399 const armnn::ConstTensor& layerInput)
2400 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2401 , m_LayerInput(layerInput) {}
2402
2403 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2404 const armnn::ConstTensor& input,
2405 const char* name) override
2406 {
2407 VerifyNameAndConnections(layer, name);
2408
2409 CompareConstTensor(input, m_LayerInput);
2410 }
2411
2412 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2413
2414 private:
2415 armnn::ConstTensor m_LayerInput;
2416 };
2417
2418 const std::string layerName("constant");
2419 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2420
2421 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2422 armnn::ConstTensor constTensor(info, constantData);
2423
2424 armnn::INetworkPtr network(armnn::INetwork::Create());
2425 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2426 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2427 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2428 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2429
2430 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2431 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2432 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2433
2434 input->GetOutputSlot(0).SetTensorInfo(info);
2435 constant->GetOutputSlot(0).SetTensorInfo(info);
2436 add->GetOutputSlot(0).SetTensorInfo(info);
2437
2438 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2439 BOOST_CHECK(deserializedNetwork);
2440
2441 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2442 deserializedNetwork->Accept(verifier);
2443}
2444
Jim Flynn11af3752019-03-19 17:22:29 +00002445class VerifyLstmLayer : public LayerVerifierBase
2446{
2447public:
2448 VerifyLstmLayer(const std::string& layerName,
2449 const std::vector<armnn::TensorInfo>& inputInfos,
2450 const std::vector<armnn::TensorInfo>& outputInfos,
2451 const armnn::LstmDescriptor& descriptor,
2452 const armnn::LstmInputParams& inputParams) :
2453 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2454 {
2455 }
2456 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2457 const armnn::LstmDescriptor& descriptor,
2458 const armnn::LstmInputParams& params,
2459 const char* name)
2460 {
2461 VerifyNameAndConnections(layer, name);
2462 VerifyDescriptor(descriptor);
2463 VerifyInputParameters(params);
2464 }
2465protected:
2466 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2467 {
2468 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2469 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2470 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2471 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2472 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2473 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
2474 }
2475 void VerifyInputParameters(const armnn::LstmInputParams& params)
2476 {
2477 VerifyConstTensors(
2478 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2479 VerifyConstTensors(
2480 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2481 VerifyConstTensors(
2482 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2483 VerifyConstTensors(
2484 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2485 VerifyConstTensors(
2486 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2487 VerifyConstTensors(
2488 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2489 VerifyConstTensors(
2490 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2491 VerifyConstTensors(
2492 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2493 VerifyConstTensors(
2494 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2495 VerifyConstTensors(
2496 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2497 VerifyConstTensors(
2498 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2499 VerifyConstTensors(
2500 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2501 VerifyConstTensors(
2502 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2503 VerifyConstTensors(
2504 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2505 VerifyConstTensors(
2506 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2507 VerifyConstTensors(
2508 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2509 VerifyConstTensors(
2510 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
2511 }
2512 void VerifyConstTensors(const std::string& tensorName,
2513 const armnn::ConstTensor* expectedPtr,
2514 const armnn::ConstTensor* actualPtr)
2515 {
2516 if (expectedPtr == nullptr)
2517 {
2518 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
2519 }
2520 else
2521 {
2522 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
2523 if (actualPtr != nullptr)
2524 {
2525 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
2526 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
2527
2528 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
2529 tensorName + " shapes don't match");
2530 BOOST_CHECK_MESSAGE(
2531 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
2532 tensorName + " data types don't match");
2533
2534 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
2535 tensorName + " (GetNumBytes) data sizes do not match");
2536 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
2537 {
2538 //check the data is identical
2539 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
2540 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
2541 bool same = true;
2542 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
2543 {
2544 same = expectedData[i] == actualData[i];
2545 if (!same)
2546 {
2547 break;
2548 }
2549 }
2550 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
2551 }
2552 }
2553 }
2554 }
2555private:
2556 armnn::LstmDescriptor m_Descriptor;
2557 armnn::LstmInputParams m_InputParams;
2558};
2559
2560BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2561{
2562 armnn::LstmDescriptor descriptor;
2563 descriptor.m_ActivationFunc = 4;
2564 descriptor.m_ClippingThresProj = 0.0f;
2565 descriptor.m_ClippingThresCell = 0.0f;
2566 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2567 descriptor.m_ProjectionEnabled = false;
2568 descriptor.m_PeepholeEnabled = true;
2569
2570 const uint32_t batchSize = 1;
2571 const uint32_t inputSize = 2;
2572 const uint32_t numUnits = 4;
2573 const uint32_t outputSize = numUnits;
2574
2575 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2576 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2577 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2578
2579 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2580 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2581
2582 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2583 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2584
2585 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2586 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2587 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2588
2589 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2590 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2591
2592 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2593 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2594
2595 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2596 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2597 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2598
2599 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2600 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2601
2602 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2603 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2604
2605 std::vector<float> cellBiasData(numUnits, 0.0f);
2606 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2607
2608 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2609 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2610
2611 armnn::LstmInputParams params;
2612 params.m_InputToForgetWeights = &inputToForgetWeights;
2613 params.m_InputToCellWeights = &inputToCellWeights;
2614 params.m_InputToOutputWeights = &inputToOutputWeights;
2615 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2616 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2617 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2618 params.m_ForgetGateBias = &forgetGateBias;
2619 params.m_CellBias = &cellBias;
2620 params.m_OutputGateBias = &outputGateBias;
2621 params.m_CellToForgetWeights = &cellToForgetWeights;
2622 params.m_CellToOutputWeights = &cellToOutputWeights;
2623
2624 armnn::INetworkPtr network = armnn::INetwork::Create();
2625 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2626 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2627 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2628 const std::string layerName("lstm");
2629 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2630 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2631 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2632 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2633 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2634
2635 // connect up
2636 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2637 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2638 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2639 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2640
2641 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2642 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2643
2644 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2645 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2646
2647 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2648 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2649
2650 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2651 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2652
2653 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2654 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2655
2656 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2657 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2658
2659 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2660 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2661
2662 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2663 BOOST_CHECK(deserializedNetwork);
2664
2665 VerifyLstmLayer checker(
2666 layerName,
2667 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2668 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2669 descriptor,
2670 params);
2671 deserializedNetwork->Accept(checker);
2672}
2673
2674BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2675{
2676 armnn::LstmDescriptor descriptor;
2677 descriptor.m_ActivationFunc = 4;
2678 descriptor.m_ClippingThresProj = 0.0f;
2679 descriptor.m_ClippingThresCell = 0.0f;
2680 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2681 descriptor.m_ProjectionEnabled = true;
2682 descriptor.m_PeepholeEnabled = true;
2683
2684 const uint32_t batchSize = 2;
2685 const uint32_t inputSize = 5;
2686 const uint32_t numUnits = 20;
2687 const uint32_t outputSize = 16;
2688
2689 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2690 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2691 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2692
2693 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2694 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2695
2696 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2697 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2698
2699 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2700 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2701
2702 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2703 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2704 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2705
2706 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2707 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2708
2709 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2710 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2711
2712 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2713 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2714
2715 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2716 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2717 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2718
2719 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2720 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2721
2722 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2723 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2724
2725 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2726 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2727
2728 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2729 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2730
2731 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2732 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2733
2734 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2735 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2736
2737 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2738 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2739 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2740
2741 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2742 std::vector<float> projectionBiasData(outputSize, 0.f);
2743 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2744
2745 armnn::LstmInputParams params;
2746 params.m_InputToForgetWeights = &inputToForgetWeights;
2747 params.m_InputToCellWeights = &inputToCellWeights;
2748 params.m_InputToOutputWeights = &inputToOutputWeights;
2749 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2750 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2751 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2752 params.m_ForgetGateBias = &forgetGateBias;
2753 params.m_CellBias = &cellBias;
2754 params.m_OutputGateBias = &outputGateBias;
2755
2756 // additional params because: descriptor.m_CifgEnabled = false
2757 params.m_InputToInputWeights = &inputToInputWeights;
2758 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2759 params.m_CellToInputWeights = &cellToInputWeights;
2760 params.m_InputGateBias = &inputGateBias;
2761
2762 // additional params because: descriptor.m_ProjectionEnabled = true
2763 params.m_ProjectionWeights = &projectionWeights;
2764 params.m_ProjectionBias = &projectionBias;
2765
2766 // additional params because: descriptor.m_PeepholeEnabled = true
2767 params.m_CellToForgetWeights = &cellToForgetWeights;
2768 params.m_CellToOutputWeights = &cellToOutputWeights;
2769
2770 armnn::INetworkPtr network = armnn::INetwork::Create();
2771 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2772 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2773 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2774 const std::string layerName("lstm");
2775 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2776 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2777 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2778 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2779 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2780
2781 // connect up
2782 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2783 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2784 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2785 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2786
2787 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2788 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2789
2790 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2791 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2792
2793 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2794 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2795
2796 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2797 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2798
2799 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2800 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2801
2802 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2803 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2804
2805 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2806 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2807
2808 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2809 BOOST_CHECK(deserializedNetwork);
2810
2811 VerifyLstmLayer checker(
2812 layerName,
2813 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2814 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2815 descriptor,
2816 params);
2817 deserializedNetwork->Accept(checker);
2818}
2819
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002820BOOST_AUTO_TEST_SUITE_END()