Compute Library
 23.08
Utils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
25 
29 
30 namespace arm_compute
31 {
32 namespace graph
33 {
35 {
37 }
38 
40 {
42  {
43  return Target::NEON;
44  }
46  {
47  return Target::CL;
48  }
49  ARM_COMPUTE_ERROR("No backend exists!");
50 }
51 
53 {
54  auto &nodes = g.nodes();
55  for(auto &node : nodes)
56  {
57  if(node)
58  {
59  node->set_assigned_target(target);
60  }
61  }
62 
63  auto &tensors = g.tensors();
64  for(auto &tensor : tensors)
65  {
66  if(tensor)
67  {
68  tensor->desc().target = target;
69  }
70  }
71 }
72 
74 {
75  ARM_COMPUTE_UNUSED(target);
76  PassManager pm;
77 
78  // Passes that mutate graph IR
79  if(cfg.use_synthetic_type)
80  {
81  switch(cfg.synthetic_type)
82  {
83  case DataType::QASYMM8:
85  {
86  pm.append(std::make_unique<SyntheticDataTypeMutator>(cfg.synthetic_type));
87  break;
88  }
89  default:
90  {
91  ARM_COMPUTE_ERROR("Unsupported DataType for SyntheticDataTypeMutator");
92  break;
93  }
94  }
95  }
96  pm.append(std::make_unique<NodeFusionMutator>());
97  pm.append(std::make_unique<GroupedConvolutionMutator>());
98  pm.append(std::make_unique<InPlaceOperationMutator>());
99 
100  // Passes that mutate backend information
101  pm.append(std::make_unique<DepthConcatSubTensorMutator>());
102  pm.append(std::make_unique<SplitLayerSubTensorMutator>());
103  pm.append(std::make_unique<NodeExecutionMethodMutator>());
104 
105  return pm;
106 }
107 
109 {
110  for(const auto &backend : backends::BackendRegistry::get().backends())
111  {
112  if(backend.second->is_backend_supported())
113  {
114  backend.second->release_backend_context(ctx);
115  }
116  }
117 }
118 
120 {
121  for(const auto &backend : backends::BackendRegistry::get().backends())
122  {
123  if(backend.second->backend_allocator())
124  {
125  backend.second->sync();
126  }
127  }
128 }
129 
131 {
132  if(backends::BackendRegistry::get().contains(target))
133  {
134  const auto &backend = backends::BackendRegistry::get().find_backend(target);
135  if(backend->is_backend_supported())
136  {
137  backend->setup_backend_context(ctx);
138  }
139  }
140 }
141 
142 size_t get_dimension_size(const TensorDescriptor &descriptor, const DataLayoutDimension data_layout_dimension)
143 {
144  ARM_COMPUTE_ERROR_ON_MSG(descriptor.layout == DataLayout::UNKNOWN, "Cannot retrieve the dimension index for an unknown layout!");
145  return descriptor.shape[get_dimension_idx(descriptor.layout, data_layout_dimension)];
146 }
147 
148 size_t get_dimension_idx(DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
149 {
150  ARM_COMPUTE_ERROR_ON_MSG(data_layout == DataLayout::UNKNOWN, "Cannot retrieve the dimension index for an unknown layout!");
151 
152  /* Return the index based on the data layout
153  * [N C H W]
154  * [3 2 1 0]
155  * [N H W C]
156  */
157  switch(data_layout_dimension)
158  {
160  return (data_layout == DataLayout::NCHW) ? 2 : 0;
161  break;
163  return (data_layout == DataLayout::NCHW) ? 1 : 2;
164  break;
166  return (data_layout == DataLayout::NCHW) ? 0 : 1;
167  break;
169  return 3;
170  break;
171  default:
172  break;
173  }
174  ARM_COMPUTE_ERROR("Data layout index not supported!");
175 }
176 
177 std::vector<NodeIdxPair> get_driving_nodes(const INode &node)
178 {
179  std::vector<NodeIdxPair> driving_nodes;
180 
181  const Graph *g = node.graph();
182  ARM_COMPUTE_ERROR_ON(g == nullptr);
183 
184  for(auto &output_edge_id : node.output_edges())
185  {
186  auto output_edge = g->edge(output_edge_id);
187  if(output_edge != nullptr)
188  {
189  ARM_COMPUTE_ERROR_ON(output_edge->consumer() == nullptr);
190  driving_nodes.push_back({ output_edge->consumer_id(), output_edge->consumer_idx() });
191  }
192  }
193 
194  return driving_nodes;
195 }
196 
197 std::vector<NodeIdxPair> get_driver_nodes(const INode &node)
198 {
199  std::vector<NodeIdxPair> driver_nodes;
200 
201  const Graph *g = node.graph();
202  ARM_COMPUTE_ERROR_ON(g == nullptr);
203 
204  for(auto &input_edge_id : node.input_edges())
205  {
206  auto input_edge = g->edge(input_edge_id);
207  if(input_edge != nullptr)
208  {
209  ARM_COMPUTE_ERROR_ON(input_edge->producer() == nullptr);
210  driver_nodes.push_back({ input_edge->producer_id(), input_edge->producer_idx() });
211  }
212  }
213 
214  return driver_nodes;
215 }
216 
218 {
219  if(tensor != nullptr && tensor->handle() == nullptr)
220  {
221  Target target = tensor->desc().target;
223  std::unique_ptr<ITensorHandle> handle = backend.create_tensor(*tensor);
224  ARM_COMPUTE_ERROR_ON_MSG(!handle, "Couldn't create backend handle!");
225  tensor->set_handle(std::move(handle));
226  }
227 }
228 
229 } // namespace graph
230 } // namespace arm_compute
arm_compute::DataLayout::NCHW
@ NCHW
Num samples, channels, height, width.
arm_compute::graph::Graph::edge
const Edge * edge(EdgeID id) const
Get edge object given its id.
Definition: Graph.cpp:214
GraphMutators.h
arm_compute::graph::get_driving_nodes
std::vector< NodeIdxPair > get_driving_nodes(const INode &node)
Get the list of driving nodes of a given node.
Definition: Utils.cpp:177
arm_compute::graph::Target::CL
@ CL
OpenCL capable target device.
arm_compute::graph::force_target_to_graph
void force_target_to_graph(Graph &g, Target target)
Forces a single target to all graph constructs.
Definition: Utils.cpp:52
arm_compute::DataLayout
DataLayout
[DataLayout enum definition]
Definition: CoreTypes.h:109
arm_compute::DataLayoutDimension::CHANNEL
@ CHANNEL
channel
arm_compute::graph::backends::IDeviceBackend::is_backend_supported
virtual bool is_backend_supported()=0
Checks if an instantiated backend is actually supported.
arm_compute::DataLayoutDimension
DataLayoutDimension
[DataLayout enum definition]
Definition: CoreTypes.h:120
arm_compute::DataType::QASYMM8
@ QASYMM8
quantized, asymmetric fixed-point 8-bit number unsigned
arm_compute::graph::setup_requested_backend_context
void setup_requested_backend_context(GraphContext &ctx, Target target)
Setups requested backend context if it exists, is supported and hasn't been initialized already.
Definition: Utils.cpp:130
arm_compute::graph::PassManager
Pass manager.
Definition: PassManager.h:43
arm_compute::graph::backends::IDeviceBackend
Device backend interface.
Definition: IDeviceBackend.h:48
arm_compute::graph::Target::NEON
@ NEON
Arm® Neon™ capable target device.
ARM_COMPUTE_ERROR
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:353
GraphContext.h
arm_compute::graph::INode::output_edges
const std::set< EdgeID > & output_edges() const
Returns output edge set.
Definition: INode.cpp:133
arm_compute::graph::Tensor
Tensor object.
Definition: Tensor.h:41
arm_compute::graph::get_dimension_size
size_t get_dimension_size(const TensorDescriptor &descriptor, const DataLayoutDimension data_layout_dimension)
Get size of a tensor's given dimension depending on its layout.
Definition: Utils.cpp:142
arm_compute::DataLayoutDimension::WIDTH
@ WIDTH
width
arm_compute::graph::backends::BackendRegistry::contains
bool contains(Target target) const
Checks if a backend for a given target exists.
Definition: BackendRegistry.cpp:59
arm_compute::test::validation::data_layout
const auto data_layout
Definition: ConvolutionLayer.cpp:406
arm_compute::graph::GraphConfig
Graph configuration structure.
Definition: Types.h:88
arm_compute::graph::get_driver_nodes
std::vector< NodeIdxPair > get_driver_nodes(const INode &node)
Get the list of driver nodes of a given node.
Definition: Utils.cpp:197
ARM_COMPUTE_ERROR_ON
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:467
arm_compute::graph::Target
Target
Definition: Types.h:104
arm_compute::DataLayoutDimension::HEIGHT
@ HEIGHT
height
ARM_COMPUTE_ERROR_ON_MSG
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:457
arm_compute::graph::INode
Node interface.
Definition: INode.h:46
arm_compute::graph::TensorDescriptor::layout
DataLayout layout
Data layout.
Definition: TensorDescriptor.h:111
arm_compute::DataType::QASYMM8_SIGNED
@ QASYMM8_SIGNED
quantized, asymmetric fixed-point 8-bit number signed
arm_compute::graph::backends::IDeviceBackend::create_tensor
virtual std::unique_ptr< ITensorHandle > create_tensor(const Tensor &tensor)=0
Create a backend Tensor.
arm_compute::graph::Graph::tensors
std::vector< std::unique_ptr< Tensor > > & tensors()
Returns tensors of graph.
Definition: Graph.cpp:194
arm_compute::graph::is_target_supported
bool is_target_supported(Target target)
Checks if a specific target is supported.
Definition: Utils.cpp:34
arm_compute::graph::TensorDescriptor::shape
TensorShape shape
Tensor shape.
Definition: TensorDescriptor.h:109
ARM_COMPUTE_UNUSED
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
tensor
CLTensor * tensor
Pointer to the auxiliary tensor.
Definition: ClWorkloadRuntime.cpp:66
arm_compute::graph::configure_tensor
void configure_tensor(Tensor *tensor)
Configures tensor.
Definition: Utils.cpp:217
BackendRegistry.h
arm_compute::graph::INode::input_edges
const std::vector< EdgeID > & input_edges() const
Returns input edge set.
Definition: INode.cpp:128
arm_compute::graph::GraphConfig::synthetic_type
DataType synthetic_type
The data type of the synthetic graph
Definition: Types.h:95
arm_compute::graph::get_dimension_idx
size_t get_dimension_idx(DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
Get index of a tensor's given dimension depending on its layout.
Definition: Utils.cpp:148
arm_compute::graph::create_default_pass_manager
PassManager create_default_pass_manager(Target target, const GraphConfig &cfg)
Creates a default PassManager.
Definition: Utils.cpp:73
arm_compute::graph::get_default_target
Target get_default_target()
Returns default target for execution.
Definition: Utils.cpp:39
arm_compute
Copyright (c) 2017-2023 Arm Limited.
Definition: introduction.dox:24
arm_compute::graph::TensorDescriptor
Tensor metadata class.
Definition: TensorDescriptor.h:38
arm_compute::graph::backends::BackendRegistry::find_backend
IDeviceBackend * find_backend(Target target)
Finds a backend in the registry.
Definition: BackendRegistry.cpp:45
arm_compute::graph::backends::IDeviceBackend::setup_backend_context
virtual void setup_backend_context(GraphContext &ctx)=0
Setups the given graph context.
arm_compute::graph::sync_backends
void sync_backends()
Synchronize kernels execution on the backends.
Definition: Utils.cpp:119
arm_compute::graph::INode::graph
const Graph * graph() const
Returns node's Graph.
Definition: INode.cpp:113
arm_compute::graph::Graph
Graph class.
Definition: Graph.h:52
Utils.h
arm_compute::graph::GraphContext
Graph context.
Definition: GraphContext.h:57
arm_compute::graph::PassManager::append
void append(std::unique_ptr< IGraphMutator > pass, bool conditional=true)
Appends a mutation pass.
Definition: PassManager.cpp:47
arm_compute::DataLayout::UNKNOWN
@ UNKNOWN
Unknown data layout.
arm_compute::graph::release_default_graph_context
void release_default_graph_context(GraphContext &ctx)
Default releases the graph context if not done manually.
Definition: Utils.cpp:108
arm_compute::DataLayoutDimension::BATCHES
@ BATCHES
batches
arm_compute::graph::backends::BackendRegistry::get_backend
IDeviceBackend & get_backend(Target target)
Get a backend from the registry.
Definition: BackendRegistry.cpp:51
arm_compute::graph::Graph::nodes
const std::vector< NodeID > & nodes(NodeType type)
Returns graph input nodes.
Definition: Graph.cpp:174
arm_compute::graph::backends::BackendRegistry::get
static BackendRegistry & get()
Gets backend registry instance.
Definition: BackendRegistry.cpp:39
arm_compute::graph::GraphConfig::use_synthetic_type
bool use_synthetic_type
Convert graph to a synthetic graph for a data type.
Definition: Types.h:94