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