Imported Upstream version 1.9.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / exec / Execution.cc
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "exec/Execution.h"
18
19 #include "util/logging.h"
20
21 namespace onert
22 {
23 namespace exec
24 {
25
26 Execution::Execution(const std::shared_ptr<ExecutorMap> &executors) : _executors{executors}
27 {
28   assert(executors != nullptr);
29   assert(executors->at(ir::SubgraphIndex{0}) != nullptr);
30   const auto &primary_subg = primary_subgraph();
31   _io_desc.inputs.resize(primary_subg.getInputs().size());
32   _io_desc.outputs.resize(primary_subg.getOutputs().size());
33 }
34
35 void Execution::changeInputShape(const ir::IOIndex &index, const ir::Shape &new_shape)
36 {
37   // This should be called BEFORE setInput.
38   if (_io_desc.inputs.at(index.value()) != 0)
39     throw std::runtime_error("Error in calling order");
40
41   // This will be used later to set input tensor dynamic
42   // Note that 'compiled' model will not be updated with new_shape
43   // but new_shape will change model input shape while 'running' the model
44   _io_desc.dynamic_input_shapes[index] = new_shape;
45 }
46
47 // TODO Remove default parameter
48 void Execution::setInput(const ir::IOIndex &index, const void *buffer, size_t length,
49                          ir::Layout layout)
50 {
51   const auto input_index = primary_subgraph().getInputs().at(index);
52   const auto info = primary_subgraph().operands().at(input_index).info();
53
54   // TODO handle when (!buffer && length != 0) : setting the input as an optional tensor
55
56   // check if size enough for input is passed
57   // if input_shape_sig is set, input_shape_sig overrides shape in info
58   // note: input_shape_sig contains shape passed by nnfw_set_input_tensorinfo()
59   {
60     auto input_shape_sig = _io_desc.dynamic_input_shapes.find(index);
61     auto size_required = (input_shape_sig != _io_desc.dynamic_input_shapes.end())
62                              ? input_shape_sig->second.num_elements() *
63                                    onert::ir::sizeOfDataType(info.typeInfo().type())
64                              : info.total_size();
65
66     if (length < size_required)
67     {
68       throw std::runtime_error{"Too small length"};
69     }
70   }
71
72   _io_desc.inputs.at(index.value()) = std::make_unique<InputDesc>(info, buffer, length, layout);
73 }
74
75 // TODO Remove default parameter
76 void Execution::setInput(const ir::IOIndex &index, const ir::TypeInfo &type, const ir::Shape &shape,
77                          const void *buffer, size_t length, ir::Layout layout)
78 {
79   auto info = ir::OperandInfo::createStaticInfo(shape, type);
80
81   if (length < info.total_size())
82   {
83     throw std::runtime_error{"Too small length"};
84   }
85
86   _io_desc.inputs.at(index.value()) = std::make_unique<InputDesc>(info, buffer, length, layout);
87 }
88
89 // TODO Remove default parameter
90 void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length, ir::Layout layout)
91 {
92   const auto output_index = primary_subgraph().getOutputs().at(index);
93   const auto info = primary_subgraph().operands().at(output_index).info();
94
95   if (length < info.total_size())
96   {
97     throw std::runtime_error{"Too small length"};
98   }
99
100   _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(info, buffer, length, layout);
101 }
102
103 // TODO Remove default parameter
104 void Execution::setOutput(const ir::IOIndex &index, const ir::TypeInfo &type,
105                           const ir::Shape &shape, void *buffer, size_t length, ir::Layout layout)
106 {
107   auto info = ir::OperandInfo::createStaticInfo(shape, type);
108
109   if (length < info.total_size())
110   {
111     throw std::runtime_error{"Too small length"};
112   }
113
114   _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(info, buffer, length, layout);
115 }
116
117 void Execution::setInputLayout(const ir::IOIndex &index, ir::Layout layout)
118 {
119   const auto &input_desc = _io_desc.inputs.at(index.value());
120   _io_desc.inputs.at(index.value()) =
121       std::make_unique<InputDesc>(input_desc->info, input_desc->buffer, input_desc->size, layout);
122 }
123
124 void Execution::setOutputLayout(const ir::IOIndex &index, ir::Layout layout)
125 {
126   const auto &output_desc = _io_desc.outputs.at(index.value());
127   _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(
128       output_desc->info, output_desc->buffer, output_desc->size, layout);
129 }
130
131 void Execution::execute()
132 {
133   VERBOSE(Execution) << "Start execution" << std::endl;
134
135   primary_executor()->execute(_io_desc);
136   finished = true;
137
138   VERBOSE(Execution) << "Execution finished" << std::endl;
139 }
140
141 void Execution::startExecute()
142 {
143   VERBOSE(Execution) << "Create asynchronous execution thread" << std::endl;
144
145   _exec_thread = std::make_unique<std::thread>(&Execution::execute, this);
146 }
147
148 void Execution::waitFinish()
149 {
150   VERBOSE(Execution) << "Wait to finish execution" << std::endl;
151
152   _exec_thread->join();
153   finished = true;
154 }
155
156 bool Execution::isFinished(void) const { return finished; }
157
158 ir::Shape Execution::getInputShape(ir::IOIndex ind) const
159 {
160   auto itr = _io_desc.dynamic_input_shapes.find(ind);
161   if (itr == _io_desc.dynamic_input_shapes.end())
162   {
163     auto operand_idx = primary_subgraph().getInputs().at(ind.value());
164     return primary_subgraph().operands().at(operand_idx).shape();
165   }
166   else
167   {
168     return itr->second;
169   }
170 }
171
172 ir::Shape Execution::getOutputShape(ir::IOIndex ind) const
173 {
174   if (!isFinished())
175     throw std::runtime_error("Cannot get output shape before execution is finished");
176
177   const auto &output_desc = _io_desc.outputs.at(ind.value());
178
179   return output_desc->info.shape();
180 }
181
182 } // namespace exec
183 } // namespace onert