ArmNN
 20.02
NetworkUtils.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "NetworkUtils.hpp"
7 
9 
10 #include <armnn/Exceptions.hpp>
12 
13 namespace armnn
14 {
15 
16 namespace
17 {
18 
19 void UpdateOutputSlotFp16ToFp32(OutputSlot& outputSlot)
20 {
21  const TensorInfo& origTensorInfo = outputSlot.GetTensorInfo();
22  TensorInfo newTensorInfo(origTensorInfo);
23  newTensorInfo.SetDataType(DataType::Float32);
24  outputSlot.SetTensorInfo(newTensorInfo);
25 }
26 
27 void ChangeOutputFp16ToFp32(Layer& layer)
28 {
29  for (auto&& outputSlot = layer.BeginOutputSlots(); outputSlot != layer.EndOutputSlots(); ++outputSlot)
30  {
31  if (outputSlot->GetTensorInfo().GetDataType() == DataType::Float16)
32  {
33  UpdateOutputSlotFp16ToFp32(*outputSlot);
34  }
35  }
36 }
37 
38 } // anonymous namespace
39 
40 std::vector<ConvertFp16ToFp32Layer*> InsertConvertFp16ToFp32LayersBefore(Graph& graph,
41  Layer& layer,
42  bool expectCorrectInputType)
43 {
44  std::vector<ConvertFp16ToFp32Layer*> convertLayers;
45  convertLayers.reserve(layer.GetNumInputSlots());
46 
47  // Insert a ConvertFp16ToFp32Layer before each input slot
48  for (auto&& inputSlot = layer.BeginInputSlots(); inputSlot != layer.EndInputSlots(); ++inputSlot)
49  {
50  bool allowInsert = true;
51  if (expectCorrectInputType)
52  {
53  // Only insert ConvertFp16ToFp32Layer before FP16 input slots
54  OutputSlot* connectedOutputSlot = inputSlot->GetConnectedOutputSlot();
55  allowInsert =
56  connectedOutputSlot && connectedOutputSlot->GetTensorInfo().GetDataType() == DataType::Float16;
57  }
58 
59  if (allowInsert)
60  {
61  const std::string name =
62  std::string("convert_fp16_to_fp32-" + std::to_string(inputSlot->GetSlotIndex()) + "-") +
63  layer.GetName();
64  ConvertFp16ToFp32Layer* convertLayer =
65  graph.InsertNewLayer<ConvertFp16ToFp32Layer>(*inputSlot, name.c_str());
66 
67  TensorInfo convertInfo = convertLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
68  convertInfo.SetDataType(DataType::Float32);
69 
70  convertLayer->GetOutputSlot().SetTensorInfo(convertInfo);
71 
72  convertLayers.emplace_back(convertLayer);
73  }
74  }
75 
76  return convertLayers;
77 }
78 
79 std::vector<ConvertFp32ToFp16Layer*> InsertConvertFp32ToFp16LayersAfter(Graph& graph, Layer& layer)
80 {
81  const unsigned int numOutputSlots = layer.GetNumOutputSlots();
82 
83  std::vector<ConvertFp32ToFp16Layer*> convertLayers;
84  convertLayers.reserve(numOutputSlots);
85 
86  // Update FP16 output slots to FP32 on current layer
87  ChangeOutputFp16ToFp32(layer);
88 
89  // Insert a ConvertFp32ToFp16Layer after each FP32 output slot
90  for (unsigned int slotIndex = 0u; slotIndex < numOutputSlots; ++slotIndex)
91  {
92  OutputSlot& outputSlot = layer.GetOutputSlot(slotIndex);
93  if(outputSlot.GetTensorInfo().GetDataType() == DataType::Float32)
94  {
95  const std::string name =
96  std::string("convert_fp32_to_fp16-" + std::to_string(slotIndex) + "-") + layer.GetName();
97  ConvertFp32ToFp16Layer* convertLayer =
98  graph.InsertNewLayer<ConvertFp32ToFp16Layer>(outputSlot, name.c_str());
99 
100  TensorInfo convertInfo = convertLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
101  convertInfo.SetDataType(DataType::Float16);
102 
103  convertLayer->GetOutputSlot().SetTensorInfo(convertInfo);
104 
105  convertLayers.emplace_back(convertLayer);
106  }
107  }
108 
109  return convertLayers;
110 }
111 
112 std::vector<DebugLayer*> InsertDebugLayerAfter(Graph& graph, Layer& layer)
113 {
114  std::vector<DebugLayer*> debugLayers;
115  debugLayers.reserve(layer.GetNumOutputSlots());
116 
117  // Connect a DebugLayer to each output slot of the layer
118  for (auto outputSlot = layer.BeginOutputSlots(); outputSlot != layer.EndOutputSlots(); ++outputSlot)
119  {
120  const std::string debugName = std::string("DebugLayerAfter") + layer.GetNameStr();
121 
122  DebugLayer* debugLayer =
123  graph.InsertNewLayer<DebugLayer>(*outputSlot, debugName.c_str());
124 
125  // Sets output tensor info for the debug layer.
126  BOOST_ASSERT(debugLayer->GetInputSlot(0).GetConnectedOutputSlot() == &(*outputSlot));
127  TensorInfo debugInfo = debugLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
128 
129  debugLayer->GetOutputSlot().SetTensorInfo(debugInfo);
130 
131  // NOTE: It is OK to do this because DebugLayer is only supported on CpuRef
132  debugLayer->SetBackendId(Compute::CpuRef);
133 
134  debugLayers.emplace_back(debugLayer);
135  }
136 
137  return debugLayers;
138 }
139 
140 } // namespace armnn
std::vector< InputSlot >::iterator EndInputSlots()
Definition: Layer.hpp:236
std::vector< ConvertFp32ToFp16Layer * > InsertConvertFp32ToFp16LayersAfter(Graph &graph, Layer &layer)
std::vector< ConvertFp16ToFp32Layer * > InsertConvertFp16ToFp32LayersBefore(Graph &graph, Layer &layer, bool expectCorrectInputType)
unsigned int GetNumInputSlots() const override
Returns the number of connectable input slots.
Definition: Layer.hpp:307
CPU Execution: Reference C++ kernels.
This layer converts data type Float 16 to Float 32.
Copyright (c) 2020 ARM Limited.
void SetBackendId(const BackendId &id)
Definition: Layer.hpp:264
unsigned int GetNumOutputSlots() const override
Returns the number of connectable output slots.
Definition: Layer.hpp:308
std::vector< InputSlot >::iterator BeginInputSlots()
Definition: Layer.hpp:235
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:310
DataType GetDataType() const
Definition: Tensor.hpp:95
const std::string & GetNameStr() const
Definition: Layer.hpp:216
This layer visualizes the data flowing through the network.
Definition: DebugLayer.hpp:13
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:55
void SetDataType(DataType type)
Definition: Tensor.hpp:96
This layer converts data type Float 32 to Float 16.
std::vector< OutputSlot >::iterator BeginOutputSlots()
Definition: Layer.hpp:239
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:58
std::vector< OutputSlot >::iterator EndOutputSlots()
Definition: Layer.hpp:240
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:312
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:305
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
Definition: Graph.hpp:409
std::vector< DebugLayer * > InsertDebugLayerAfter(Graph &graph, Layer &layer)
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63