2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "exec/Execution.h"
19 #include "util/logging.h"
26 Execution::Execution(const std::shared_ptr<ExecutorMap> &executors) : _executors{executors}
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());
35 void Execution::changeInputShape(const ir::IOIndex &index, const ir::Shape &new_shape)
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");
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;
47 // TODO Remove default parameter
48 void Execution::setInput(const ir::IOIndex &index, const void *buffer, size_t length,
51 const auto input_index = primary_subgraph().getInputs().at(index);
52 const auto info = primary_subgraph().operands().at(input_index).info();
54 // TODO handle when (!buffer && length != 0) : setting the input as an optional tensor
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()
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())
66 if (length < size_required)
68 throw std::runtime_error{"Too small length"};
72 _io_desc.inputs.at(index.value()) = std::make_unique<InputDesc>(info, buffer, length, layout);
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)
79 auto info = ir::OperandInfo::createStaticInfo(shape, type);
81 if (length < info.total_size())
83 throw std::runtime_error{"Too small length"};
86 _io_desc.inputs.at(index.value()) = std::make_unique<InputDesc>(info, buffer, length, layout);
89 // TODO Remove default parameter
90 void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length, ir::Layout layout)
92 const auto output_index = primary_subgraph().getOutputs().at(index);
93 const auto info = primary_subgraph().operands().at(output_index).info();
95 if (length < info.total_size())
97 throw std::runtime_error{"Too small length"};
100 _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(info, buffer, length, layout);
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)
107 auto info = ir::OperandInfo::createStaticInfo(shape, type);
109 if (length < info.total_size())
111 throw std::runtime_error{"Too small length"};
114 _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(info, buffer, length, layout);
117 void Execution::setInputLayout(const ir::IOIndex &index, ir::Layout layout)
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);
124 void Execution::setOutputLayout(const ir::IOIndex &index, ir::Layout layout)
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);
131 void Execution::execute()
133 VERBOSE(Execution) << "Start execution" << std::endl;
135 primary_executor()->execute(_io_desc);
138 VERBOSE(Execution) << "Execution finished" << std::endl;
141 void Execution::startExecute()
143 VERBOSE(Execution) << "Create asynchronous execution thread" << std::endl;
145 _exec_thread = std::make_unique<std::thread>(&Execution::execute, this);
148 void Execution::waitFinish()
150 VERBOSE(Execution) << "Wait to finish execution" << std::endl;
152 _exec_thread->join();
156 bool Execution::isFinished(void) const { return finished; }
158 ir::Shape Execution::getInputShape(ir::IOIndex ind) const
160 auto itr = _io_desc.dynamic_input_shapes.find(ind);
161 if (itr == _io_desc.dynamic_input_shapes.end())
163 auto operand_idx = primary_subgraph().getInputs().at(ind.value());
164 return primary_subgraph().operands().at(operand_idx).shape();
172 ir::Shape Execution::getOutputShape(ir::IOIndex ind) const
175 throw std::runtime_error("Cannot get output shape before execution is finished");
177 const auto &output_desc = _io_desc.outputs.at(ind.value());
179 return output_desc->info.shape();