2 * Copyright (c) 2018 ARM Limited.
4 * SPDX-License-Identifier: MIT
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:
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
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
24 #include "arm_compute/graph/detail/ExecutionHelpers.h"
26 #include "arm_compute/graph/Graph.h"
27 #include "arm_compute/graph/GraphContext.h"
28 #include "arm_compute/graph/GraphManager.h"
29 #include "arm_compute/graph/Tensor.h"
30 #include "arm_compute/graph/backends/BackendRegistry.h"
38 void default_initialize_backends()
40 for(const auto &backend : backends::BackendRegistry::get().backends())
42 backend.second->initialize_backend();
46 void validate_all_nodes(Graph &g)
48 auto &nodes = g.nodes();
51 for(auto &node : nodes)
55 Target assigned_target = node->assigned_target();
56 auto backend = backends::BackendRegistry::get().find_backend(assigned_target);
57 ARM_COMPUTE_ERROR_ON_MSG(!backend, "Requested backend doesn't exist!");
58 Status status = backend->validate_node(*node);
59 ARM_COMPUTE_ERROR_ON_MSG(!bool(status), status.error_description().c_str());
64 void configure_all_tensors(Graph &g)
66 auto &tensors = g.tensors();
68 for(auto &tensor : tensors)
72 Target target = tensor->desc().target;
73 auto backend = backends::BackendRegistry::get().find_backend(target);
74 ARM_COMPUTE_ERROR_ON_MSG(!backend, "Requested backend doesn't exist!");
75 auto handle = backend->create_tensor(*tensor);
76 ARM_COMPUTE_ERROR_ON_MSG(!backend, "Couldn't create backend handle!");
77 tensor->set_handle(std::move(handle));
82 void allocate_all_input_tensors(INode &node)
84 for(unsigned int i = 0; i < node.num_inputs(); ++i)
86 Tensor *tensor = node.input(i);
87 if(tensor != nullptr && !tensor->bound_edges().empty())
89 ARM_COMPUTE_ERROR_ON_MSG(!tensor->handle(), "Tensor handle is not configured!");
90 tensor->handle()->allocate();
95 void allocate_all_output_tensors(INode &node)
97 for(unsigned int i = 0; i < node.num_outputs(); ++i)
99 Tensor *tensor = node.output(i);
100 if(tensor != nullptr && !tensor->bound_edges().empty())
102 ARM_COMPUTE_ERROR_ON_MSG(!tensor->handle(), "Tensor handle is not configured!");
103 tensor->handle()->allocate();
108 void allocate_const_tensors(Graph &g)
110 for(auto &node : g.nodes())
116 case NodeType::Const:
117 case NodeType::Input:
118 allocate_all_output_tensors(*node);
120 case NodeType::Output:
121 allocate_all_input_tensors(*node);
129 void allocate_all_tensors(Graph &g)
131 auto &tensors = g.tensors();
133 for(auto &tensor : tensors)
135 if(tensor && !tensor->bound_edges().empty() && tensor->handle() != nullptr && tensor->handle()->tensor().info()->is_resizable() && tensor->handle()->tensor().is_used())
137 tensor->handle()->allocate();
142 ExecutionWorkload configure_all_nodes(Graph &g, GraphContext &ctx)
144 ExecutionWorkload workload;
148 auto &nodes = g.nodes();
151 for(auto &node : nodes)
155 Target assigned_target = node->assigned_target();
156 auto backend = backends::BackendRegistry::get().find_backend(assigned_target);
157 ARM_COMPUTE_ERROR_ON_MSG(!backend, "Requested backend doesn't exist!");
158 auto func = backend->configure_node(*node, ctx);
162 task.task = std::move(func);
163 task.node = node.get();
164 workload.tasks.push_back(std::move(task));
169 // Add inputs and outputs
170 for(auto &node : nodes)
172 if(node != nullptr && node->type() == NodeType::Input)
174 workload.inputs.push_back(node->output(0));
177 if(node != nullptr && node->type() == NodeType::Output)
179 workload.outputs.push_back(node->input(0));
187 void release_unused_tensors(Graph &g)
189 for(auto &tensor : g.tensors())
191 if(tensor != nullptr && tensor->handle() != nullptr)
193 tensor->handle()->release_if_unused();
198 void call_tensor_accessor(Tensor *tensor)
200 ARM_COMPUTE_ERROR_ON(!tensor);
201 tensor->call_accessor();
204 void call_all_const_node_accessors(Graph &g)
206 auto &nodes = g.nodes();
208 for(auto &node : nodes)
210 if(node != nullptr && node->type() == NodeType::Const)
212 call_tensor_accessor(node->output(0));
217 void call_all_input_node_accessors(ExecutionWorkload &workload)
219 for(auto &input : workload.inputs)
223 input->call_accessor();
228 void prepare_all_tasks(ExecutionWorkload &workload)
230 ARM_COMPUTE_ERROR_ON(workload.graph == nullptr);
231 for(auto &task : workload.tasks)
234 release_unused_tensors(*workload.graph);
238 void call_all_tasks(ExecutionWorkload &workload)
240 ARM_COMPUTE_ERROR_ON(workload.ctx == nullptr);
242 // Acquire memory for the transition buffers
243 for(auto &mm_ctx : workload.ctx->memory_managers())
245 if(mm_ctx.second.cross_group != nullptr)
247 mm_ctx.second.cross_group->acquire();
252 for(auto &task : workload.tasks)
257 // Release memory for the transition buffers
258 for(auto &mm_ctx : workload.ctx->memory_managers())
260 if(mm_ctx.second.cross_group != nullptr)
262 mm_ctx.second.cross_group->release();
267 void call_all_output_node_accessors(ExecutionWorkload &workload)
269 for(auto &output : workload.outputs)
271 if(output != nullptr)
273 output->call_accessor();
277 } // namespace detail
279 } // namespace arm_compute