blob: 0979076476bc7138f9b977bfb1fda7331cda8076 [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{
24 static void Apply()
25 {
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 =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000493 network->AddConvolution2dLayer(descriptor, weights, biases, layerName.c_str());
494 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000495
496 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000497 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000498
499 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000500 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
501
502 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
503 BOOST_CHECK(deserializedNetwork);
504
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000505 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
506 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000507}
508
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000509BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000510{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000511 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000512 {
513 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000514 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
515 const std::vector<armnn::TensorInfo>& inputInfos,
516 const std::vector<armnn::TensorInfo>& outputInfos,
517 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
518 const armnn::ConstTensor& weight,
519 const armnn::Optional<armnn::ConstTensor>& bias)
520 : LayerVerifierBase(layerName, inputInfos, outputInfos)
521 , m_Descriptor(descriptor)
522 , m_Weight(weight)
523 , m_Bias(bias) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000524
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000525 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
526 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
527 const armnn::ConstTensor& weight,
528 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000529 const char* name) override
530 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000531 VerifyNameAndConnections(layer, name);
532 VerifyDescriptor(descriptor);
533
534 CompareConstTensor(weight, m_Weight);
535
536 BOOST_TEST(bias.has_value() == m_Bias.has_value());
537 if (bias.has_value() && m_Bias.has_value())
538 {
539 CompareConstTensor(bias.value(), m_Bias.value());
540 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000541 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000542
543 private:
544 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
545 {
546 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
547 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
548 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
549 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
550 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
551 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
552 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
553 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
554 }
555
556 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
557 armnn::ConstTensor m_Weight;
558 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000559 };
560
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000561 const std::string layerName("depwiseConvolution2d");
562 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
563 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000564
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000565 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
566 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000567
568 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
569 armnn::ConstTensor weights(weightsInfo, weightsData);
570
571 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
572 armnn::ConstTensor biases(biasesInfo, biasesData);
573
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000574 armnn::DepthwiseConvolution2dDescriptor descriptor;
575 descriptor.m_StrideX = 1;
576 descriptor.m_StrideY = 1;
577 descriptor.m_BiasEnabled = true;
578 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
579
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000580 armnn::INetworkPtr network = armnn::INetwork::Create();
581 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
582 armnn::IConnectableLayer* const depthwiseConvLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000583 network->AddDepthwiseConvolution2dLayer(descriptor, weights, biases, layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000584 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
585
586 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000587 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000588
589 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000590 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
591
592 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
593 BOOST_CHECK(deserializedNetwork);
594
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000595 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
596 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000597}
598
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000599BOOST_AUTO_TEST_CASE(SerializeDequantize)
600{
601 class DequantizeLayerVerifier : public LayerVerifierBase
602 {
603 public:
604 DequantizeLayerVerifier(const std::string& layerName,
605 const std::vector<armnn::TensorInfo>& inputInfos,
606 const std::vector<armnn::TensorInfo>& outputInfos)
607 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
608
609 void VisitDequantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
610 {
611 VerifyNameAndConnections(layer, name);
612 }
613 };
614
615 const std::string layerName("dequantize");
616 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
617 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
618
619 armnn::INetworkPtr network = armnn::INetwork::Create();
620 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
621 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
622 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
623
624 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
625 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
626
627 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
628 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
629
630 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
631 BOOST_CHECK(deserializedNetwork);
632
633 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
634 deserializedNetwork->Accept(verifier);
635}
636
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000637BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
638{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000639 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000640 {
641 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000642 DetectionPostProcessLayerVerifier(const std::string& layerName,
643 const std::vector<armnn::TensorInfo>& inputInfos,
644 const std::vector<armnn::TensorInfo>& outputInfos,
645 const armnn::DetectionPostProcessDescriptor& descriptor,
646 const armnn::ConstTensor& anchors)
647 : LayerVerifierBase(layerName, inputInfos, outputInfos)
648 , m_Descriptor(descriptor)
649 , m_Anchors(anchors) {}
650
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000651 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
652 const armnn::DetectionPostProcessDescriptor& descriptor,
653 const armnn::ConstTensor& anchors,
654 const char* name) override
655 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000656 VerifyNameAndConnections(layer, name);
657 VerifyDescriptor(descriptor);
658
659 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000660 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000661
662 private:
663 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
664 {
665 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
666 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
667 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
668 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
669 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
670 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
671 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
672 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
673 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
674 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
675 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
676 }
677
678 armnn::DetectionPostProcessDescriptor m_Descriptor;
679 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000680 };
681
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000682 const std::string layerName("detectionPostProcess");
683
684 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000685 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
686 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000687 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000688
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000689 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000690 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
691 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
692 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
693 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000694 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000695
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000696 armnn::DetectionPostProcessDescriptor descriptor;
697 descriptor.m_UseRegularNms = true;
698 descriptor.m_MaxDetections = 3;
699 descriptor.m_MaxClassesPerDetection = 1;
700 descriptor.m_DetectionsPerClass =1;
701 descriptor.m_NmsScoreThreshold = 0.0;
702 descriptor.m_NmsIouThreshold = 0.5;
703 descriptor.m_NumClasses = 2;
704 descriptor.m_ScaleY = 10.0;
705 descriptor.m_ScaleX = 10.0;
706 descriptor.m_ScaleH = 5.0;
707 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000708
709 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
710 const std::vector<float> anchorsData({
711 0.5f, 0.5f, 1.0f, 1.0f,
712 0.5f, 0.5f, 1.0f, 1.0f,
713 0.5f, 0.5f, 1.0f, 1.0f,
714 0.5f, 10.5f, 1.0f, 1.0f,
715 0.5f, 10.5f, 1.0f, 1.0f,
716 0.5f, 100.5f, 1.0f, 1.0f
717 });
718 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
719
720 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000721 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000722 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000723
724 for (unsigned int i = 0; i < 2; i++)
725 {
726 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
727 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
728 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
729 }
730
731 for (unsigned int i = 0; i < 4; i++)
732 {
733 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
734 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
735 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
736 }
737
738 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
739 BOOST_CHECK(deserializedNetwork);
740
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000741 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
742 deserializedNetwork->Accept(verifier);
743}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000744
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000745BOOST_AUTO_TEST_CASE(SerializeDivision)
746{
747 class DivisionLayerVerifier : public LayerVerifierBase
748 {
749 public:
750 DivisionLayerVerifier(const std::string& layerName,
751 const std::vector<armnn::TensorInfo>& inputInfos,
752 const std::vector<armnn::TensorInfo>& outputInfos)
753 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
754
755 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
756 {
757 VerifyNameAndConnections(layer, name);
758 }
759 };
760
761 const std::string layerName("division");
762 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
763
764 armnn::INetworkPtr network = armnn::INetwork::Create();
765 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
766 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
767 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
768 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
769
770 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
771 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
772 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
773
774 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
775 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
776 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
777
778 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
779 BOOST_CHECK(deserializedNetwork);
780
781 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
782 deserializedNetwork->Accept(verifier);
783}
784
785BOOST_AUTO_TEST_CASE(SerializeEqual)
786{
787 class EqualLayerVerifier : public LayerVerifierBase
788 {
789 public:
790 EqualLayerVerifier(const std::string& layerName,
791 const std::vector<armnn::TensorInfo>& inputInfos,
792 const std::vector<armnn::TensorInfo>& outputInfos)
793 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
794
795 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
796 {
797 VerifyNameAndConnections(layer, name);
798 }
799 };
800
801 const std::string layerName("equal");
802 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
803 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
804 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
805
806 armnn::INetworkPtr network = armnn::INetwork::Create();
807 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
808 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
809 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
810 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
811
812 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
813 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
814 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
815
816 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
817 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
818 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
819
820 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
821 BOOST_CHECK(deserializedNetwork);
822
823 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
824 deserializedNetwork->Accept(verifier);
825}
826
827BOOST_AUTO_TEST_CASE(SerializeFloor)
828{
829 class FloorLayerVerifier : public LayerVerifierBase
830 {
831 public:
832 FloorLayerVerifier(const std::string& layerName,
833 const std::vector<armnn::TensorInfo>& inputInfos,
834 const std::vector<armnn::TensorInfo>& outputInfos)
835 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
836
837 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
838 {
839 VerifyNameAndConnections(layer, name);
840 }
841 };
842
843 const std::string layerName("floor");
844 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
845
846 armnn::INetworkPtr network = armnn::INetwork::Create();
847 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
848 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
849 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
850
851 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
852 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
853
854 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
855 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
856
857 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
858 BOOST_CHECK(deserializedNetwork);
859
860 FloorLayerVerifier verifier(layerName, {info}, {info});
861 deserializedNetwork->Accept(verifier);
862}
863
864BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
865{
866 class FullyConnectedLayerVerifier : public LayerVerifierBase
867 {
868 public:
869 FullyConnectedLayerVerifier(const std::string& layerName,
870 const std::vector<armnn::TensorInfo>& inputInfos,
871 const std::vector<armnn::TensorInfo>& outputInfos,
872 const armnn::FullyConnectedDescriptor& descriptor,
873 const armnn::ConstTensor& weight,
874 const armnn::Optional<armnn::ConstTensor>& bias)
875 : LayerVerifierBase(layerName, inputInfos, outputInfos)
876 , m_Descriptor(descriptor)
877 , m_Weight(weight)
878 , m_Bias(bias) {}
879
880 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
881 const armnn::FullyConnectedDescriptor& descriptor,
882 const armnn::ConstTensor& weight,
883 const armnn::Optional<armnn::ConstTensor>& bias,
884 const char* name) override
885 {
886 VerifyNameAndConnections(layer, name);
887 VerifyDescriptor(descriptor);
888
889 CompareConstTensor(weight, m_Weight);
890
891 BOOST_TEST(bias.has_value() == m_Bias.has_value());
892 if (bias.has_value() && m_Bias.has_value())
893 {
894 CompareConstTensor(bias.value(), m_Bias.value());
895 }
896 }
897
898 private:
899 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
900 {
901 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
902 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
903 }
904
905 armnn::FullyConnectedDescriptor m_Descriptor;
906 armnn::ConstTensor m_Weight;
907 armnn::Optional<armnn::ConstTensor> m_Bias;
908 };
909
910 const std::string layerName("fullyConnected");
911 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
912 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
913
914 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
915 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
916 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
917 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
918 armnn::ConstTensor weights(weightsInfo, weightsData);
919 armnn::ConstTensor biases(biasesInfo, biasesData);
920
921 armnn::FullyConnectedDescriptor descriptor;
922 descriptor.m_BiasEnabled = true;
923 descriptor.m_TransposeWeightMatrix = false;
924
925 armnn::INetworkPtr network = armnn::INetwork::Create();
926 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
927 armnn::IConnectableLayer* const fullyConnectedLayer =
928 network->AddFullyConnectedLayer(descriptor, weights, biases, layerName.c_str());
929 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
930
931 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
932 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
933
934 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
935 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
936
937 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
938 BOOST_CHECK(deserializedNetwork);
939
940 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
941 deserializedNetwork->Accept(verifier);
942}
943
944BOOST_AUTO_TEST_CASE(SerializeGather)
945{
946 class GatherLayerVerifier : public LayerVerifierBase
947 {
948 public:
949 GatherLayerVerifier(const std::string& layerName,
950 const std::vector<armnn::TensorInfo>& inputInfos,
951 const std::vector<armnn::TensorInfo>& outputInfos)
952 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
953
954 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
955 {
956 VerifyNameAndConnections(layer, name);
957 }
958
959 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
960 const armnn::ConstTensor& input,
961 const char *name) override {}
962 };
963
964 const std::string layerName("gather");
965 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
966 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
967 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
968
969 paramsInfo.SetQuantizationScale(1.0f);
970 paramsInfo.SetQuantizationOffset(0);
971 outputInfo.SetQuantizationScale(1.0f);
972 outputInfo.SetQuantizationOffset(0);
973
974 const std::vector<int32_t>& indicesData = {7, 6, 5};
975
976 armnn::INetworkPtr network = armnn::INetwork::Create();
977 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
978 armnn::IConnectableLayer *const constantLayer =
979 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
980 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
981 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
982
983 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
984 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
985 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
986
987 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
988 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
989 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
990
991 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
992 BOOST_CHECK(deserializedNetwork);
993
994 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
995 deserializedNetwork->Accept(verifier);
996}
997
998BOOST_AUTO_TEST_CASE(SerializeGreater)
999{
1000 class GreaterLayerVerifier : public LayerVerifierBase
1001 {
1002 public:
1003 GreaterLayerVerifier(const std::string& layerName,
1004 const std::vector<armnn::TensorInfo>& inputInfos,
1005 const std::vector<armnn::TensorInfo>& outputInfos)
1006 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1007
1008 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1009 {
1010 VerifyNameAndConnections(layer, name);
1011 }
1012 };
1013
1014 const std::string layerName("greater");
1015 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1016 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1017 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
1018
1019 armnn::INetworkPtr network = armnn::INetwork::Create();
1020 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
1021 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
1022 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
1023 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1024
1025 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
1026 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
1027 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1028
1029 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
1030 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
1031 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1032
1033 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1034 BOOST_CHECK(deserializedNetwork);
1035
1036 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
1037 deserializedNetwork->Accept(verifier);
1038}
1039
1040BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1041{
1042 class L2NormalizationLayerVerifier : public LayerVerifierBase
1043 {
1044 public:
1045 L2NormalizationLayerVerifier(const std::string& layerName,
1046 const std::vector<armnn::TensorInfo>& inputInfos,
1047 const std::vector<armnn::TensorInfo>& outputInfos,
1048 const armnn::L2NormalizationDescriptor& descriptor)
1049 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1050 , m_Descriptor(descriptor) {}
1051
1052 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1053 const armnn::L2NormalizationDescriptor& descriptor,
1054 const char* name) override
1055 {
1056 VerifyNameAndConnections(layer, name);
1057 VerifyDescriptor(descriptor);
1058 }
1059 private:
1060 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1061 {
1062 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1063 }
1064
1065 armnn::L2NormalizationDescriptor m_Descriptor;
1066 };
1067
1068 const std::string l2NormLayerName("l2Normalization");
1069 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1070
1071 armnn::L2NormalizationDescriptor desc;
1072 desc.m_DataLayout = armnn::DataLayout::NCHW;
1073
1074 armnn::INetworkPtr network = armnn::INetwork::Create();
1075 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1076 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1077 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1078
1079 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1080 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1081
1082 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1083 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1084
1085 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1086 BOOST_CHECK(deserializedNetwork);
1087
1088 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1089 deserializedNetwork->Accept(verifier);
1090}
1091
1092BOOST_AUTO_TEST_CASE(SerializeMaximum)
1093{
1094 class MaximumLayerVerifier : public LayerVerifierBase
1095 {
1096 public:
1097 MaximumLayerVerifier(const std::string& layerName,
1098 const std::vector<armnn::TensorInfo>& inputInfos,
1099 const std::vector<armnn::TensorInfo>& outputInfos)
1100 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1101
1102 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1103 {
1104 VerifyNameAndConnections(layer, name);
1105 }
1106 };
1107
1108 const std::string layerName("maximum");
1109 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1110
1111 armnn::INetworkPtr network = armnn::INetwork::Create();
1112 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1113 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1114 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1115 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1116
1117 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1118 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1119 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1120
1121 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1122 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1123 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1124
1125 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1126 BOOST_CHECK(deserializedNetwork);
1127
1128 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1129 deserializedNetwork->Accept(verifier);
1130}
1131
1132BOOST_AUTO_TEST_CASE(SerializeMean)
1133{
1134 class MeanLayerVerifier : public LayerVerifierBase
1135 {
1136 public:
1137 MeanLayerVerifier(const std::string& layerName,
1138 const std::vector<armnn::TensorInfo>& inputInfos,
1139 const std::vector<armnn::TensorInfo>& outputInfos,
1140 const armnn::MeanDescriptor& descriptor)
1141 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1142 , m_Descriptor(descriptor) {}
1143
1144 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1145 const armnn::MeanDescriptor& descriptor,
1146 const char* name) override
1147 {
1148 VerifyNameAndConnections(layer, name);
1149 VerifyDescriptor(descriptor);
1150 }
1151
1152 private:
1153 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1154 {
1155 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1156 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1157 }
1158
1159 armnn::MeanDescriptor m_Descriptor;
1160 };
1161
1162 const std::string layerName("mean");
1163 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1164 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1165
1166 armnn::MeanDescriptor descriptor;
1167 descriptor.m_Axis = { 2 };
1168 descriptor.m_KeepDims = true;
1169
1170 armnn::INetworkPtr network = armnn::INetwork::Create();
1171 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1172 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1173 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1174
1175 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1176 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1177
1178 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1179 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1180
1181 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1182 BOOST_CHECK(deserializedNetwork);
1183
1184 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1185 deserializedNetwork->Accept(verifier);
1186}
1187
1188BOOST_AUTO_TEST_CASE(SerializeMerger)
1189{
1190 class MergerLayerVerifier : public LayerVerifierBase
1191 {
1192 public:
1193 MergerLayerVerifier(const std::string& layerName,
1194 const std::vector<armnn::TensorInfo>& inputInfos,
1195 const std::vector<armnn::TensorInfo>& outputInfos,
1196 const armnn::OriginsDescriptor& descriptor)
1197 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1198 , m_Descriptor(descriptor) {}
1199
1200 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1201 const armnn::OriginsDescriptor& descriptor,
1202 const char* name) override
1203 {
1204 VerifyNameAndConnections(layer, name);
1205 VerifyDescriptor(descriptor);
1206 }
1207
1208 private:
1209 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1210 {
1211 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1212 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1213 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
1214
1215 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1216 {
1217 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
1218 {
1219 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
1220 }
1221 }
1222 }
1223
1224 armnn::OriginsDescriptor m_Descriptor;
1225 };
1226
1227 const std::string layerName("merger");
1228 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1229 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1230
1231 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1232
1233 armnn::OriginsDescriptor descriptor =
1234 armnn::CreateMergerDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1235
1236 armnn::INetworkPtr network = armnn::INetwork::Create();
1237 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1238 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1239 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
1240 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1241
1242 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1243 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1244 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1245
1246 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1247 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1248 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1249
1250 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1251 BOOST_CHECK(deserializedNetwork);
1252
1253 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1254 deserializedNetwork->Accept(verifier);
1255}
1256
1257BOOST_AUTO_TEST_CASE(SerializeMinimum)
1258{
1259 class MinimumLayerVerifier : public LayerVerifierBase
1260 {
1261 public:
1262 MinimumLayerVerifier(const std::string& layerName,
1263 const std::vector<armnn::TensorInfo>& inputInfos,
1264 const std::vector<armnn::TensorInfo>& outputInfos)
1265 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1266
1267 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1268 {
1269 VerifyNameAndConnections(layer, name);
1270 }
1271 };
1272
1273 const std::string layerName("minimum");
1274 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1275
1276 armnn::INetworkPtr network = armnn::INetwork::Create();
1277 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1278 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1279 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1280 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1281
1282 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1283 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1284 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1285
1286 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1287 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1288 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1289
1290 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1291 BOOST_CHECK(deserializedNetwork);
1292
1293 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1294 deserializedNetwork->Accept(verifier);
1295}
1296
1297BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1298{
1299 class MultiplicationLayerVerifier : public LayerVerifierBase
1300 {
1301 public:
1302 MultiplicationLayerVerifier(const std::string& layerName,
1303 const std::vector<armnn::TensorInfo>& inputInfos,
1304 const std::vector<armnn::TensorInfo>& outputInfos)
1305 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1306
1307 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1308 {
1309 VerifyNameAndConnections(layer, name);
1310 }
1311 };
1312
1313 const std::string layerName("multiplication");
1314 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1315
1316 armnn::INetworkPtr network = armnn::INetwork::Create();
1317 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1318 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1319 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1320 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1321
1322 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1323 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1324 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1325
1326 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1327 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1328 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1329
1330 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1331 BOOST_CHECK(deserializedNetwork);
1332
1333 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1334 deserializedNetwork->Accept(verifier);
1335}
1336
1337BOOST_AUTO_TEST_CASE(SerializeNormalization)
1338{
1339 class NormalizationLayerVerifier : public LayerVerifierBase
1340 {
1341 public:
1342 NormalizationLayerVerifier(const std::string& layerName,
1343 const std::vector<armnn::TensorInfo>& inputInfos,
1344 const std::vector<armnn::TensorInfo>& outputInfos,
1345 const armnn::NormalizationDescriptor& descriptor)
1346 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1347 , m_Descriptor(descriptor) {}
1348
1349 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1350 const armnn::NormalizationDescriptor& descriptor,
1351 const char* name) override
1352 {
1353 VerifyNameAndConnections(layer, name);
1354 VerifyDescriptor(descriptor);
1355 }
1356
1357 private:
1358 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1359 {
1360 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1361 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1362 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1363 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1364 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1365 BOOST_TEST(
1366 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1367 BOOST_TEST(
1368 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1369 }
1370
1371 armnn::NormalizationDescriptor m_Descriptor;
1372 };
1373
1374 const std::string layerName("normalization");
1375 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1376
1377 armnn::NormalizationDescriptor desc;
1378 desc.m_DataLayout = armnn::DataLayout::NCHW;
1379 desc.m_NormSize = 3;
1380 desc.m_Alpha = 1;
1381 desc.m_Beta = 1;
1382 desc.m_K = 1;
1383
1384 armnn::INetworkPtr network = armnn::INetwork::Create();
1385 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1386 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1387 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1388
1389 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1390 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1391
1392 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1393 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1394
1395 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1396 BOOST_CHECK(deserializedNetwork);
1397
1398 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1399 deserializedNetwork->Accept(verifier);
1400}
1401
1402BOOST_AUTO_TEST_CASE(SerializePad)
1403{
1404 class PadLayerVerifier : public LayerVerifierBase
1405 {
1406 public:
1407 PadLayerVerifier(const std::string& layerName,
1408 const std::vector<armnn::TensorInfo>& inputInfos,
1409 const std::vector<armnn::TensorInfo>& outputInfos,
1410 const armnn::PadDescriptor& descriptor)
1411 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1412 , m_Descriptor(descriptor) {}
1413
1414 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1415 const armnn::PadDescriptor& descriptor,
1416 const char* name) override
1417 {
1418 VerifyNameAndConnections(layer, name);
1419 VerifyDescriptor(descriptor);
1420 }
1421
1422 private:
1423 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1424 {
1425 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
1426 }
1427
1428 armnn::PadDescriptor m_Descriptor;
1429 };
1430
1431 const std::string layerName("pad");
1432 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1433 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1434
1435 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1436
1437 armnn::INetworkPtr network = armnn::INetwork::Create();
1438 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1439 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1440 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1441
1442 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1443 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1444
1445 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1446 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1447
1448 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1449 BOOST_CHECK(deserializedNetwork);
1450
1451 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1452 deserializedNetwork->Accept(verifier);
1453}
1454
1455BOOST_AUTO_TEST_CASE(SerializePermute)
1456{
1457 class PermuteLayerVerifier : public LayerVerifierBase
1458 {
1459 public:
1460 PermuteLayerVerifier(const std::string& layerName,
1461 const std::vector<armnn::TensorInfo>& inputInfos,
1462 const std::vector<armnn::TensorInfo>& outputInfos,
1463 const armnn::PermuteDescriptor& descriptor)
1464 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1465 , m_Descriptor(descriptor) {}
1466
1467 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1468 const armnn::PermuteDescriptor& descriptor,
1469 const char* name) override
1470 {
1471 VerifyNameAndConnections(layer, name);
1472 VerifyDescriptor(descriptor);
1473 }
1474
1475 private:
1476 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1477 {
1478 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1479 }
1480
1481 armnn::PermuteDescriptor m_Descriptor;
1482 };
1483
1484 const std::string layerName("permute");
1485 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1486 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1487
1488 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1489
1490 armnn::INetworkPtr network = armnn::INetwork::Create();
1491 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1492 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1493 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1494
1495 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1496 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1497
1498 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1499 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1500
1501 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1502 BOOST_CHECK(deserializedNetwork);
1503
1504 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1505 deserializedNetwork->Accept(verifier);
1506}
1507
1508BOOST_AUTO_TEST_CASE(SerializePooling2d)
1509{
1510 class Pooling2dLayerVerifier : public LayerVerifierBase
1511 {
1512 public:
1513 Pooling2dLayerVerifier(const std::string& layerName,
1514 const std::vector<armnn::TensorInfo>& inputInfos,
1515 const std::vector<armnn::TensorInfo>& outputInfos,
1516 const armnn::Pooling2dDescriptor& descriptor)
1517 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1518 , m_Descriptor(descriptor) {}
1519
1520 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
1521 const armnn::Pooling2dDescriptor& descriptor,
1522 const char* name) override
1523 {
1524 VerifyNameAndConnections(layer, name);
1525 VerifyDescriptor(descriptor);
1526 }
1527
1528 private:
1529 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
1530 {
1531 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1532 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
1533 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
1534 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
1535 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
1536 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
1537 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
1538 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
1539 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
1540
1541 BOOST_TEST(
1542 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
1543 BOOST_TEST(
1544 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
1545 BOOST_TEST(
1546 static_cast<int>(descriptor.m_OutputShapeRounding) ==
1547 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
1548 }
1549
1550 armnn::Pooling2dDescriptor m_Descriptor;
1551 };
1552
1553 const std::string layerName("pooling2d");
1554 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1555 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1556
1557 armnn::Pooling2dDescriptor desc;
1558 desc.m_DataLayout = armnn::DataLayout::NHWC;
1559 desc.m_PadTop = 0;
1560 desc.m_PadBottom = 0;
1561 desc.m_PadLeft = 0;
1562 desc.m_PadRight = 0;
1563 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1564 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1565 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1566 desc.m_PoolHeight = 2;
1567 desc.m_PoolWidth = 2;
1568 desc.m_StrideX = 2;
1569 desc.m_StrideY = 2;
1570
1571 armnn::INetworkPtr network = armnn::INetwork::Create();
1572 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1573 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1574 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1575
1576 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1577 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1578
1579 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1580 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1581
1582 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1583 BOOST_CHECK(deserializedNetwork);
1584
1585 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1586 deserializedNetwork->Accept(verifier);
1587}
1588
Derek Lamberti87acb272019-03-27 16:51:31 +00001589BOOST_AUTO_TEST_CASE(SerializeQuantize)
1590{
1591 class QuantizeLayerVerifier : public LayerVerifierBase
1592 {
1593 public:
1594 QuantizeLayerVerifier(const std::string& layerName,
1595 const std::vector<armnn::TensorInfo>& inputInfos,
1596 const std::vector<armnn::TensorInfo>& outputInfos)
1597 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1598
1599 void VisitQuantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1600 {
1601 VerifyNameAndConnections(layer, name);
1602 }
1603 };
1604
1605 const std::string layerName("quantize");
1606 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1607
1608 armnn::INetworkPtr network = armnn::INetwork::Create();
1609 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1610 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1611 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1612
1613 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1614 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1615
1616 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1617 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1618
1619 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1620 BOOST_CHECK(deserializedNetwork);
1621
1622 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1623 deserializedNetwork->Accept(verifier);
1624}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001625BOOST_AUTO_TEST_CASE(SerializeReshape)
1626{
1627 class ReshapeLayerVerifier : public LayerVerifierBase
1628 {
1629 public:
1630 ReshapeLayerVerifier(const std::string& layerName,
1631 const std::vector<armnn::TensorInfo>& inputInfos,
1632 const std::vector<armnn::TensorInfo>& outputInfos,
1633 const armnn::ReshapeDescriptor& descriptor)
1634 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1635 , m_Descriptor(descriptor) {}
1636
1637 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
1638 const armnn::ReshapeDescriptor& descriptor,
1639 const char* name) override
1640 {
1641 VerifyNameAndConnections(layer, name);
1642 VerifyDescriptor(descriptor);
1643 }
1644
1645 private:
1646 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
1647 {
1648 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
1649 }
1650
1651 armnn::ReshapeDescriptor m_Descriptor;
1652 };
1653
1654 const std::string layerName("reshape");
1655 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
1656 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
1657
1658 armnn::ReshapeDescriptor descriptor({3, 3});
1659
1660 armnn::INetworkPtr network = armnn::INetwork::Create();
1661 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1662 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
1663 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1664
1665 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
1666 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1667
1668 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1669 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1670
1671 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1672 BOOST_CHECK(deserializedNetwork);
1673
1674 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1675 deserializedNetwork->Accept(verifier);
1676}
1677
1678BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
1679{
1680 class ResizeBilinearLayerVerifier : public LayerVerifierBase
1681 {
1682 public:
1683 ResizeBilinearLayerVerifier(const std::string& layerName,
1684 const std::vector<armnn::TensorInfo>& inputInfos,
1685 const std::vector<armnn::TensorInfo>& outputInfos,
1686 const armnn::ResizeBilinearDescriptor& descriptor)
1687 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1688 , m_Descriptor(descriptor) {}
1689
1690 void VisitResizeBilinearLayer(const armnn::IConnectableLayer* layer,
1691 const armnn::ResizeBilinearDescriptor& descriptor,
1692 const char* name) override
1693 {
1694 VerifyNameAndConnections(layer, name);
1695 VerifyDescriptor(descriptor);
1696 }
1697
1698 private:
1699 void VerifyDescriptor(const armnn::ResizeBilinearDescriptor& descriptor)
1700 {
1701 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1702 BOOST_TEST(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
1703 BOOST_TEST(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
1704 }
1705
1706 armnn::ResizeBilinearDescriptor m_Descriptor;
1707 };
1708
1709 const std::string layerName("resizeBilinear");
1710 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
1711 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
1712
1713 armnn::ResizeBilinearDescriptor desc;
1714 desc.m_TargetWidth = 4;
1715 desc.m_TargetHeight = 2;
1716
1717 armnn::INetworkPtr network = armnn::INetwork::Create();
1718 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1719 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
1720 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1721
1722 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
1723 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1724
1725 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1726 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1727
1728 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1729 BOOST_CHECK(deserializedNetwork);
1730
1731 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1732 deserializedNetwork->Accept(verifier);
1733}
1734
1735BOOST_AUTO_TEST_CASE(SerializeRsqrt)
1736{
1737 class RsqrtLayerVerifier : public LayerVerifierBase
1738 {
1739 public:
1740 RsqrtLayerVerifier(const std::string& layerName,
1741 const std::vector<armnn::TensorInfo>& inputInfos,
1742 const std::vector<armnn::TensorInfo>& outputInfos)
1743 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1744
1745 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
1746 {
1747 VerifyNameAndConnections(layer, name);
1748 }
1749 };
1750
1751 const std::string layerName("rsqrt");
1752 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
1753
1754 armnn::INetworkPtr network = armnn::INetwork::Create();
1755 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1756 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
1757 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1758
1759 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
1760 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1761
1762 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1763 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1764
1765 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1766 BOOST_CHECK(deserializedNetwork);
1767
1768 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
1769 deserializedNetwork->Accept(verifier);
1770}
1771
1772BOOST_AUTO_TEST_CASE(SerializeSoftmax)
1773{
1774 class SoftmaxLayerVerifier : public LayerVerifierBase
1775 {
1776 public:
1777 SoftmaxLayerVerifier(const std::string& layerName,
1778 const std::vector<armnn::TensorInfo>& inputInfos,
1779 const std::vector<armnn::TensorInfo>& outputInfos,
1780 const armnn::SoftmaxDescriptor& descriptor)
1781 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1782 , m_Descriptor(descriptor) {}
1783
1784 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
1785 const armnn::SoftmaxDescriptor& descriptor,
1786 const char* name) override
1787 {
1788 VerifyNameAndConnections(layer, name);
1789 VerifyDescriptor(descriptor);
1790 }
1791
1792 private:
1793 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
1794 {
1795 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1796 }
1797
1798 armnn::SoftmaxDescriptor m_Descriptor;
1799 };
1800
1801 const std::string layerName("softmax");
1802 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1803
1804 armnn::SoftmaxDescriptor descriptor;
1805 descriptor.m_Beta = 1.0f;
1806
1807 armnn::INetworkPtr network = armnn::INetwork::Create();
1808 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1809 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
1810 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1811
1812 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
1813 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1814
1815 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1816 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1817
1818 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1819 BOOST_CHECK(deserializedNetwork);
1820
1821 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1822 deserializedNetwork->Accept(verifier);
1823}
1824
1825BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
1826{
1827 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
1828 {
1829 public:
1830 SpaceToBatchNdLayerVerifier(const std::string& layerName,
1831 const std::vector<armnn::TensorInfo>& inputInfos,
1832 const std::vector<armnn::TensorInfo>& outputInfos,
1833 const armnn::SpaceToBatchNdDescriptor& descriptor)
1834 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1835 , m_Descriptor(descriptor) {}
1836
1837 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
1838 const armnn::SpaceToBatchNdDescriptor& descriptor,
1839 const char* name) override
1840 {
1841 VerifyNameAndConnections(layer, name);
1842 VerifyDescriptor(descriptor);
1843 }
1844
1845 private:
1846 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
1847 {
1848 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
1849 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
1850 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1851 }
1852
1853 armnn::SpaceToBatchNdDescriptor m_Descriptor;
1854 };
1855
1856 const std::string layerName("spaceToBatchNd");
1857 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
1858 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
1859
1860 armnn::SpaceToBatchNdDescriptor desc;
1861 desc.m_DataLayout = armnn::DataLayout::NCHW;
1862 desc.m_BlockShape = {2, 2};
1863 desc.m_PadList = {{0, 0}, {2, 0}};
1864
1865 armnn::INetworkPtr network = armnn::INetwork::Create();
1866 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1867 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
1868 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1869
1870 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
1871 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1872
1873 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1874 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1875
1876 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1877 BOOST_CHECK(deserializedNetwork);
1878
1879 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1880 deserializedNetwork->Accept(verifier);
1881}
1882
1883BOOST_AUTO_TEST_CASE(SerializeSplitter)
1884{
1885 class SplitterLayerVerifier : public LayerVerifierBase
1886 {
1887 public:
1888 SplitterLayerVerifier(const std::string& layerName,
1889 const std::vector<armnn::TensorInfo>& inputInfos,
1890 const std::vector<armnn::TensorInfo>& outputInfos,
1891 const armnn::ViewsDescriptor& descriptor)
1892 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1893 , m_Descriptor(descriptor) {}
1894
1895 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
1896 const armnn::ViewsDescriptor& descriptor,
1897 const char* name) override
1898 {
1899 VerifyNameAndConnections(layer, name);
1900 VerifyDescriptor(descriptor);
1901 }
1902
1903 private:
1904 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
1905 {
1906 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1907 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
1908
1909 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1910 {
1911 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
1912 {
1913 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
1914 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
1915 }
1916 }
1917 }
1918
1919 armnn::ViewsDescriptor m_Descriptor;
1920 };
1921
1922 const unsigned int numViews = 3;
1923 const unsigned int numDimensions = 4;
1924 const unsigned int inputShape[] = {1, 18, 4, 4};
1925 const unsigned int outputShape[] = {1, 6, 4, 4};
1926
1927 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
1928 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
1929 static_cast<unsigned int>(inputShape[1]),
1930 static_cast<unsigned int>(inputShape[2]),
1931 static_cast<unsigned int>(inputShape[3])};
1932 splitterDimSizes[1] /= numViews;
1933 armnn::ViewsDescriptor desc(numViews, numDimensions);
1934
1935 for (unsigned int g = 0; g < numViews; ++g)
1936 {
1937 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
1938
1939 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
1940 {
1941 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
1942 }
1943 }
1944
1945 const std::string layerName("splitter");
1946 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
1947 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
1948
1949 armnn::INetworkPtr network = armnn::INetwork::Create();
1950 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1951 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
1952 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
1953 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
1954 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
1955
1956 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
1957 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
1958 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
1959 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
1960
1961 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1962 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1963 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
1964 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
1965
1966 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1967 BOOST_CHECK(deserializedNetwork);
1968
1969 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
1970 deserializedNetwork->Accept(verifier);
1971}
1972
1973BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
1974{
1975 class StridedSliceLayerVerifier : public LayerVerifierBase
1976 {
1977 public:
1978 StridedSliceLayerVerifier(const std::string& layerName,
1979 const std::vector<armnn::TensorInfo>& inputInfos,
1980 const std::vector<armnn::TensorInfo>& outputInfos,
1981 const armnn::StridedSliceDescriptor& descriptor)
1982 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1983 , m_Descriptor(descriptor) {}
1984
1985 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
1986 const armnn::StridedSliceDescriptor& descriptor,
1987 const char* name) override
1988 {
1989 VerifyNameAndConnections(layer, name);
1990 VerifyDescriptor(descriptor);
1991 }
1992
1993 private:
1994 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
1995 {
1996 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
1997 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
1998 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
1999 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2000 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2001 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2002 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2003 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2004 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2005 }
2006 armnn::StridedSliceDescriptor m_Descriptor;
2007 };
2008
2009 const std::string layerName("stridedSlice");
2010 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2011 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2012
2013 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2014 desc.m_EndMask = (1 << 4) - 1;
2015 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2016 desc.m_DataLayout = armnn::DataLayout::NCHW;
2017
2018 armnn::INetworkPtr network = armnn::INetwork::Create();
2019 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2020 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2021 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2022
2023 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2024 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2025
2026 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2027 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2028
2029 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2030 BOOST_CHECK(deserializedNetwork);
2031
2032 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2033 deserializedNetwork->Accept(verifier);
2034}
2035
2036BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2037{
2038 class SubtractionLayerVerifier : public LayerVerifierBase
2039 {
2040 public:
2041 SubtractionLayerVerifier(const std::string& layerName,
2042 const std::vector<armnn::TensorInfo>& inputInfos,
2043 const std::vector<armnn::TensorInfo>& outputInfos)
2044 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2045
2046 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2047 {
2048 VerifyNameAndConnections(layer, name);
2049 }
2050 };
2051
2052 const std::string layerName("subtraction");
2053 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2054
2055 armnn::INetworkPtr network = armnn::INetwork::Create();
2056 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2057 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2058 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2059 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2060
2061 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2062 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2063 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2064
2065 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2066 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2067 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2068
2069 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2070 BOOST_CHECK(deserializedNetwork);
2071
2072 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2073 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002074}
2075
Sadik Armagandb059fd2019-03-20 12:28:32 +00002076BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2077{
2078 class ConstantLayerVerifier : public LayerVerifierBase
2079 {
2080 public:
2081 ConstantLayerVerifier(const std::string& layerName,
2082 const std::vector<armnn::TensorInfo>& inputInfos,
2083 const std::vector<armnn::TensorInfo>& outputInfos,
2084 const armnn::ConstTensor& layerInput)
2085 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2086 , m_LayerInput(layerInput) {}
2087
2088 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2089 const armnn::ConstTensor& input,
2090 const char* name) override
2091 {
2092 VerifyNameAndConnections(layer, name);
2093
2094 CompareConstTensor(input, m_LayerInput);
2095 }
2096
2097 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2098
2099 private:
2100 armnn::ConstTensor m_LayerInput;
2101 };
2102
2103 const std::string layerName("constant");
2104 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2105
2106 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2107 armnn::ConstTensor constTensor(info, constantData);
2108
2109 armnn::INetworkPtr network(armnn::INetwork::Create());
2110 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2111 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2112 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2113 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2114
2115 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2116 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2117 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2118
2119 input->GetOutputSlot(0).SetTensorInfo(info);
2120 constant->GetOutputSlot(0).SetTensorInfo(info);
2121 add->GetOutputSlot(0).SetTensorInfo(info);
2122
2123 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2124 BOOST_CHECK(deserializedNetwork);
2125
2126 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2127 deserializedNetwork->Accept(verifier);
2128}
2129
Jim Flynn11af3752019-03-19 17:22:29 +00002130class VerifyLstmLayer : public LayerVerifierBase
2131{
2132public:
2133 VerifyLstmLayer(const std::string& layerName,
2134 const std::vector<armnn::TensorInfo>& inputInfos,
2135 const std::vector<armnn::TensorInfo>& outputInfos,
2136 const armnn::LstmDescriptor& descriptor,
2137 const armnn::LstmInputParams& inputParams) :
2138 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2139 {
2140 }
2141 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2142 const armnn::LstmDescriptor& descriptor,
2143 const armnn::LstmInputParams& params,
2144 const char* name)
2145 {
2146 VerifyNameAndConnections(layer, name);
2147 VerifyDescriptor(descriptor);
2148 VerifyInputParameters(params);
2149 }
2150protected:
2151 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2152 {
2153 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2154 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2155 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2156 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2157 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2158 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
2159 }
2160 void VerifyInputParameters(const armnn::LstmInputParams& params)
2161 {
2162 VerifyConstTensors(
2163 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2164 VerifyConstTensors(
2165 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2166 VerifyConstTensors(
2167 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2168 VerifyConstTensors(
2169 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2170 VerifyConstTensors(
2171 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2172 VerifyConstTensors(
2173 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2174 VerifyConstTensors(
2175 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2176 VerifyConstTensors(
2177 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2178 VerifyConstTensors(
2179 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2180 VerifyConstTensors(
2181 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2182 VerifyConstTensors(
2183 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2184 VerifyConstTensors(
2185 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2186 VerifyConstTensors(
2187 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2188 VerifyConstTensors(
2189 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2190 VerifyConstTensors(
2191 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2192 VerifyConstTensors(
2193 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2194 VerifyConstTensors(
2195 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
2196 }
2197 void VerifyConstTensors(const std::string& tensorName,
2198 const armnn::ConstTensor* expectedPtr,
2199 const armnn::ConstTensor* actualPtr)
2200 {
2201 if (expectedPtr == nullptr)
2202 {
2203 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
2204 }
2205 else
2206 {
2207 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
2208 if (actualPtr != nullptr)
2209 {
2210 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
2211 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
2212
2213 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
2214 tensorName + " shapes don't match");
2215 BOOST_CHECK_MESSAGE(
2216 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
2217 tensorName + " data types don't match");
2218
2219 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
2220 tensorName + " (GetNumBytes) data sizes do not match");
2221 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
2222 {
2223 //check the data is identical
2224 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
2225 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
2226 bool same = true;
2227 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
2228 {
2229 same = expectedData[i] == actualData[i];
2230 if (!same)
2231 {
2232 break;
2233 }
2234 }
2235 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
2236 }
2237 }
2238 }
2239 }
2240private:
2241 armnn::LstmDescriptor m_Descriptor;
2242 armnn::LstmInputParams m_InputParams;
2243};
2244
2245BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2246{
2247 armnn::LstmDescriptor descriptor;
2248 descriptor.m_ActivationFunc = 4;
2249 descriptor.m_ClippingThresProj = 0.0f;
2250 descriptor.m_ClippingThresCell = 0.0f;
2251 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2252 descriptor.m_ProjectionEnabled = false;
2253 descriptor.m_PeepholeEnabled = true;
2254
2255 const uint32_t batchSize = 1;
2256 const uint32_t inputSize = 2;
2257 const uint32_t numUnits = 4;
2258 const uint32_t outputSize = numUnits;
2259
2260 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2261 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2262 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2263
2264 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2265 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2266
2267 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2268 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2269
2270 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2271 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2272 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2273
2274 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2275 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2276
2277 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2278 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2279
2280 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2281 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2282 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2283
2284 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2285 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2286
2287 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2288 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2289
2290 std::vector<float> cellBiasData(numUnits, 0.0f);
2291 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2292
2293 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2294 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2295
2296 armnn::LstmInputParams params;
2297 params.m_InputToForgetWeights = &inputToForgetWeights;
2298 params.m_InputToCellWeights = &inputToCellWeights;
2299 params.m_InputToOutputWeights = &inputToOutputWeights;
2300 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2301 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2302 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2303 params.m_ForgetGateBias = &forgetGateBias;
2304 params.m_CellBias = &cellBias;
2305 params.m_OutputGateBias = &outputGateBias;
2306 params.m_CellToForgetWeights = &cellToForgetWeights;
2307 params.m_CellToOutputWeights = &cellToOutputWeights;
2308
2309 armnn::INetworkPtr network = armnn::INetwork::Create();
2310 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2311 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2312 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2313 const std::string layerName("lstm");
2314 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2315 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2316 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2317 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2318 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2319
2320 // connect up
2321 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2322 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2323 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2324 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2325
2326 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2327 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2328
2329 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2330 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2331
2332 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2333 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2334
2335 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2336 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2337
2338 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2339 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2340
2341 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2342 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2343
2344 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2345 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2346
2347 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2348 BOOST_CHECK(deserializedNetwork);
2349
2350 VerifyLstmLayer checker(
2351 layerName,
2352 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2353 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2354 descriptor,
2355 params);
2356 deserializedNetwork->Accept(checker);
2357}
2358
2359BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2360{
2361 armnn::LstmDescriptor descriptor;
2362 descriptor.m_ActivationFunc = 4;
2363 descriptor.m_ClippingThresProj = 0.0f;
2364 descriptor.m_ClippingThresCell = 0.0f;
2365 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2366 descriptor.m_ProjectionEnabled = true;
2367 descriptor.m_PeepholeEnabled = true;
2368
2369 const uint32_t batchSize = 2;
2370 const uint32_t inputSize = 5;
2371 const uint32_t numUnits = 20;
2372 const uint32_t outputSize = 16;
2373
2374 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2375 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2376 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2377
2378 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2379 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2380
2381 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2382 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2383
2384 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2385 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2386
2387 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2388 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2389 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2390
2391 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2392 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2393
2394 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2395 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2396
2397 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2398 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2399
2400 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2401 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2402 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2403
2404 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2405 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2406
2407 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2408 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2409
2410 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2411 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2412
2413 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2414 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2415
2416 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2417 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2418
2419 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2420 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2421
2422 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2423 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2424 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2425
2426 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2427 std::vector<float> projectionBiasData(outputSize, 0.f);
2428 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2429
2430 armnn::LstmInputParams params;
2431 params.m_InputToForgetWeights = &inputToForgetWeights;
2432 params.m_InputToCellWeights = &inputToCellWeights;
2433 params.m_InputToOutputWeights = &inputToOutputWeights;
2434 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2435 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2436 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2437 params.m_ForgetGateBias = &forgetGateBias;
2438 params.m_CellBias = &cellBias;
2439 params.m_OutputGateBias = &outputGateBias;
2440
2441 // additional params because: descriptor.m_CifgEnabled = false
2442 params.m_InputToInputWeights = &inputToInputWeights;
2443 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2444 params.m_CellToInputWeights = &cellToInputWeights;
2445 params.m_InputGateBias = &inputGateBias;
2446
2447 // additional params because: descriptor.m_ProjectionEnabled = true
2448 params.m_ProjectionWeights = &projectionWeights;
2449 params.m_ProjectionBias = &projectionBias;
2450
2451 // additional params because: descriptor.m_PeepholeEnabled = true
2452 params.m_CellToForgetWeights = &cellToForgetWeights;
2453 params.m_CellToOutputWeights = &cellToOutputWeights;
2454
2455 armnn::INetworkPtr network = armnn::INetwork::Create();
2456 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2457 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2458 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2459 const std::string layerName("lstm");
2460 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2461 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2462 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2463 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2464 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2465
2466 // connect up
2467 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2468 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2469 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2470 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2471
2472 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2473 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2474
2475 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2476 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2477
2478 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2479 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2480
2481 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2482 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2483
2484 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2485 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2486
2487 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2488 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2489
2490 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2491 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2492
2493 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2494 BOOST_CHECK(deserializedNetwork);
2495
2496 VerifyLstmLayer checker(
2497 layerName,
2498 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2499 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2500 descriptor,
2501 params);
2502 deserializedNetwork->Accept(checker);
2503}
2504
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002505BOOST_AUTO_TEST_SUITE_END()