Skip to content

Commit ea01780

Browse files
authored
[onert] Clean up Execution API (#15927)
This commit cleans up Execution API - Add API to access I/O info - Remove APIs which can be handled by new API - Remove setInput/setOutput API used for NNAPI only - Change IExecutors context paramter as inout and remove const to return shape inference result - Change IODescription vector element type: use raw type instead of unique_ptr for simple copy ONE-DCO-1.0-Signed-off-by: Hyeongseok Oh <[email protected]>
1 parent f0b931a commit ea01780

File tree

13 files changed

+81
-204
lines changed

13 files changed

+81
-204
lines changed

runtime/onert/api/nnfw/src/nnfw_session.cc

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ NNFW_STATUS nnfw_session::input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
815815
}
816816
else
817817
{
818-
const auto &info = _execution->getInputInfo(index);
818+
const auto &info = _execution->inputInfo(index);
819819
fillTensorInfo(ti, info.shape(), info.typeInfo().type());
820820
}
821821
}
@@ -855,10 +855,8 @@ NNFW_STATUS nnfw_session::output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
855855
}
856856
else
857857
{
858-
auto io_index = onert::ir::IOIndex{index};
859-
auto shape = _execution->getOutputShape(io_index);
860-
auto dtype = _compiler_artifact->_executors->outputInfo(io_index).typeInfo().type();
861-
fillTensorInfo(ti, shape, dtype);
858+
auto info = _execution->outputInfo(index);
859+
fillTensorInfo(ti, info.shape(), info.typeInfo().type());
862860
}
863861
}
864862
catch (const std::exception &e)
@@ -1562,7 +1560,7 @@ NNFW_STATUS nnfw_session::train_set_input(uint32_t index, const void *input,
15621560
try
15631561
{
15641562
auto ind = onert::ir::IOIndex(index);
1565-
auto size = _execution->getInputTotalSize(ind);
1563+
auto size = _execution->inputInfo(index).total_size();
15661564
if (input_tensorinfo && getBufSize(input_tensorinfo) != size)
15671565
{
15681566
std::cerr
@@ -1607,8 +1605,7 @@ NNFW_STATUS nnfw_session::train_set_expected(uint32_t index, const void *expecte
16071605

16081606
try
16091607
{
1610-
auto output_ind = onert::ir::IOIndex(index);
1611-
auto size = _execution->getOutputTotalSize(output_ind);
1608+
auto size = _execution->outputInfo(index).total_size();
16121609
if (expected_tensorinfo && getBufSize(expected_tensorinfo) != size)
16131610
{
16141611
std::cerr << "Error during nnfw_session::train_set_expected : invalid tensorinfo"
@@ -2285,28 +2282,16 @@ NNFW_STATUS nnfw_session::run_with_auto_compilation(const char *target, NNFW_COD
22852282
std::vector<void *> _output_buffers;
22862283

22872284
using namespace onert::ir;
2288-
// Save Inputs buffers, set compile option to use float type
2289-
for (auto input_index = IOIndex{0}; input_index < IOIndex{input_size}; input_index++)
2290-
{
2291-
auto input_Shape = _execution->getInputShape(input_index);
2292-
auto input_buffer = _execution->getInputBuffer(input_index);
2285+
// Copy execution context for backup: I/O buffer, shape, and execution options
2286+
const onert::exec::ExecutionContext ctx_backup = _execution->context();
22932287

2294-
_input_buffers.push_back(input_buffer);
2288+
// Set compile option to use float type
2289+
for (auto input_index = IOIndex{0}; input_index < IOIndex{input_size}; input_index++)
22952290
_coptions->input_type.insert_or_assign(input_index, TypeInfo(DataType::FLOAT32));
2296-
}
22972291

22982292
// Save Outputs buffers
22992293
for (auto output_index = IOIndex{0}; output_index < IOIndex{output_size}; output_index++)
2300-
{
2301-
auto output_Shape = _execution->getOutputShape(output_index);
2302-
auto output_buffer = _execution->getOutputBuffer(output_index);
2303-
2304-
_output_buffers.push_back(output_buffer);
23052294
_coptions->output_type.insert_or_assign(output_index, TypeInfo(DataType::FLOAT32));
2306-
}
2307-
2308-
// Save execution options
2309-
auto saved_options = _execution->executionOptions();
23102295

23112296
// if there is compiled model - try to load it
23122297
if (file_compiled_model.good())
@@ -2350,41 +2335,8 @@ NNFW_STATUS nnfw_session::run_with_auto_compilation(const char *target, NNFW_COD
23502335
if (status != NNFW_STATUS_NO_ERROR)
23512336
return status;
23522337

2353-
// Restore execution options
2354-
_execution->executionOptions() = saved_options;
2355-
2356-
// Restore inputs to the quantized or compiled model
2357-
for (uint32_t input_index = 0; input_index < _input_buffers.size(); input_index++)
2358-
{
2359-
nnfw_tensorinfo ti;
2360-
status = input_tensorinfo(input_index, &ti);
2361-
if (status != NNFW_STATUS_NO_ERROR)
2362-
return status;
2363-
2364-
auto input_size_in_bytes = getBufSize(&ti);
2365-
2366-
status = set_input(input_index, ti.dtype, _input_buffers[input_index], input_size_in_bytes);
2367-
2368-
if (status != NNFW_STATUS_NO_ERROR)
2369-
return status;
2370-
}
2371-
2372-
// Restore outputs to the quantized or compiled model
2373-
for (uint32_t output_index = 0; output_index < _output_buffers.size(); output_index++)
2374-
{
2375-
2376-
nnfw_tensorinfo ti;
2377-
status = output_tensorinfo(output_index, &ti);
2378-
if (status != NNFW_STATUS_NO_ERROR)
2379-
return status;
2380-
2381-
uint64_t output_size_in_bytes = getBufSize(&ti);
2382-
2383-
status =
2384-
set_output(output_index, ti.dtype, _output_buffers[output_index], output_size_in_bytes);
2385-
if (status != NNFW_STATUS_NO_ERROR)
2386-
return status;
2387-
}
2338+
// Restore execution context: I/O buffer, shape, and execution options
2339+
_execution->restoreContext(ctx_backup);
23882340
}
23892341

23902342
// Run quantized model

runtime/onert/core/include/exec/Execution.h

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -69,38 +69,28 @@ class Execution
6969
*/
7070
void setInput(const ir::IOIndex &index, const void *buffer, size_t length);
7171

72-
/**
73-
* @brief Set input data's information, especially to specify unknown dimensions on model
74-
* build time.
75-
* @param[in] index Input index
76-
* @param[in] shape Input data's shape
77-
* @param[in] buffer Input data's buffer pointer
78-
* @param[in] length Input data's length
79-
*/
80-
void setInput(const ir::IOIndex &index, const ir::Shape &shape, const void *buffer,
81-
size_t length);
8272
/**
8373
* @brief Set output data's information
8474
* @param[in] index Output index
8575
* @param[in] buffer Output data's buffer pointer
8676
* @param[in] length Output data's length
8777
*/
8878
void setOutput(const ir::IOIndex &index, void *buffer, size_t length);
89-
/**
90-
* @brief Set output data's information, especially to specify unknown dimensions on model
91-
* build time.
92-
* @param[in] index Output index
93-
* @param[in] shape Output data's shape
94-
* @param[in] buffer Output data's buffer pointer
95-
* @param[in] length Output data's length
96-
*/
97-
void setOutput(const ir::IOIndex &index, const ir::Shape &shape, void *buffer, size_t length);
79+
9880
/**
9981
* @brief Get the Input Info object
10082
* @param[in] index Input index
10183
* @return Input info
10284
*/
103-
const ir::OperandInfo &getInputInfo(uint32_t index) { return _ctx.desc.inputs.at(index)->info; }
85+
const ir::OperandInfo &inputInfo(uint32_t index) { return _ctx.desc.inputs.at(index).info; }
86+
87+
/**
88+
* @brief Get the Output Info object
89+
* @param[in] index Output index
90+
* @return Output info
91+
*/
92+
const ir::OperandInfo &outputInfo(uint32_t index) { return _ctx.desc.outputs.at(index).info; }
93+
10494
/**
10595
* @brief Execution
10696
* @note It should be called after setting input and output buffer
@@ -151,24 +141,17 @@ class Execution
151141
const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)>
152142
&fn) const;
153143

154-
ir::Shape getInputShape(ir::IOIndex ind) const;
155-
ir::Shape getOutputShape(ir::IOIndex ind) const;
156-
size_t getInputTotalSize(ir::IOIndex ind) const;
157-
size_t getOutputTotalSize(ir::IOIndex ind) const;
158-
159144
/**
160-
* @brief Get pointer of Input Buffer
161-
* @param[in] index Input index
162-
* @return Pointer of Input Buffer
145+
* @brief Get context of execution
146+
* @return Execution context
163147
*/
164-
const void *getInputBuffer(ir::IOIndex ind) const;
148+
const ExecutionContext &context() const { return _ctx; }
165149

166150
/**
167-
* @brief Get pointer of Output Buffer
168-
* @param[in] index Output index
169-
* @return Pointer of Output Buffer
151+
* @brief Set context of execution at once
152+
* @param[in] ctx Execution context
170153
*/
171-
void *getOutputBuffer(ir::IOIndex ind);
154+
void restoreContext(const ExecutionContext &ctx) { _ctx = ctx; }
172155

173156
ExecutionOptions &executionOptions() { return _ctx.options; }
174157

runtime/onert/core/include/exec/ExecutionContext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ struct OutputDesc
4949

5050
struct IODescription
5151
{
52-
std::vector<std::unique_ptr<InputDesc>> inputs;
53-
std::vector<std::unique_ptr<OutputDesc>> outputs;
52+
std::vector<InputDesc> inputs;
53+
std::vector<OutputDesc> outputs;
5454
};
5555

5656
struct ExecutionOptions

runtime/onert/core/include/exec/IExecutors.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ class IExecutors
9898
virtual const backend::IPortableTensor *outputTensor(const ir::IOIndex &index) const = 0;
9999

100100
/**
101-
* @brief Execute NN package executor set
102-
* @param[in] ctx Execution context
101+
* @brief Execute NN package executor set
102+
* @param[inout] ctx Execution context. It reflects execution result (ex. output shape inference)
103103
*/
104-
virtual void execute(const ExecutionContext &ctx) = 0;
104+
virtual void execute(ExecutionContext &ctx) = 0;
105105
};
106106

107107
} // namespace onert::exec

runtime/onert/core/src/exec/Execution.cc

Lines changed: 11 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,11 @@ Execution::Execution(const std::shared_ptr<IExecutors> &executors) : _executors{
3232
assert(executors->entryExecutor() != nullptr);
3333

3434
// Initialize I/O description
35-
_ctx.desc.inputs.resize(_executors->inputSize());
3635
for (uint32_t i = 0; i < _executors->inputSize(); ++i)
37-
_ctx.desc.inputs.at(i) = std::make_unique<InputDesc>(_executors->inputInfo(ir::IOIndex(i)));
36+
_ctx.desc.inputs.emplace_back(_executors->inputInfo(ir::IOIndex(i)));
3837

39-
_ctx.desc.outputs.resize(_executors->outputSize());
4038
for (uint32_t i = 0; i < _executors->outputSize(); ++i)
41-
_ctx.desc.outputs.at(i) = std::make_unique<OutputDesc>(_executors->outputInfo(ir::IOIndex(i)));
39+
_ctx.desc.outputs.emplace_back(_executors->outputInfo(ir::IOIndex(i)));
4240
_ctx.shape_updated = false;
4341

4442
_is_internal_output_tensor.resize(_executors->outputSize());
@@ -62,9 +60,9 @@ void Execution::changeInputShape(const ir::IOIndex &index, const ir::Shape &new_
6260
// Note that 'compiled' model will not be updated with new_shape
6361
// but new_shape will change model input shape while 'running' the model
6462
auto &input_desc = _ctx.desc.inputs.at(index.value());
65-
if (new_shape != input_desc->info.shape())
63+
if (new_shape != input_desc.info.shape())
6664
{
67-
input_desc->info.shape(new_shape);
65+
input_desc.info.shape(new_shape);
6866
_ctx.shape_updated = true;
6967

7068
VERBOSE(Execution) << "Model input shape will be changed at the start of execute()"
@@ -77,15 +75,8 @@ void Execution::setInput(const ir::IOIndex &index, const void *buffer, size_t le
7775
{
7876
// Length validation in execute(): datatype can be changed by API call
7977
auto &input_desc = _ctx.desc.inputs.at(index.value());
80-
input_desc->buffer = buffer;
81-
input_desc->size = length;
82-
}
83-
84-
void Execution::setInput(const ir::IOIndex &index, const ir::Shape &shape, const void *buffer,
85-
size_t length)
86-
{
87-
changeInputShape(index, shape);
88-
setInput(index, buffer, length);
78+
input_desc.buffer = buffer;
79+
input_desc.size = length;
8980
}
9081

9182
void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length)
@@ -94,17 +85,8 @@ void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length)
9485
// - datatype can be changed by API call
9586
// - shape can be changed by dynamic shape inference
9687
auto &output_desc = _ctx.desc.outputs.at(index.value());
97-
output_desc->buffer = buffer;
98-
output_desc->size = length;
99-
}
100-
101-
void Execution::setOutput(const ir::IOIndex &index, const ir::Shape &shape, void *buffer,
102-
size_t length)
103-
{
104-
auto &output_desc = _ctx.desc.outputs.at(index.value());
105-
output_desc->info.shape(shape);
106-
107-
setOutput(index, buffer, length);
88+
output_desc.buffer = buffer;
89+
output_desc.size = length;
10890
}
10991

11092
void Execution::execute()
@@ -114,7 +96,7 @@ void Execution::execute()
11496
// Input length validation check
11597
for (const auto &input : _ctx.desc.inputs)
11698
{
117-
if (input->info.total_size() > input->size)
99+
if (input.info.total_size() > input.size)
118100
throw std::runtime_error{"Too small input buffer length"};
119101
}
120102

@@ -126,9 +108,9 @@ void Execution::execute()
126108
{
127109
const bool is_managed_internally = _is_internal_output_tensor.at(i);
128110
const auto &output = _ctx.desc.outputs.at(i);
129-
if (!is_managed_internally && output->info.total_size() > output->size)
111+
if (!is_managed_internally && output.info.total_size() > output.size)
130112
throw std::runtime_error{"Too small output buffer length"};
131-
if (is_managed_internally && output->buffer != nullptr)
113+
if (is_managed_internally && output.buffer != nullptr)
132114
VERBOSE(Execution) << "Warning: Output buffer was set from API even though the output "
133115
"tensor was allocated internally"
134116
<< std::endl;
@@ -193,41 +175,4 @@ void Execution::iterateTrainableTensors(
193175
execs->iterateTrainableTensors(fn);
194176
}
195177

196-
ir::Shape Execution::getInputShape(ir::IOIndex ind) const
197-
{
198-
return _ctx.desc.inputs.at(ind.value())->info.shape();
199-
}
200-
201-
// NNAPI return fail if ANeuralNetworksExecution_getOutputOperandRank or
202-
// ANeuralNetworksExecution_getOutputOperandDimensions is called before execution.
203-
// On the other hand, NNFW API return static shape inference result if nnfw_output_tensorinfo is
204-
// called before execution.
205-
// To handle both case, this method retun static shape inference result and fail will be handled on
206-
// NNAPI frontend.
207-
ir::Shape Execution::getOutputShape(ir::IOIndex ind) const
208-
{
209-
return _ctx.desc.outputs.at(ind.value())->info.shape();
210-
}
211-
212-
size_t Execution::getInputTotalSize(ir::IOIndex ind) const
213-
{
214-
// TODO Support dynamic shape
215-
return _ctx.desc.inputs.at(ind.value())->info.total_size();
216-
}
217-
218-
size_t Execution::getOutputTotalSize(ir::IOIndex ind) const
219-
{
220-
return _ctx.desc.outputs.at(ind.value())->info.total_size();
221-
}
222-
223-
const void *Execution::getInputBuffer(ir::IOIndex ind) const
224-
{
225-
return _ctx.desc.inputs.at(ind.value())->buffer;
226-
}
227-
228-
void *Execution::getOutputBuffer(ir::IOIndex ind)
229-
{
230-
return _ctx.desc.outputs.at(ind.value())->buffer;
231-
}
232-
233178
} // namespace onert::exec

runtime/onert/core/src/exec/Execution.test.cc

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,14 @@ TEST(ExecInstance, neg_small_inoutsize)
366366

367367
onert::exec::Execution execution{executors};
368368

369-
execution.setInput(input1, new_shape, reinterpret_cast<const void *>(input1_buffer), 8);
370-
execution.setInput(input2, new_shape, reinterpret_cast<const void *>(input2_buffer), 2);
369+
execution.changeInputShape(input1, new_shape);
370+
execution.changeInputShape(input2, new_shape);
371+
execution.setInput(input1, reinterpret_cast<const void *>(input1_buffer), 8);
372+
execution.setInput(input2, reinterpret_cast<const void *>(input2_buffer), 2);
371373
EXPECT_THROW(execution.execute(), std::exception);
372374

373375
// Not throw exception because input shape is changed and output buffer is enough
374-
execution.setInput(input2, new_shape, reinterpret_cast<const void *>(input2_buffer), 8);
376+
execution.setInput(input2, reinterpret_cast<const void *>(input2_buffer), 8);
375377
execution.setOutput(output, reinterpret_cast<void *>(output_buffer), 16);
376378
execution.execute();
377379

@@ -762,12 +764,9 @@ TEST(ExecInstance, multi_model_dequant_input_quant_output)
762764
auto executors = mockup.artifact->_executors;
763765

764766
onert::exec::Execution execution{executors};
765-
execution.setInput(input1, execution.getInputShape(input1),
766-
reinterpret_cast<const void *>(input1_buffer), 4);
767-
execution.setInput(input2, execution.getInputShape(input2),
768-
reinterpret_cast<const void *>(input2_buffer), 4);
769-
execution.setOutput(output, execution.getOutputShape(output),
770-
reinterpret_cast<void *>(output_buffer), 4);
767+
execution.setInput(input1, reinterpret_cast<const void *>(input1_buffer), 4);
768+
execution.setInput(input2, reinterpret_cast<const void *>(input2_buffer), 4);
769+
execution.setOutput(output, reinterpret_cast<void *>(output_buffer), 4);
771770
execution.execute();
772771

773772
for (auto i = 0; i < 4; i++)

0 commit comments

Comments
 (0)