blob: 1c1cefd455dca4704eb8cab5ec50e747a88b35ae [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 "Serializer.hpp"
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00007
8#include "SerializerUtils.hpp"
9
Mike Kelly8c1701a2019-02-11 17:01:27 +000010#include <armnn/ArmNN.hpp>
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000011
Mike Kelly8c1701a2019-02-11 17:01:27 +000012#include <iostream>
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000013
Matthew Bentham268509a2019-02-25 13:58:24 +000014#include <ArmnnSchema_generated.h>
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000015
Mike Kelly8c1701a2019-02-11 17:01:27 +000016#include <flatbuffers/util.h>
17
18using namespace armnn;
19namespace fb = flatbuffers;
Derek Lamberti0028d1b2019-02-20 13:57:42 +000020namespace serializer = armnnSerializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000021
22namespace armnnSerializer
23{
24
Mike Kellyaf484012019-02-20 16:53:11 +000025serializer::ActivationFunction GetFlatBufferActivationFunction(armnn::ActivationFunction function)
26{
27 switch (function)
28 {
29 case armnn::ActivationFunction::Sigmoid:
30 return serializer::ActivationFunction::ActivationFunction_Sigmoid;
31 case armnn::ActivationFunction::TanH:
32 return serializer::ActivationFunction::ActivationFunction_TanH;
33 case armnn::ActivationFunction::Linear:
34 return serializer::ActivationFunction::ActivationFunction_Linear;
35 case armnn::ActivationFunction::ReLu:
36 return serializer::ActivationFunction::ActivationFunction_ReLu;
37 case armnn::ActivationFunction::BoundedReLu:
38 return serializer::ActivationFunction::ActivationFunction_BoundedReLu;
39 case armnn::ActivationFunction::LeakyReLu:
40 return serializer::ActivationFunction::ActivationFunction_LeakyReLu;
41 case armnn::ActivationFunction::Abs:
42 return serializer::ActivationFunction::ActivationFunction_Abs;
43 case armnn::ActivationFunction::Sqrt:
44 return serializer::ActivationFunction::ActivationFunction_Sqrt;
45 case armnn::ActivationFunction::Square:
46 return serializer::ActivationFunction::ActivationFunction_Square;
47 default:
48 return serializer::ActivationFunction::ActivationFunction_Sigmoid;
49 }
50}
51
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000052uint32_t SerializerVisitor::GetSerializedId(unsigned int guid)
53{
54 std::pair<unsigned int, uint32_t> guidPair(guid, m_layerId);
55
56 if (m_guidMap.empty())
57 {
58 m_guidMap.insert(guidPair);
59 }
60 else if (m_guidMap.find(guid) == m_guidMap.end())
61 {
62 guidPair.second = ++m_layerId;
63 m_guidMap.insert(guidPair);
64 return m_layerId;
65 }
Saoirse Stewart30211042019-02-18 17:19:16 +000066 return m_guidMap[guid];
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000067}
68
Mike Kelly8c1701a2019-02-11 17:01:27 +000069// Build FlatBuffer for Input Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +000070void SerializerVisitor::VisitInputLayer(const armnn::IConnectableLayer* layer, LayerBindingId id, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000071{
72 // Create FlatBuffer BaseLayer
73 auto flatBufferInputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Input);
74
75 // Create FlatBuffer BindableBaseLayer
76 auto flatBufferInputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
77 flatBufferInputBaseLayer,
78 id);
Mike Kelly8c1701a2019-02-11 17:01:27 +000079 // Push layer Guid to outputIds.
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000080 m_inputIds.push_back(GetSerializedId(layer->GetGuid()));
Mike Kelly8c1701a2019-02-11 17:01:27 +000081
82 // Create the FlatBuffer InputLayer
83 auto flatBufferInputLayer = serializer::CreateInputLayer(m_flatBufferBuilder, flatBufferInputBindableBaseLayer);
84
85 // Add the AnyLayer to the FlatBufferLayers
86 CreateAnyLayer(flatBufferInputLayer.o, serializer::Layer::Layer_InputLayer);
87}
88
89// Build FlatBuffer for Output Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +000090void SerializerVisitor::VisitOutputLayer(const armnn::IConnectableLayer* layer, LayerBindingId id, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000091{
92 // Create FlatBuffer BaseLayer
93 auto flatBufferOutputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Output);
94
95 // Create FlatBuffer BindableBaseLayer
96 auto flatBufferOutputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
97 flatBufferOutputBaseLayer,
98 id);
99 // Push layer Guid to outputIds.
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000100 m_outputIds.push_back(GetSerializedId(layer->GetGuid()));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000101
102 // Create the FlatBuffer OutputLayer
103 auto flatBufferOutputLayer = serializer::CreateOutputLayer(m_flatBufferBuilder, flatBufferOutputBindableBaseLayer);
104 // Add the AnyLayer to the FlatBufferLayers
105 CreateAnyLayer(flatBufferOutputLayer.o, serializer::Layer::Layer_OutputLayer);
106}
107
Mike Kellyaf484012019-02-20 16:53:11 +0000108// Build FlatBuffer for Activation Layer
109void SerializerVisitor::VisitActivationLayer(const armnn::IConnectableLayer* layer,
110 const armnn::ActivationDescriptor& descriptor,
111 const char* name)
112{
113 // Create FlatBuffer BaseLayer
114 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Activation);
115
116 // Create the FlatBuffer ActivationDescriptor
117 auto flatBufferDescriptor = CreateActivationDescriptor(m_flatBufferBuilder,
118 GetFlatBufferActivationFunction(descriptor.m_Function),
119 descriptor.m_A,
120 descriptor.m_B);
121
122 // Create the FlatBuffer ActivationLayer
123 auto flatBufferAdditionLayer = CreateActivationLayer(m_flatBufferBuilder,
124 flatBufferBaseLayer,
125 flatBufferDescriptor);
126
127 // Add the AnyLayer to the FlatBufferLayers
128 CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_ActivationLayer);
129}
130
Mike Kelly8c1701a2019-02-11 17:01:27 +0000131// Build FlatBuffer for Addition Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000132void SerializerVisitor::VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000133{
134 // Create FlatBuffer BaseLayer
135 auto flatBufferAdditionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Addition);
136
137 // Create the FlatBuffer AdditionLayer
138 auto flatBufferAdditionLayer = serializer::CreateAdditionLayer(m_flatBufferBuilder, flatBufferAdditionBaseLayer);
139
140 // Add the AnyLayer to the FlatBufferLayers
141 CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_AdditionLayer);
142}
143
Conor Kennedy76277882019-02-26 08:29:54 +0000144// Build FlatBuffer for Constant Layer
145void SerializerVisitor::VisitConstantLayer(const armnn::IConnectableLayer* layer,
146 const armnn::ConstTensor& input,
147 const char* name)
148{
149 // Create FlatBuffer BaseLayer
150 auto flatBufferConstantBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Constant);
151
152 auto flatBufferConstTensorInfo = CreateConstTensorInfo(input);
153
154 // Create the FlatBuffer ConstantLayer
155 auto flatBufferLayer = CreateConstantLayer(m_flatBufferBuilder,
156 flatBufferConstantBaseLayer,
157 flatBufferConstTensorInfo);
158
159 // Add the AnyLayer to the FlatBufferLayers
160 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_ConstantLayer);
161}
162
Mike Kellya0766c32019-02-19 17:22:07 +0000163// Build FlatBuffer for Convolution2dLayer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000164void SerializerVisitor::VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
165 const armnn::Convolution2dDescriptor& descriptor,
166 const armnn::ConstTensor& weights,
167 const armnn::Optional<armnn::ConstTensor>& biases,
Mike Kellya0766c32019-02-19 17:22:07 +0000168 const char* name)
169{
170 // Create FlatBuffer BaseLayer
171 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution2d);
172
173 auto flatBufferDescriptor = CreateConvolution2dDescriptor(m_flatBufferBuilder,
174 descriptor.m_PadLeft,
175 descriptor.m_PadRight,
176 descriptor.m_PadTop,
177 descriptor.m_PadBottom,
178 descriptor.m_StrideX,
179 descriptor.m_StrideY,
180 descriptor.m_BiasEnabled,
181 GetFlatBufferDataLayout(descriptor.m_DataLayout));
182 auto flatBufferWeightsConstTensorInfo = CreateConstTensorInfo(weights);
183 flatbuffers::Offset<serializer::ConstTensor> flatBufferBiasesConstTensorInfo;
184
185 if (biases.has_value())
186 {
187 flatBufferBiasesConstTensorInfo = CreateConstTensorInfo(biases.value());
188 }
189
190 // Create the FlatBuffer Convolution2dLayer
191 auto flatBufferLayer = CreateConvolution2dLayer(m_flatBufferBuilder,
192 flatBufferBaseLayer,
193 flatBufferDescriptor,
194 flatBufferWeightsConstTensorInfo,
195 flatBufferBiasesConstTensorInfo);
196
197 // Add the AnyLayer to the FlatBufferLayers
198 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution2dLayer);
199}
200
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000201void SerializerVisitor::VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
202 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
203 const armnn::ConstTensor& weights,
204 const armnn::Optional<armnn::ConstTensor>& biases,
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000205 const char* name)
206{
207 auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_DepthwiseConvolution2d);
208 auto fbDescriptor = CreateDepthwiseConvolution2dDescriptor(m_flatBufferBuilder,
209 descriptor.m_PadLeft,
210 descriptor.m_PadRight,
211 descriptor.m_PadTop,
212 descriptor.m_PadBottom,
213 descriptor.m_StrideX,
214 descriptor.m_StrideY,
215 descriptor.m_BiasEnabled,
216 GetFlatBufferDataLayout(descriptor.m_DataLayout));
217
218 flatbuffers::Offset<serializer::ConstTensor> fbWeightsConstTensorInfo = CreateConstTensorInfo(weights);
219 flatbuffers::Offset<serializer::ConstTensor> fbBiasesConstTensorInfo;
220 if (biases.has_value())
221 {
222 fbBiasesConstTensorInfo = CreateConstTensorInfo(biases.value());
223 }
224
225 auto flatBufferLayer = CreateDepthwiseConvolution2dLayer(m_flatBufferBuilder,
226 fbBaseLayer,
227 fbDescriptor,
228 fbWeightsConstTensorInfo,
229 fbBiasesConstTensorInfo);
230
231 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_DepthwiseConvolution2dLayer);
232}
233
Sadik Armagan5f450272019-02-12 14:31:45 +0000234// Build FlatBuffer for Multiplication Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000235void SerializerVisitor::VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name)
Sadik Armagan5f450272019-02-12 14:31:45 +0000236{
237 // Create FlatBuffer BaseLayer
238 auto flatBufferMultiplicationBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Multiplication);
239
240 // Create the FlatBuffer MultiplicationLayer
241 auto flatBufferMultiplicationLayer =
242 serializer::CreateMultiplicationLayer(m_flatBufferBuilder, flatBufferMultiplicationBaseLayer);
243
244 // Add the AnyLayer to the FlatBufferLayers
245 CreateAnyLayer(flatBufferMultiplicationLayer.o, serializer::Layer::Layer_MultiplicationLayer);
246}
247
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000248void SerializerVisitor::VisitPermuteLayer(const armnn::IConnectableLayer* layer,
249 const armnn::PermuteDescriptor& permuteDescriptor,
250 const char* name)
251{
252 // Create FlatBuffer BaseLayer
253 auto flatBufferPermuteBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Permute);
254
255 std::vector<unsigned int> dimMappings;
256 for (auto& v: permuteDescriptor.m_DimMappings)
257 {
258 dimMappings.push_back(v);
259 }
260
261 auto flatBufferPermuteDesc = serializer::CreatePermuteDescriptor(m_flatBufferBuilder,
262 m_flatBufferBuilder.CreateVector(dimMappings));
263
264 // Create the FlatBuffer PermuteLayer
265 auto flatBufferPermuteLayer = serializer::CreatePermuteLayer(m_flatBufferBuilder,
266 flatBufferPermuteBaseLayer,
267 flatBufferPermuteDesc);
268
269 // Add the AnyLayer to the FlatBufferLayers
270 CreateAnyLayer(flatBufferPermuteLayer.o, serializer::Layer::Layer_PermuteLayer);
271}
272
Saoirse Stewart263829c2019-02-19 15:54:14 +0000273// Build FlatBuffer for Reshape Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000274void SerializerVisitor::VisitReshapeLayer(const armnn::IConnectableLayer* layer,
Saoirse Stewart263829c2019-02-19 15:54:14 +0000275 const armnn::ReshapeDescriptor& reshapeDescriptor,
276 const char* name)
277{
278 // Create FlatBuffer BaseLayer
279 auto flatBufferReshapeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Reshape);
280
281 std::vector<unsigned int> targetShape;
282 for (unsigned int i =0; i < reshapeDescriptor.m_TargetShape.GetNumDimensions(); i++)
283 {
284 targetShape.push_back(reshapeDescriptor.m_TargetShape[i]);
285 }
286
287 auto flatBufferReshapeDesc = serializer::CreateReshapeDescriptor(m_flatBufferBuilder,
288 m_flatBufferBuilder.CreateVector(targetShape));
289
290 // Create the FlatBuffer ReshapeLayer
291 auto flatBufferReshapeLayer = serializer::CreateReshapeLayer(m_flatBufferBuilder, flatBufferReshapeBaseLayer,
292 flatBufferReshapeDesc);
293
294 // Add the AnyLayer to the FlatBufferLayers
295 CreateAnyLayer(flatBufferReshapeLayer.o, serializer::Layer::Layer_ReshapeLayer);
296}
297
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000298// Build FlatBuffer for Softmax Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000299void SerializerVisitor::VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
300 const armnn::SoftmaxDescriptor& softmaxDescriptor,
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000301 const char* name)
302{
303 // Create FlatBuffer BaseLayer
304 auto flatBufferSoftmaxBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Softmax);
305
306 // Create the FlatBuffer SoftmaxDescriptor
307 auto flatBufferSoftmaxDesc =
308 serializer::CreateSoftmaxDescriptor(m_flatBufferBuilder, softmaxDescriptor.m_Beta);
309
310 // Create the FlatBuffer SoftmaxLayer
311 auto flatBufferSoftmaxLayer =
312 serializer::CreateSoftmaxLayer(m_flatBufferBuilder,
313 flatBufferSoftmaxBaseLayer,
314 flatBufferSoftmaxDesc);
315
316 CreateAnyLayer(flatBufferSoftmaxLayer.o, serializer::Layer::Layer_SoftmaxLayer);
317}
318
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000319void SerializerVisitor::VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
320 const armnn::Pooling2dDescriptor& pooling2dDescriptor,
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000321 const char* name)
322{
323 auto fbPooling2dBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Pooling2d);
324 auto fbPooling2dDescriptor = serializer::CreatePooling2dDescriptor(
325 m_flatBufferBuilder,
326 GetFlatBufferPoolingAlgorithm(pooling2dDescriptor.m_PoolType),
327 pooling2dDescriptor.m_PadLeft,
328 pooling2dDescriptor.m_PadRight,
329 pooling2dDescriptor.m_PadTop,
330 pooling2dDescriptor.m_PadBottom,
331 pooling2dDescriptor.m_PoolWidth,
332 pooling2dDescriptor.m_PoolHeight,
333 pooling2dDescriptor.m_StrideX,
334 pooling2dDescriptor.m_StrideY,
335 GetFlatBufferOutputShapeRounding(pooling2dDescriptor.m_OutputShapeRounding),
336 GetFlatBufferPaddingMethod(pooling2dDescriptor.m_PaddingMethod),
337 GetFlatBufferDataLayout(pooling2dDescriptor.m_DataLayout));
338
339 auto fbPooling2dLayer = serializer::CreatePooling2dLayer(m_flatBufferBuilder,
340 fbPooling2dBaseLayer,
341 fbPooling2dDescriptor);
342
343 CreateAnyLayer(fbPooling2dLayer.o, serializer::Layer::Layer_Pooling2dLayer);
344}
345
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000346// Build FlatBuffer for FullyConnected Layer
347void SerializerVisitor::VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
348 const armnn::FullyConnectedDescriptor& fullyConnectedDescriptor,
349 const armnn::ConstTensor& weights,
350 const armnn::Optional<armnn::ConstTensor>& biases,
351 const char* name)
352{
353 // Create FlatBuffer BaseLayer
354 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_FullyConnected);
355
356 // Create FlatBuffer FullyConnectedDescriptor
357 auto flatBufferDescriptor =
358 serializer::CreateFullyConnectedDescriptor(m_flatBufferBuilder,
359 fullyConnectedDescriptor.m_BiasEnabled,
360 fullyConnectedDescriptor.m_TransposeWeightMatrix);
361
362 // Create FlatBuffer weights data
363 auto flatBufferWeights = CreateConstTensorInfo(weights);
364
365 // Create FlatBuffer bias data
366 flatbuffers::Offset<serializer::ConstTensor> flatBufferBiases;
367 if (fullyConnectedDescriptor.m_BiasEnabled)
368 {
369 flatBufferBiases = CreateConstTensorInfo(biases.value());
370 }
371
372 // Create FlatBuffer FullyConnectedLayer
373 auto flatBufferLayer = serializer::CreateFullyConnectedLayer(m_flatBufferBuilder,
374 flatBufferBaseLayer,
375 flatBufferDescriptor,
376 flatBufferWeights,
377 flatBufferBiases);
378
379 // Add created FullyConnectedLayer to the FlatBufferLayers
380 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_FullyConnectedLayer);
381}
382
Nattapat Chaimanowong45286992019-02-26 15:53:02 +0000383// Build FlatBuffer for SpaceToBatchNd Layer
384void SerializerVisitor::VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
385 const armnn::SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor,
386 const char* name)
387{
388 // Create FlatBuffer BaseLayer
389 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_SpaceToBatchNd);
390
391 std::vector<unsigned int> padList;
392 padList.reserve(spaceToBatchNdDescriptor.m_PadList.size()*2);
393 for (auto& pad : spaceToBatchNdDescriptor.m_PadList)
394 {
395 padList.push_back(pad.first);
396 padList.push_back(pad.second);
397 }
398
399 auto flatBufferDescriptor =
400 CreateSpaceToBatchNdDescriptor(m_flatBufferBuilder,
401 m_flatBufferBuilder.CreateVector(spaceToBatchNdDescriptor.m_BlockShape),
402 m_flatBufferBuilder.CreateVector(padList),
403 GetFlatBufferDataLayout(spaceToBatchNdDescriptor.m_DataLayout));
404
405 auto flatBufferLayer = serializer::CreateSpaceToBatchNdLayer(m_flatBufferBuilder,
406 flatBufferBaseLayer,
407 flatBufferDescriptor);
408
409 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_SpaceToBatchNdLayer);
410}
411
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000412fb::Offset<serializer::LayerBase> SerializerVisitor::CreateLayerBase(const IConnectableLayer* layer,
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000413 const serializer::LayerType layerType)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000414{
415 std::vector<fb::Offset<serializer::InputSlot>> inputSlots = CreateInputSlots(layer);
416 std::vector<fb::Offset<serializer::OutputSlot>> outputSlots = CreateOutputSlots(layer);
417
418 return serializer::CreateLayerBase(m_flatBufferBuilder,
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000419 GetSerializedId(layer->GetGuid()),
Mike Kelly8c1701a2019-02-11 17:01:27 +0000420 m_flatBufferBuilder.CreateString(layer->GetName()),
421 layerType,
422 m_flatBufferBuilder.CreateVector(inputSlots),
423 m_flatBufferBuilder.CreateVector(outputSlots));
424}
425
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000426void SerializerVisitor::CreateAnyLayer(const flatbuffers::Offset<void>& layer, const serializer::Layer serializerLayer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000427{
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000428 auto anyLayer = armnnSerializer::CreateAnyLayer(m_flatBufferBuilder, serializerLayer, layer);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000429 m_serializedLayers.push_back(anyLayer);
430}
431
Mike Kellya0766c32019-02-19 17:22:07 +0000432template <typename T>
433flatbuffers::Offset<flatbuffers::Vector<T>> SerializerVisitor::CreateDataVector(const void* memory, unsigned int size)
434{
435 const T* buffer = reinterpret_cast<const T*>(memory);
436 std::vector<T> vector(buffer, buffer + (size / sizeof(T)));
437 auto fbVector = m_flatBufferBuilder.CreateVector(vector);
438 return fbVector;
439}
440
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000441flatbuffers::Offset<serializer::ConstTensor>
442 SerializerVisitor::CreateConstTensorInfo(const armnn::ConstTensor& constTensor)
Mike Kellya0766c32019-02-19 17:22:07 +0000443{
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000444 armnn::TensorInfo tensorInfo = constTensor.GetInfo();
Mike Kellya0766c32019-02-19 17:22:07 +0000445
446 // Get the dimensions
447 std::vector<unsigned int> shape;
448
449 for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
450 {
451 shape.push_back(tensorInfo.GetShape()[dim]);
452 }
453
454 // Create FlatBuffer TensorInfo
455 auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
456 m_flatBufferBuilder.CreateVector(shape),
457 GetFlatBufferDataType(tensorInfo.GetDataType()),
458 tensorInfo.GetQuantizationScale(),
459 tensorInfo.GetQuantizationOffset());
460 flatbuffers::Offset<void> fbPayload;
461
462 switch (tensorInfo.GetDataType())
463 {
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000464 case armnn::DataType::Float32:
465 case armnn::DataType::Signed32:
Mike Kellya0766c32019-02-19 17:22:07 +0000466 {
467 auto fbVector = CreateDataVector<int32_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
468 flatbuffers::Offset<serializer::IntData> flatBuffersData = serializer::CreateIntData(
469 m_flatBufferBuilder,
470 fbVector);
471 fbPayload = flatBuffersData.o;
472 break;
473 }
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000474 case armnn::DataType::Float16:
Mike Kellya0766c32019-02-19 17:22:07 +0000475 {
476 auto fbVector = CreateDataVector<int16_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
477 flatbuffers::Offset<serializer::ShortData> flatBuffersData = serializer::CreateShortData(
478 m_flatBufferBuilder,
479 fbVector);
480 fbPayload = flatBuffersData.o;
481 break;
482 }
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000483 case armnn::DataType::QuantisedAsymm8:
484 case armnn::DataType::Boolean:
Mike Kellya0766c32019-02-19 17:22:07 +0000485 default:
486 {
487 auto fbVector = CreateDataVector<int8_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
488 flatbuffers::Offset<serializer::ByteData> flatBuffersData = serializer::CreateByteData(
489 m_flatBufferBuilder,
490 fbVector);
491 fbPayload = flatBuffersData.o;
492 }
493 }
494 flatbuffers::Offset<serializer::ConstTensor> flatBufferConstTensor = serializer::CreateConstTensor(
495 m_flatBufferBuilder,
496 flatBufferTensorInfo,
497 GetFlatBufferConstTensorData(tensorInfo.GetDataType()),
498 fbPayload);
499 return flatBufferConstTensor;
500}
501
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000502std::vector<fb::Offset<serializer::InputSlot>>
503 SerializerVisitor::CreateInputSlots(const armnn::IConnectableLayer* layer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000504{
Mike Kellya0766c32019-02-19 17:22:07 +0000505 std::vector<fb::Offset<serializer::InputSlot>> inputSlots;
Mike Kelly8c1701a2019-02-11 17:01:27 +0000506
507 // Get the InputSlots
508 for (unsigned int slotIndex = 0; slotIndex<layer->GetNumInputSlots(); ++slotIndex)
509 {
510 const IInputSlot& inputSlot = layer->GetInputSlot(slotIndex);
511
512 // Get the Connection for the InputSlot
513 const IOutputSlot* connection = inputSlot.GetConnection();
514
515 // Create FlatBuffer Connection
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000516 serializer::Connection conn(GetSerializedId(inputSlot.GetConnection()->GetOwningLayerGuid()),
517 connection->CalculateIndexOnOwner());
Mike Kelly8c1701a2019-02-11 17:01:27 +0000518 // Create FlatBuffer InputSlot
519 inputSlots.push_back(serializer::CreateInputSlot(m_flatBufferBuilder, slotIndex, &conn));
520 }
521 return inputSlots;
522}
523
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000524std::vector<fb::Offset<serializer::OutputSlot>>
525 SerializerVisitor::CreateOutputSlots(const armnn::IConnectableLayer* layer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000526{
527 std::vector<fb::Offset<serializer::OutputSlot>> outputSlots;
528
529 // Get the OutputSlots
530 for (unsigned int slotIndex = 0; slotIndex < layer->GetNumOutputSlots(); ++slotIndex)
531 {
532 const IOutputSlot& outputSlot = layer->GetOutputSlot(slotIndex);
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000533 const armnn::TensorInfo& tensorInfo = outputSlot.GetTensorInfo();
Mike Kelly8c1701a2019-02-11 17:01:27 +0000534
535 // Get the dimensions
536 std::vector<unsigned int> shape;
537 for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
538 {
539 shape.push_back(tensorInfo.GetShape()[dim]);
540 }
541
542 // Create FlatBuffer TensorInfo
543 auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
544 m_flatBufferBuilder.CreateVector(shape),
545 GetFlatBufferDataType(tensorInfo.GetDataType()),
546 tensorInfo.GetQuantizationScale(),
547 tensorInfo.GetQuantizationOffset());
548
549 // Create FlatBuffer Outputslot
550 outputSlots.push_back(serializer::CreateOutputSlot(m_flatBufferBuilder,
551 slotIndex,
552 flatBufferTensorInfo));
553 }
554 return outputSlots;
555}
556
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000557
558ISerializer* ISerializer::CreateRaw()
559{
560 return new Serializer();
561}
562
563ISerializerPtr ISerializer::Create()
564{
565 return ISerializerPtr(CreateRaw(), &ISerializer::Destroy);
566}
567
568void ISerializer::Destroy(ISerializer* serializer)
569{
570 delete serializer;
571}
572
573void Serializer::Serialize(const INetwork& inNetwork)
574{
575 // Iterate through to network
576 inNetwork.Accept(m_SerializerVisitor);
577 flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerVisitor.GetFlatBufferBuilder();
578
579 // Create FlatBuffer SerializedGraph
580 auto serializedGraph = serializer::CreateSerializedGraph(
581 fbBuilder,
582 fbBuilder.CreateVector(m_SerializerVisitor.GetSerializedLayers()),
583 fbBuilder.CreateVector(m_SerializerVisitor.GetInputIds()),
584 fbBuilder.CreateVector(m_SerializerVisitor.GetOutputIds()));
585
586 // Serialize the graph
587 fbBuilder.Finish(serializedGraph);
588}
589
590bool Serializer::SaveSerializedToStream(std::ostream& stream)
591{
592 flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerVisitor.GetFlatBufferBuilder();
593
Nattapat Chaimanowong7b53b692019-02-12 14:38:31 +0000594 auto bytesToWrite = boost::numeric_cast<std::streamsize>(fbBuilder.GetSize());
595 stream.write(reinterpret_cast<const char*>(fbBuilder.GetBufferPointer()), bytesToWrite);
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000596 return !stream.bad();
597}
598
Matteo Martincighec333912019-02-13 15:12:39 +0000599} // namespace armnnSerializer