blob: f64c14a184b7f54a14a09da06796eab9e32b5363 [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
6#include <armnn/ArmNN.hpp>
7#include <armnn/INetwork.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00008
Mike Kelly8c1701a2019-02-11 17:01:27 +00009#include "../Serializer.hpp"
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000010
Derek Lamberti0028d1b2019-02-20 13:57:42 +000011#include <armnnDeserializer/IDeserializer.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000012
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +000013#include <random>
Mike Kelly8c1701a2019-02-11 17:01:27 +000014#include <sstream>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000015#include <vector>
16
Mike Kelly8c1701a2019-02-11 17:01:27 +000017#include <boost/test/unit_test.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000018#include <flatbuffers/idl.h>
19
Derek Lamberti0028d1b2019-02-20 13:57:42 +000020using armnnDeserializer::IDeserializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000021
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000022namespace
23{
24
25armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
26{
27 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +000028 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000029}
30
31std::string SerializeNetwork(const armnn::INetwork& network)
32{
33 armnnSerializer::Serializer serializer;
34 serializer.Serialize(network);
35
36 std::stringstream stream;
37 serializer.SaveSerializedToStream(stream);
38
39 std::string serializerString{stream.str()};
40 return serializerString;
41}
42
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +000043template<typename DataType>
44static std::vector<DataType> GenerateRandomData(size_t size)
45{
46 constexpr bool isIntegerType = std::is_integral<DataType>::value;
47 using Distribution =
48 typename std::conditional<isIntegerType,
49 std::uniform_int_distribution<DataType>,
50 std::uniform_real_distribution<DataType>>::type;
51
52 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
53 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
54
55 static Distribution distribution(lowerLimit, upperLimit);
56 static std::default_random_engine generator;
57
58 std::vector<DataType> randomData(size);
59 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
60
61 return randomData;
62}
63
64void CheckDeserializedNetworkAgainstOriginal(const armnn::INetwork& deserializedNetwork,
65 const armnn::INetwork& originalNetwork,
66 const armnn::TensorShape& inputShape,
67 const armnn::TensorShape& outputShape,
68 armnn::LayerBindingId inputBindingId = 0,
69 armnn::LayerBindingId outputBindingId = 0)
70{
71 armnn::IRuntime::CreationOptions options;
72 armnn::IRuntimePtr runtime = armnn::IRuntime::Create(options);
73
74 std::vector<armnn::BackendId> preferredBackends = { armnn::BackendId("CpuRef") };
75
76 // Optimize original network
77 armnn::IOptimizedNetworkPtr optimizedOriginalNetwork =
78 armnn::Optimize(originalNetwork, preferredBackends, runtime->GetDeviceSpec());
79 BOOST_CHECK(optimizedOriginalNetwork);
80
81 // Optimize deserialized network
82 armnn::IOptimizedNetworkPtr optimizedDeserializedNetwork =
83 armnn::Optimize(deserializedNetwork, preferredBackends, runtime->GetDeviceSpec());
84 BOOST_CHECK(optimizedDeserializedNetwork);
85
86 armnn::NetworkId networkId1;
87 armnn::NetworkId networkId2;
88
89 // Load original and deserialized network
90 armnn::Status status1 = runtime->LoadNetwork(networkId1, std::move(optimizedOriginalNetwork));
91 BOOST_CHECK(status1 == armnn::Status::Success);
92
93 armnn::Status status2 = runtime->LoadNetwork(networkId2, std::move(optimizedDeserializedNetwork));
94 BOOST_CHECK(status2 == armnn::Status::Success);
95
96 // Generate some input data
97 std::vector<float> inputData = GenerateRandomData<float>(inputShape.GetNumElements());
98
99 armnn::InputTensors inputTensors1
100 {
101 { 0, armnn::ConstTensor(runtime->GetInputTensorInfo(networkId1, inputBindingId), inputData.data()) }
102 };
103
104 armnn::InputTensors inputTensors2
105 {
106 { 0, armnn::ConstTensor(runtime->GetInputTensorInfo(networkId2, inputBindingId), inputData.data()) }
107 };
108
109 std::vector<float> outputData1(outputShape.GetNumElements());
110 std::vector<float> outputData2(outputShape.GetNumElements());
111
112 armnn::OutputTensors outputTensors1
113 {
114 { 0, armnn::Tensor(runtime->GetOutputTensorInfo(networkId1, outputBindingId), outputData1.data()) }
115 };
116
117 armnn::OutputTensors outputTensors2
118 {
119 { 0, armnn::Tensor(runtime->GetOutputTensorInfo(networkId2, outputBindingId), outputData2.data()) }
120 };
121
122 // Run original and deserialized network
123 runtime->EnqueueWorkload(networkId1, inputTensors1, outputTensors1);
124 runtime->EnqueueWorkload(networkId2, inputTensors2, outputTensors2);
125
126 // Compare output data
127 BOOST_CHECK_EQUAL_COLLECTIONS(outputData1.begin(), outputData1.end(),
128 outputData2.begin(), outputData2.end());
129}
130
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000131} // anonymous namespace
132
133BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000134
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000135BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000136{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000137 class VerifyAdditionName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
138 {
139 public:
140 void VisitAdditionLayer(const armnn::IConnectableLayer*, const char* name) override
141 {
142 BOOST_TEST(name == "addition");
143 }
144 };
145
Mike Kelly8c1701a2019-02-11 17:01:27 +0000146 armnn::INetworkPtr network = armnn::INetwork::Create();
147 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
148 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
149
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000150 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer("addition");
151 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
152 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000153
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000154 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
155 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000156
Jim Flynn3091b062019-02-15 14:45:04 +0000157 armnn::TensorShape shape{1U};
158 armnn::TensorInfo info(shape, armnn::DataType::Float32);
159 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
160 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000161 additionLayer->GetOutputSlot(0).SetTensorInfo(info);
Jim Flynn3091b062019-02-15 14:45:04 +0000162
Mike Kelly8c1701a2019-02-11 17:01:27 +0000163 armnnSerializer::Serializer serializer;
164 serializer.Serialize(*network);
165
166 std::stringstream stream;
167 serializer.SaveSerializedToStream(stream);
168 BOOST_TEST(stream.str().length() > 0);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000169
170 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str());
171 BOOST_CHECK(deserializedNetwork);
172
173 VerifyAdditionName nameChecker;
174 deserializedNetwork->Accept(nameChecker);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000175}
176
Conor Kennedy76277882019-02-26 08:29:54 +0000177BOOST_AUTO_TEST_CASE(SerializeConstant)
178{
179 armnn::INetworkPtr network = armnn::INetwork::Create();
180
181 armnn::ConstTensor inputTensor;
182
183 armnn::IConnectableLayer* const inputLayer0 = network->AddConstantLayer(inputTensor, "constant");
184 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
185
186 inputLayer0->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
187
188 armnnSerializer::Serializer serializer;
189 serializer.Serialize(*network);
190
191 std::stringstream stream;
192 serializer.SaveSerializedToStream(stream);
193 BOOST_TEST(stream.str().length() > 0);
194 BOOST_TEST(stream.str().find("constant") != stream.str().npos);
195}
196
197BOOST_AUTO_TEST_CASE(SerializeDeserializeConstant)
198{
199 class VerifyConstantName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
200 {
201 public:
202 void VisitConstantLayer(const armnn::IConnectableLayer*, const armnn::ConstTensor&, const char* name) override
203 {
204 BOOST_TEST(name == "constant");
205 }
206 };
207
208 armnn::TensorInfo commonTensorInfo({ 2, 3 }, armnn::DataType::Float32);
209
210 std::vector<float> constantData = GenerateRandomData<float>(commonTensorInfo.GetNumElements());
211 armnn::ConstTensor constTensor(commonTensorInfo, constantData);
212
213 // Builds up the structure of the network.
214 armnn::INetworkPtr net(armnn::INetwork::Create());
215
216 armnn::IConnectableLayer* input = net->AddInputLayer(0);
217 armnn::IConnectableLayer* constant = net->AddConstantLayer(constTensor, "constant");
218 armnn::IConnectableLayer* add = net->AddAdditionLayer();
219 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
220
221 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
222 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
223 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
224
225 // Sets the tensors in the network.
226 input->GetOutputSlot(0).SetTensorInfo(commonTensorInfo);
227 constant->GetOutputSlot(0).SetTensorInfo(commonTensorInfo);
228 add->GetOutputSlot(0).SetTensorInfo(commonTensorInfo);
229
230 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*net));
231 BOOST_CHECK(deserializedNetwork);
232
233 VerifyConstantName nameChecker;
234 deserializedNetwork->Accept(nameChecker);
235
236 CheckDeserializedNetworkAgainstOriginal(*net,
237 *deserializedNetwork,
238 commonTensorInfo.GetShape(),
239 commonTensorInfo.GetShape());
240}
241
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000242BOOST_AUTO_TEST_CASE(SerializeMultiplication)
Sadik Armagan5f450272019-02-12 14:31:45 +0000243{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000244 class VerifyMultiplicationName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
245 {
246 public:
247 void VisitMultiplicationLayer(const armnn::IConnectableLayer*, const char* name) override
248 {
249 BOOST_TEST(name == "multiplication");
250 }
251 };
252
Sadik Armagan5f450272019-02-12 14:31:45 +0000253 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
254
255 armnn::INetworkPtr network = armnn::INetwork::Create();
256 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
257 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
258
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000259 const char* multLayerName = "multiplication";
Sadik Armagan5f450272019-02-12 14:31:45 +0000260
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000261 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(multLayerName);
262 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
263 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
Sadik Armagan5f450272019-02-12 14:31:45 +0000264
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000265 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
266 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Sadik Armagan5f450272019-02-12 14:31:45 +0000267
Jim Flynn3091b062019-02-15 14:45:04 +0000268 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
269 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000270 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
Jim Flynn3091b062019-02-15 14:45:04 +0000271
Sadik Armagan5f450272019-02-12 14:31:45 +0000272 armnnSerializer::Serializer serializer;
273 serializer.Serialize(*network);
274
275 std::stringstream stream;
276 serializer.SaveSerializedToStream(stream);
277 BOOST_TEST(stream.str().length() > 0);
278 BOOST_TEST(stream.str().find(multLayerName) != stream.str().npos);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000279
280 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str());
281 BOOST_CHECK(deserializedNetwork);
282
283 VerifyMultiplicationName nameChecker;
284 deserializedNetwork->Accept(nameChecker);
Sadik Armagan5f450272019-02-12 14:31:45 +0000285}
286
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000287BOOST_AUTO_TEST_CASE(SerializeDeserializeConvolution2d)
Saoirse Stewart263829c2019-02-19 15:54:14 +0000288{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000289
290 class VerifyConvolution2dName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
291 {
292 public:
293 void VisitConvolution2dLayer(const armnn::IConnectableLayer*,
294 const armnn::Convolution2dDescriptor&,
295 const armnn::ConstTensor&,
296 const armnn::Optional<armnn::ConstTensor>&,
297 const char* name) override
298 {
299 BOOST_TEST(name == "convolution");
300 }
301 };
302
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000303 armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
304 armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000305
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000306 armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
307 armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
308
309 // Construct network
310 armnn::INetworkPtr network = armnn::INetwork::Create();
311
312 armnn::Convolution2dDescriptor descriptor;
313 descriptor.m_PadLeft = 1;
314 descriptor.m_PadRight = 1;
315 descriptor.m_PadTop = 1;
316 descriptor.m_PadBottom = 1;
317 descriptor.m_StrideX = 2;
318 descriptor.m_StrideY = 2;
319 descriptor.m_BiasEnabled = true;
320 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
321
322 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
323 armnn::ConstTensor weights(weightsInfo, weightsData);
324
325 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
326 armnn::ConstTensor biases(biasesInfo, biasesData);
327
328 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0, "input");
329 armnn::IConnectableLayer* const convLayer =
330 network->AddConvolution2dLayer(descriptor, weights, biases, "convolution");
331 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0, "output");
332
333 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
334 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
335
336 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
337 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
338
339 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
340 BOOST_CHECK(deserializedNetwork);
341
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000342 VerifyConvolution2dName nameChecker;
343 deserializedNetwork->Accept(nameChecker);
344
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000345 CheckDeserializedNetworkAgainstOriginal(*network,
346 *deserializedNetwork,
347 inputInfo.GetShape(),
348 outputInfo.GetShape());
349}
350
351BOOST_AUTO_TEST_CASE(SerializeDeserializeReshape)
352{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000353 class VerifyReshapeName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
354 {
355 public:
356 void VisitReshapeLayer(const armnn::IConnectableLayer*, const armnn::ReshapeDescriptor&, const char* name)
357 {
358 BOOST_TEST(name == "reshape");
359 }
360 };
361
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000362 unsigned int inputShape[] = { 1, 9 };
363 unsigned int outputShape[] = { 3, 3 };
Saoirse Stewart263829c2019-02-19 15:54:14 +0000364
365 auto inputTensorInfo = armnn::TensorInfo(2, inputShape, armnn::DataType::Float32);
366 auto outputTensorInfo = armnn::TensorInfo(2, outputShape, armnn::DataType::Float32);
367 auto reshapeOutputTensorInfo = armnn::TensorInfo(2, outputShape, armnn::DataType::Float32);
368
369 armnn::ReshapeDescriptor reshapeDescriptor;
370 reshapeDescriptor.m_TargetShape = reshapeOutputTensorInfo.GetShape();
371
372 armnn::INetworkPtr network = armnn::INetwork::Create();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000373 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
374 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(reshapeDescriptor, "reshape");
375 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000376
377 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
378 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
379 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
380 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
381
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000382 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
383 BOOST_CHECK(deserializedNetwork);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000384
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000385 VerifyReshapeName nameChecker;
386 deserializedNetwork->Accept(nameChecker);
387
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000388 CheckDeserializedNetworkAgainstOriginal(*network,
389 *deserializedNetwork,
390 inputTensorInfo.GetShape(),
391 outputTensorInfo.GetShape());
Saoirse Stewart263829c2019-02-19 15:54:14 +0000392}
393
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000394BOOST_AUTO_TEST_CASE(SerializeDeserializeDepthwiseConvolution2d)
395{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000396 class VerifyDepthwiseConvolution2dName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
397 {
398 public:
399 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer*,
400 const armnn::DepthwiseConvolution2dDescriptor&,
401 const armnn::ConstTensor&,
402 const armnn::Optional<armnn::ConstTensor>&,
403 const char* name) override
404 {
405 BOOST_TEST(name == "depthwise_convolution");
406 }
407 };
408
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000409 armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
410 armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
411
412 armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
413 armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
414
415 armnn::DepthwiseConvolution2dDescriptor descriptor;
416 descriptor.m_StrideX = 1;
417 descriptor.m_StrideY = 1;
418 descriptor.m_BiasEnabled = true;
419 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
420
421 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
422 armnn::ConstTensor weights(weightsInfo, weightsData);
423
424 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
425 armnn::ConstTensor biases(biasesInfo, biasesData);
426
427 armnn::INetworkPtr network = armnn::INetwork::Create();
428 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
429 armnn::IConnectableLayer* const depthwiseConvLayer =
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000430 network->AddDepthwiseConvolution2dLayer(descriptor, weights, biases, "depthwise_convolution");
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000431 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
432
433 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
434 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
435 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
436 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
437
438 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
439 BOOST_CHECK(deserializedNetwork);
440
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000441 VerifyDepthwiseConvolution2dName nameChecker;
442 deserializedNetwork->Accept(nameChecker);
443
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000444 CheckDeserializedNetworkAgainstOriginal(*network,
445 *deserializedNetwork,
446 inputInfo.GetShape(),
447 outputInfo.GetShape());
448}
449
450BOOST_AUTO_TEST_CASE(SerializeDeserializeSoftmax)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000451{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000452 class VerifySoftmaxName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
453 {
454 public:
455 void VisitSoftmaxLayer(const armnn::IConnectableLayer*, const armnn::SoftmaxDescriptor&, const char* name)
456 {
457 BOOST_TEST(name == "softmax");
458 }
459 };
460
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000461 armnn::TensorInfo tensorInfo({1, 10}, armnn::DataType::Float32);
462
463 armnn::SoftmaxDescriptor descriptor;
464 descriptor.m_Beta = 1.0f;
465
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000466 armnn::INetworkPtr network = armnn::INetwork::Create();
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000467 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
468 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, "softmax");
469 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000470
471 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
472 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
473 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
474 softmaxLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
475
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000476 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000477 BOOST_CHECK(deserializedNetwork);
478
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000479 VerifySoftmaxName nameChecker;
480 deserializedNetwork->Accept(nameChecker);
481
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000482 CheckDeserializedNetworkAgainstOriginal(*network,
483 *deserializedNetwork,
484 tensorInfo.GetShape(),
485 tensorInfo.GetShape());
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000486}
487
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000488BOOST_AUTO_TEST_CASE(SerializeDeserializePooling2d)
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000489{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000490 class VerifyPooling2dName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
491 {
492 void VisitPooling2dLayer(const armnn::IConnectableLayer*, const armnn::Pooling2dDescriptor&, const char* name)
493 {
494 BOOST_TEST(name == "pooling2d");
495 }
496 };
497
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000498 unsigned int inputShape[] = {1, 2, 2, 1};
499 unsigned int outputShape[] = {1, 1, 1, 1};
500
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000501 auto inputInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
502 auto outputInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000503
504 armnn::Pooling2dDescriptor desc;
505 desc.m_DataLayout = armnn::DataLayout::NHWC;
506 desc.m_PadTop = 0;
507 desc.m_PadBottom = 0;
508 desc.m_PadLeft = 0;
509 desc.m_PadRight = 0;
510 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
511 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
512 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
513 desc.m_PoolHeight = 2;
514 desc.m_PoolWidth = 2;
515 desc.m_StrideX = 2;
516 desc.m_StrideY = 2;
517
518 armnn::INetworkPtr network = armnn::INetwork::Create();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000519 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
520 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, "pooling2d");
521 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000522
523 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000524 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000525 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000526 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000527
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000528 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
529 BOOST_CHECK(deserializedNetwork);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000530
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000531 VerifyPooling2dName nameChecker;
532 deserializedNetwork->Accept(nameChecker);
533
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000534 CheckDeserializedNetworkAgainstOriginal(*network,
535 *deserializedNetwork,
536 inputInfo.GetShape(),
537 outputInfo.GetShape());
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000538}
539
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000540BOOST_AUTO_TEST_CASE(SerializeDeserializePermute)
541{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000542 class VerifyPermuteName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
543 {
544 public:
545 void VisitPermuteLayer(const armnn::IConnectableLayer*, const armnn::PermuteDescriptor&, const char* name)
546 {
547 BOOST_TEST(name == "permute");
548 }
549 };
550
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000551 unsigned int inputShape[] = { 4, 3, 2, 1 };
552 unsigned int outputShape[] = { 1, 2, 3, 4 };
553 unsigned int dimsMapping[] = { 3, 2, 1, 0 };
554
555 auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
556 auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
557
558 armnn::PermuteDescriptor permuteDescriptor(armnn::PermutationVector(dimsMapping, 4));
559
560 armnn::INetworkPtr network = armnn::INetwork::Create();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000561 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
562 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(permuteDescriptor, "permute");
563 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000564
565 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
566 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
567 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
568 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
569
570 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
571 BOOST_CHECK(deserializedNetwork);
572
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000573 VerifyPermuteName nameChecker;
574 deserializedNetwork->Accept(nameChecker);
575
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000576 CheckDeserializedNetworkAgainstOriginal(*network,
577 *deserializedNetwork,
578 inputTensorInfo.GetShape(),
579 outputTensorInfo.GetShape());
580}
581
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000582BOOST_AUTO_TEST_CASE(SerializeDeserializeFullyConnected)
583{
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000584 class VerifyFullyConnectedName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
585 {
586 public:
587 void VisitFullyConnectedLayer(const armnn::IConnectableLayer*,
588 const armnn::FullyConnectedDescriptor&,
589 const armnn::ConstTensor&,
590 const armnn::Optional<armnn::ConstTensor>&,
591 const char* name) override
592 {
593 BOOST_TEST(name == "fully_connected");
594 }
595 };
596
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000597 armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
598 armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
599
600 armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
601 armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
602
603 armnn::FullyConnectedDescriptor descriptor;
604 descriptor.m_BiasEnabled = true;
605 descriptor.m_TransposeWeightMatrix = false;
606
607 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
608 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
609
610 armnn::ConstTensor weights(weightsInfo, weightsData);
611 armnn::ConstTensor biases(biasesInfo, biasesData);
612
613 armnn::INetworkPtr network = armnn::INetwork::Create();
614 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0, "input");
615 armnn::IConnectableLayer* const fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor,
616 weights,
617 biases,
618 "fully_connected");
619 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0, "output");
620
621 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
622 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
623
624 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
625 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
626
627 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
628 BOOST_CHECK(deserializedNetwork);
629
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000630 VerifyFullyConnectedName nameChecker;
631 deserializedNetwork->Accept(nameChecker);
632
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000633 CheckDeserializedNetworkAgainstOriginal(*network,
634 *deserializedNetwork,
635 inputInfo.GetShape(),
636 outputInfo.GetShape());
637}
638
Nattapat Chaimanowong45286992019-02-26 15:53:02 +0000639BOOST_AUTO_TEST_CASE(SerializeDeserializeSpaceToBatchNd)
640{
641 class VerifySpaceToBatchNdName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
642 {
643 public:
644 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer*,
645 const armnn::SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor,
646 const char* name) override
647 {
648 BOOST_TEST(name == "SpaceToBatchNdLayer");
649 }
650 };
651
652 unsigned int inputShape[] = {2, 1, 2, 4};
653 unsigned int outputShape[] = {8, 1, 1, 3};
654
655 armnn::SpaceToBatchNdDescriptor desc;
656 desc.m_DataLayout = armnn::DataLayout::NCHW;
657 desc.m_BlockShape = {2, 2};
658 desc.m_PadList = {{0, 0}, {2, 0}};
659
660 auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
661 auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
662
663 armnn::INetworkPtr network = armnn::INetwork::Create();
664 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
665 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, "SpaceToBatchNdLayer");
666 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
667
668 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
669 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
670 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
671 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
672
673 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
674 BOOST_CHECK(deserializedNetwork);
675
676 VerifySpaceToBatchNdName nameChecker;
677 deserializedNetwork->Accept(nameChecker);
678
679 CheckDeserializedNetworkAgainstOriginal(*network,
680 *deserializedNetwork,
681 inputTensorInfo.GetShape(),
682 outputTensorInfo.GetShape());
683}
684
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000685BOOST_AUTO_TEST_SUITE_END()