ArmNN
 24.02
NetworkUtils.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022 Arm Ltd and Contributors. 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 UpdateOutputSlotToFp32(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  UpdateOutputSlotToFp32(*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, bool toFile)
113 {
114  std::vector<DebugLayer*> debugLayers;
115  debugLayers.reserve(layer.GetNumOutputSlots());
116 
117  // Connect a DebugLayer to each output slot of the layer
118  uint32_t outputSlotIdx = 0;
119  for (auto outputSlot = layer.BeginOutputSlots(); outputSlot != layer.EndOutputSlots(); ++outputSlot)
120  {
121  const std::string debugName = std::string("DebugLayerAfter") + layer.GetNameStr() + "_" +
122  std::to_string(outputSlotIdx);
123 
124  DebugLayer* debugLayer =
125  graph.InsertNewLayer<DebugLayer>(*outputSlot, debugName.c_str(), toFile);
126 
127  // Sets output tensor info for the debug layer.
128  ARMNN_ASSERT(debugLayer->GetInputSlot(0).GetConnectedOutputSlot() == &(*outputSlot));
129  TensorInfo debugInfo = debugLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
130 
131  debugLayer->GetOutputSlot().SetTensorInfo(debugInfo);
132 
133  // NOTE: It is OK to do this because DebugLayer is only supported on CpuRef
134  debugLayer->SetBackendId(Compute::CpuRef);
135 
136  debugLayers.emplace_back(debugLayer);
137 
138  ++outputSlotIdx;
139  }
140 
141  return debugLayers;
142 }
143 
144 } // namespace armnn
ARMNN_ASSERT
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn::InsertConvertFp16ToFp32LayersBefore
std::vector< ConvertFp16ToFp32Layer * > InsertConvertFp16ToFp32LayersBefore(Graph &graph, Layer &layer, bool expectCorrectInputType)
Definition: NetworkUtils.cpp:40
SubgraphViewSelector.hpp
armnn::OutputSlot::GetTensorInfo
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:92
armnn::Compute::CpuRef
@ CpuRef
CPU Execution: Reference C++ kernels.
armnn::OutputSlot
Definition: Layer.hpp:100
armnn::OutputSlot::SetTensorInfo
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:87
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::TensorInfo::SetDataType
void SetDataType(DataType type)
Definition: Tensor.hpp:201
armnn::DataType::Float32
@ Float32
armnn::Layer::GetOutputSlot
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:339
NetworkUtils.hpp
BackendRegistry.hpp
armnn::Layer::GetInputSlot
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
armnn::Layer::GetName
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:332
armnn::Layer
Definition: Layer.hpp:230
armnn::DataType::Float16
@ Float16
armnn::ConvertFp32ToFp16Layer
This layer converts data type Float 32 to Float 16.
Definition: ConvertFp32ToFp16Layer.hpp:13
armnn::ConvertFp16ToFp32Layer
This layer converts data type Float 16 to Float 32.
Definition: ConvertFp16ToFp32Layer.hpp:14
armnn::InsertConvertFp32ToFp16LayersAfter
std::vector< ConvertFp32ToFp16Layer * > InsertConvertFp32ToFp16LayersAfter(Graph &graph, Layer &layer)
Definition: NetworkUtils.cpp:79
armnn::Layer::EndInputSlots
std::vector< InputSlot >::iterator EndInputSlots()
Definition: Layer.hpp:263
armnn::Layer::GetNumOutputSlots
unsigned int GetNumOutputSlots() const override
Returns the number of connectable output slots.
Definition: Layer.hpp:335
armnn::InsertDebugLayerAfter
std::vector< DebugLayer * > InsertDebugLayerAfter(Graph &graph, Layer &layer, bool toFile)
Definition: NetworkUtils.cpp:112
armnn::Layer::BeginInputSlots
std::vector< InputSlot >::iterator BeginInputSlots()
Definition: Layer.hpp:262
armnn::TensorInfo::GetDataType
DataType GetDataType() const
Definition: Tensor.hpp:200
armnn::Layer::GetNameStr
const std::string & GetNameStr() const
Definition: Layer.hpp:240
armnn::Layer::GetNumInputSlots
unsigned int GetNumInputSlots() const override
Returns the number of connectable input slots.
Definition: Layer.hpp:334
armnn::Layer::BeginOutputSlots
std::vector< OutputSlot >::iterator BeginOutputSlots()
Definition: Layer.hpp:266
armnn::DebugLayer
This layer visualizes the data flowing through the network.
Definition: DebugLayer.hpp:13
armnn::InputSlot::GetConnectedOutputSlot
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
Exceptions.hpp
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::Layer::SetBackendId
void SetBackendId(const BackendId &id) override
Set the backend of the IConnectableLayer.
Definition: Layer.hpp:291
armnn::Layer::EndOutputSlots
std::vector< OutputSlot >::iterator EndOutputSlots()
Definition: Layer.hpp:267
armnn::Graph
Definition: Graph.hpp:30
armnn::Graph::InsertNewLayer
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
Definition: Graph.hpp:471