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