blob: f475be101583811371e42594d2f4e97c6432de4c [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
Mike Kelly8c1701a2019-02-11 17:01:27 +000014#include <Schema_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;
20namespace serializer = armnn::armnnSerializer;
21
22namespace armnnSerializer
23{
24
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000025uint32_t SerializerVisitor::GetSerializedId(unsigned int guid)
26{
27 std::pair<unsigned int, uint32_t> guidPair(guid, m_layerId);
28
29 if (m_guidMap.empty())
30 {
31 m_guidMap.insert(guidPair);
32 }
33 else if (m_guidMap.find(guid) == m_guidMap.end())
34 {
35 guidPair.second = ++m_layerId;
36 m_guidMap.insert(guidPair);
37 return m_layerId;
38 }
39 return m_layerId;
40}
41
Mike Kelly8c1701a2019-02-11 17:01:27 +000042// Build FlatBuffer for Input Layer
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +000043void SerializerVisitor::VisitInputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000044{
45 // Create FlatBuffer BaseLayer
46 auto flatBufferInputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Input);
47
48 // Create FlatBuffer BindableBaseLayer
49 auto flatBufferInputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
50 flatBufferInputBaseLayer,
51 id);
Mike Kelly8c1701a2019-02-11 17:01:27 +000052 // Push layer Guid to outputIds.
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000053 m_inputIds.push_back(GetSerializedId(layer->GetGuid()));
Mike Kelly8c1701a2019-02-11 17:01:27 +000054
55 // Create the FlatBuffer InputLayer
56 auto flatBufferInputLayer = serializer::CreateInputLayer(m_flatBufferBuilder, flatBufferInputBindableBaseLayer);
57
58 // Add the AnyLayer to the FlatBufferLayers
59 CreateAnyLayer(flatBufferInputLayer.o, serializer::Layer::Layer_InputLayer);
60}
61
62// Build FlatBuffer for Output Layer
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +000063void SerializerVisitor::VisitOutputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000064{
65 // Create FlatBuffer BaseLayer
66 auto flatBufferOutputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Output);
67
68 // Create FlatBuffer BindableBaseLayer
69 auto flatBufferOutputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
70 flatBufferOutputBaseLayer,
71 id);
72 // Push layer Guid to outputIds.
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000073 m_outputIds.push_back(GetSerializedId(layer->GetGuid()));
Mike Kelly8c1701a2019-02-11 17:01:27 +000074
75 // Create the FlatBuffer OutputLayer
76 auto flatBufferOutputLayer = serializer::CreateOutputLayer(m_flatBufferBuilder, flatBufferOutputBindableBaseLayer);
77 // Add the AnyLayer to the FlatBufferLayers
78 CreateAnyLayer(flatBufferOutputLayer.o, serializer::Layer::Layer_OutputLayer);
79}
80
81// Build FlatBuffer for Addition Layer
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +000082void SerializerVisitor::VisitAdditionLayer(const IConnectableLayer* layer, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000083{
84 // Create FlatBuffer BaseLayer
85 auto flatBufferAdditionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Addition);
86
87 // Create the FlatBuffer AdditionLayer
88 auto flatBufferAdditionLayer = serializer::CreateAdditionLayer(m_flatBufferBuilder, flatBufferAdditionBaseLayer);
89
90 // Add the AnyLayer to the FlatBufferLayers
91 CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_AdditionLayer);
92}
93
Mike Kellya0766c32019-02-19 17:22:07 +000094// Build FlatBuffer for Convolution2dLayer
95void SerializerVisitor::VisitConvolution2dLayer(const IConnectableLayer* layer,
96 const Convolution2dDescriptor& descriptor,
97 const ConstTensor& weights,
98 const Optional<ConstTensor>& biases,
99 const char* name)
100{
101 // Create FlatBuffer BaseLayer
102 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution2d);
103
104 auto flatBufferDescriptor = CreateConvolution2dDescriptor(m_flatBufferBuilder,
105 descriptor.m_PadLeft,
106 descriptor.m_PadRight,
107 descriptor.m_PadTop,
108 descriptor.m_PadBottom,
109 descriptor.m_StrideX,
110 descriptor.m_StrideY,
111 descriptor.m_BiasEnabled,
112 GetFlatBufferDataLayout(descriptor.m_DataLayout));
113 auto flatBufferWeightsConstTensorInfo = CreateConstTensorInfo(weights);
114 flatbuffers::Offset<serializer::ConstTensor> flatBufferBiasesConstTensorInfo;
115
116 if (biases.has_value())
117 {
118 flatBufferBiasesConstTensorInfo = CreateConstTensorInfo(biases.value());
119 }
120
121 // Create the FlatBuffer Convolution2dLayer
122 auto flatBufferLayer = CreateConvolution2dLayer(m_flatBufferBuilder,
123 flatBufferBaseLayer,
124 flatBufferDescriptor,
125 flatBufferWeightsConstTensorInfo,
126 flatBufferBiasesConstTensorInfo);
127
128 // Add the AnyLayer to the FlatBufferLayers
129 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution2dLayer);
130}
131
Sadik Armagan5f450272019-02-12 14:31:45 +0000132// Build FlatBuffer for Multiplication Layer
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000133void SerializerVisitor::VisitMultiplicationLayer(const IConnectableLayer* layer, const char* name)
Sadik Armagan5f450272019-02-12 14:31:45 +0000134{
135 // Create FlatBuffer BaseLayer
136 auto flatBufferMultiplicationBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Multiplication);
137
138 // Create the FlatBuffer MultiplicationLayer
139 auto flatBufferMultiplicationLayer =
140 serializer::CreateMultiplicationLayer(m_flatBufferBuilder, flatBufferMultiplicationBaseLayer);
141
142 // Add the AnyLayer to the FlatBufferLayers
143 CreateAnyLayer(flatBufferMultiplicationLayer.o, serializer::Layer::Layer_MultiplicationLayer);
144}
145
Saoirse Stewart263829c2019-02-19 15:54:14 +0000146// Build FlatBuffer for Reshape Layer
147void SerializerVisitor::VisitReshapeLayer(const IConnectableLayer* layer,
148 const armnn::ReshapeDescriptor& reshapeDescriptor,
149 const char* name)
150{
151 // Create FlatBuffer BaseLayer
152 auto flatBufferReshapeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Reshape);
153
154 std::vector<unsigned int> targetShape;
155 for (unsigned int i =0; i < reshapeDescriptor.m_TargetShape.GetNumDimensions(); i++)
156 {
157 targetShape.push_back(reshapeDescriptor.m_TargetShape[i]);
158 }
159
160 auto flatBufferReshapeDesc = serializer::CreateReshapeDescriptor(m_flatBufferBuilder,
161 m_flatBufferBuilder.CreateVector(targetShape));
162
163 // Create the FlatBuffer ReshapeLayer
164 auto flatBufferReshapeLayer = serializer::CreateReshapeLayer(m_flatBufferBuilder, flatBufferReshapeBaseLayer,
165 flatBufferReshapeDesc);
166
167 // Add the AnyLayer to the FlatBufferLayers
168 CreateAnyLayer(flatBufferReshapeLayer.o, serializer::Layer::Layer_ReshapeLayer);
169}
170
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000171// Build FlatBuffer for Softmax Layer
172void SerializerVisitor::VisitSoftmaxLayer(const IConnectableLayer* layer,
173 const SoftmaxDescriptor& softmaxDescriptor,
174 const char* name)
175{
176 // Create FlatBuffer BaseLayer
177 auto flatBufferSoftmaxBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Softmax);
178
179 // Create the FlatBuffer SoftmaxDescriptor
180 auto flatBufferSoftmaxDesc =
181 serializer::CreateSoftmaxDescriptor(m_flatBufferBuilder, softmaxDescriptor.m_Beta);
182
183 // Create the FlatBuffer SoftmaxLayer
184 auto flatBufferSoftmaxLayer =
185 serializer::CreateSoftmaxLayer(m_flatBufferBuilder,
186 flatBufferSoftmaxBaseLayer,
187 flatBufferSoftmaxDesc);
188
189 CreateAnyLayer(flatBufferSoftmaxLayer.o, serializer::Layer::Layer_SoftmaxLayer);
190}
191
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000192void SerializerVisitor::VisitPooling2dLayer(const IConnectableLayer* layer,
193 const Pooling2dDescriptor& pooling2dDescriptor,
194 const char* name)
195{
196 auto fbPooling2dBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Pooling2d);
197 auto fbPooling2dDescriptor = serializer::CreatePooling2dDescriptor(
198 m_flatBufferBuilder,
199 GetFlatBufferPoolingAlgorithm(pooling2dDescriptor.m_PoolType),
200 pooling2dDescriptor.m_PadLeft,
201 pooling2dDescriptor.m_PadRight,
202 pooling2dDescriptor.m_PadTop,
203 pooling2dDescriptor.m_PadBottom,
204 pooling2dDescriptor.m_PoolWidth,
205 pooling2dDescriptor.m_PoolHeight,
206 pooling2dDescriptor.m_StrideX,
207 pooling2dDescriptor.m_StrideY,
208 GetFlatBufferOutputShapeRounding(pooling2dDescriptor.m_OutputShapeRounding),
209 GetFlatBufferPaddingMethod(pooling2dDescriptor.m_PaddingMethod),
210 GetFlatBufferDataLayout(pooling2dDescriptor.m_DataLayout));
211
212 auto fbPooling2dLayer = serializer::CreatePooling2dLayer(m_flatBufferBuilder,
213 fbPooling2dBaseLayer,
214 fbPooling2dDescriptor);
215
216 CreateAnyLayer(fbPooling2dLayer.o, serializer::Layer::Layer_Pooling2dLayer);
217}
218
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000219fb::Offset<serializer::LayerBase> SerializerVisitor::CreateLayerBase(const IConnectableLayer* layer,
220 const serializer::LayerType layerType)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000221{
222 std::vector<fb::Offset<serializer::InputSlot>> inputSlots = CreateInputSlots(layer);
223 std::vector<fb::Offset<serializer::OutputSlot>> outputSlots = CreateOutputSlots(layer);
224
225 return serializer::CreateLayerBase(m_flatBufferBuilder,
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000226 GetSerializedId(layer->GetGuid()),
Mike Kelly8c1701a2019-02-11 17:01:27 +0000227 m_flatBufferBuilder.CreateString(layer->GetName()),
228 layerType,
229 m_flatBufferBuilder.CreateVector(inputSlots),
230 m_flatBufferBuilder.CreateVector(outputSlots));
231}
232
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000233void SerializerVisitor::CreateAnyLayer(const flatbuffers::Offset<void>& layer, const serializer::Layer serializerLayer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000234{
235 auto anyLayer = armnn::armnnSerializer::CreateAnyLayer(m_flatBufferBuilder,
236 serializerLayer,
237 layer);
238 m_serializedLayers.push_back(anyLayer);
239}
240
Mike Kellya0766c32019-02-19 17:22:07 +0000241template <typename T>
242flatbuffers::Offset<flatbuffers::Vector<T>> SerializerVisitor::CreateDataVector(const void* memory, unsigned int size)
243{
244 const T* buffer = reinterpret_cast<const T*>(memory);
245 std::vector<T> vector(buffer, buffer + (size / sizeof(T)));
246 auto fbVector = m_flatBufferBuilder.CreateVector(vector);
247 return fbVector;
248}
249
250flatbuffers::Offset<serializer::ConstTensor> SerializerVisitor::CreateConstTensorInfo(const ConstTensor& constTensor)
251{
252 TensorInfo tensorInfo = constTensor.GetInfo();
253
254 // Get the dimensions
255 std::vector<unsigned int> shape;
256
257 for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
258 {
259 shape.push_back(tensorInfo.GetShape()[dim]);
260 }
261
262 // Create FlatBuffer TensorInfo
263 auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
264 m_flatBufferBuilder.CreateVector(shape),
265 GetFlatBufferDataType(tensorInfo.GetDataType()),
266 tensorInfo.GetQuantizationScale(),
267 tensorInfo.GetQuantizationOffset());
268 flatbuffers::Offset<void> fbPayload;
269
270 switch (tensorInfo.GetDataType())
271 {
272 case DataType::Float32:
273 case DataType::Signed32:
274 {
275 auto fbVector = CreateDataVector<int32_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
276 flatbuffers::Offset<serializer::IntData> flatBuffersData = serializer::CreateIntData(
277 m_flatBufferBuilder,
278 fbVector);
279 fbPayload = flatBuffersData.o;
280 break;
281 }
282 case DataType::Float16:
283 {
284 auto fbVector = CreateDataVector<int16_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
285 flatbuffers::Offset<serializer::ShortData> flatBuffersData = serializer::CreateShortData(
286 m_flatBufferBuilder,
287 fbVector);
288 fbPayload = flatBuffersData.o;
289 break;
290 }
291 case DataType::QuantisedAsymm8:
292 case DataType::Boolean:
293 default:
294 {
295 auto fbVector = CreateDataVector<int8_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
296 flatbuffers::Offset<serializer::ByteData> flatBuffersData = serializer::CreateByteData(
297 m_flatBufferBuilder,
298 fbVector);
299 fbPayload = flatBuffersData.o;
300 }
301 }
302 flatbuffers::Offset<serializer::ConstTensor> flatBufferConstTensor = serializer::CreateConstTensor(
303 m_flatBufferBuilder,
304 flatBufferTensorInfo,
305 GetFlatBufferConstTensorData(tensorInfo.GetDataType()),
306 fbPayload);
307 return flatBufferConstTensor;
308}
309
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000310std::vector<fb::Offset<serializer::InputSlot>> SerializerVisitor::CreateInputSlots(const IConnectableLayer* layer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000311{
Mike Kellya0766c32019-02-19 17:22:07 +0000312 std::vector<fb::Offset<serializer::InputSlot>> inputSlots;
Mike Kelly8c1701a2019-02-11 17:01:27 +0000313
314 // Get the InputSlots
315 for (unsigned int slotIndex = 0; slotIndex<layer->GetNumInputSlots(); ++slotIndex)
316 {
317 const IInputSlot& inputSlot = layer->GetInputSlot(slotIndex);
318
319 // Get the Connection for the InputSlot
320 const IOutputSlot* connection = inputSlot.GetConnection();
321
322 // Create FlatBuffer Connection
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000323 serializer::Connection conn(GetSerializedId(inputSlot.GetConnection()->GetOwningLayerGuid()),
324 connection->CalculateIndexOnOwner());
Mike Kelly8c1701a2019-02-11 17:01:27 +0000325 // Create FlatBuffer InputSlot
326 inputSlots.push_back(serializer::CreateInputSlot(m_flatBufferBuilder, slotIndex, &conn));
327 }
328 return inputSlots;
329}
330
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000331std::vector<fb::Offset<serializer::OutputSlot>> SerializerVisitor::CreateOutputSlots(const IConnectableLayer* layer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000332{
333 std::vector<fb::Offset<serializer::OutputSlot>> outputSlots;
334
335 // Get the OutputSlots
336 for (unsigned int slotIndex = 0; slotIndex < layer->GetNumOutputSlots(); ++slotIndex)
337 {
338 const IOutputSlot& outputSlot = layer->GetOutputSlot(slotIndex);
339 const TensorInfo& tensorInfo = outputSlot.GetTensorInfo();
340
341 // Get the dimensions
342 std::vector<unsigned int> shape;
343 for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
344 {
345 shape.push_back(tensorInfo.GetShape()[dim]);
346 }
347
348 // Create FlatBuffer TensorInfo
349 auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
350 m_flatBufferBuilder.CreateVector(shape),
351 GetFlatBufferDataType(tensorInfo.GetDataType()),
352 tensorInfo.GetQuantizationScale(),
353 tensorInfo.GetQuantizationOffset());
354
355 // Create FlatBuffer Outputslot
356 outputSlots.push_back(serializer::CreateOutputSlot(m_flatBufferBuilder,
357 slotIndex,
358 flatBufferTensorInfo));
359 }
360 return outputSlots;
361}
362
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000363
364ISerializer* ISerializer::CreateRaw()
365{
366 return new Serializer();
367}
368
369ISerializerPtr ISerializer::Create()
370{
371 return ISerializerPtr(CreateRaw(), &ISerializer::Destroy);
372}
373
374void ISerializer::Destroy(ISerializer* serializer)
375{
376 delete serializer;
377}
378
379void Serializer::Serialize(const INetwork& inNetwork)
380{
381 // Iterate through to network
382 inNetwork.Accept(m_SerializerVisitor);
383 flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerVisitor.GetFlatBufferBuilder();
384
385 // Create FlatBuffer SerializedGraph
386 auto serializedGraph = serializer::CreateSerializedGraph(
387 fbBuilder,
388 fbBuilder.CreateVector(m_SerializerVisitor.GetSerializedLayers()),
389 fbBuilder.CreateVector(m_SerializerVisitor.GetInputIds()),
390 fbBuilder.CreateVector(m_SerializerVisitor.GetOutputIds()));
391
392 // Serialize the graph
393 fbBuilder.Finish(serializedGraph);
394}
395
396bool Serializer::SaveSerializedToStream(std::ostream& stream)
397{
398 flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerVisitor.GetFlatBufferBuilder();
399
Nattapat Chaimanowong7b53b692019-02-12 14:38:31 +0000400 auto bytesToWrite = boost::numeric_cast<std::streamsize>(fbBuilder.GetSize());
401 stream.write(reinterpret_cast<const char*>(fbBuilder.GetBufferPointer()), bytesToWrite);
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000402 return !stream.bad();
403}
404
Matteo Martincighec333912019-02-13 15:12:39 +0000405} // namespace armnnSerializer