Skip to content

Commit

Permalink
[onert] Introduce ExecutionContext (Samsung#13160)
Browse files Browse the repository at this point in the history
This commit introduces ExecutionContext struct.
It includes IODescription and execution options to be used by executor.

ONE-DCO-1.0-Signed-off-by: Hyeongseok Oh <[email protected]>
  • Loading branch information
hseok-oh authored Jun 13, 2024
1 parent 99e297d commit d1d1a80
Show file tree
Hide file tree
Showing 15 changed files with 72 additions and 55 deletions.
4 changes: 2 additions & 2 deletions runtime/onert/core/include/exec/Execution.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "backend/train/ITrainableTensor.h"
#include "ir/Layout.h"
#include "exec/IExecutors.h"
#include "IODescription.h"
#include "ExecutionContext.h"

#include <thread>
#include <deque>
Expand Down Expand Up @@ -182,7 +182,7 @@ class Execution

private:
const std::shared_ptr<IExecutors> _executors;
IODescription _io_desc;
ExecutionContext _ctx;
std::unique_ptr<std::thread> _exec_thread;
bool finished{false};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* limitations under the License.
*/

#ifndef __ONERT_EXEC_IO_DESCRIPTION_H__
#define __ONERT_EXEC_IO_DESCRIPTION_H__
#ifndef __ONERT_EXEC_EXECUTION_CONTEXT_H__
#define __ONERT_EXEC_EXECUTION_CONTEXT_H__

#include <vector>
#include <unordered_map>
Expand Down Expand Up @@ -61,10 +61,23 @@ struct IODescription
{
std::vector<std::unique_ptr<InputDesc>> inputs;
std::vector<std::unique_ptr<OutputDesc>> outputs;
bool updated; // Require shape inference and buffer size calculation
};

struct ExecutionOptions
{
bool dump_minmax = false;
bool trace = false;
bool profile = false;
};

struct ExecutionContext
{
IODescription desc;
bool shape_updated = false; // Require shape inference and buffer size calculation
ExecutionOptions optoins;
};

} // namespace exec
} // namespace onert

#endif // __ONERT_EXEC_IO_DESCRIPTION_H__
#endif // __ONERT_EXEC_EXECUTION_CONTEXT_H__
6 changes: 3 additions & 3 deletions runtime/onert/core/include/exec/IExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include "ir/Graph.h"
#include "IFunction.h"
#include "IODescription.h"
#include "ExecutionContext.h"
#include "ir/Index.h"
#include "ir/OperationIndexMap.h"

Expand Down Expand Up @@ -75,10 +75,10 @@ struct IExecutor

/**
* @brief Execute with user-given input/output description (for primary subgraph)
* @param[in] desc Input and output description
* @param[in] ctx Execution context
* @note This method should be thread-safe
*/
virtual void execute(const IODescription &desc) = 0;
virtual void execute(const ExecutionContext &ctx) = 0;

/**
* @brief Execute with given input/output tensors
Expand Down
4 changes: 2 additions & 2 deletions runtime/onert/core/include/exec/IExecutors.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ class IExecutors

/**
* @brief Execute NN package executor set
* @param[in] desc Input and output buffer description
* @param[in] ctx Execution context
*/
virtual void execute(const IODescription &desc) = 0;
virtual void execute(const ExecutionContext &ctx) = 0;
};

} // namespace exec
Expand Down
46 changes: 23 additions & 23 deletions runtime/onert/core/src/exec/Execution.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,26 @@ Execution::Execution(const std::shared_ptr<IExecutors> &executors) : _executors{
assert(executors->entryExecutor() != nullptr);

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

_io_desc.outputs.resize(_executors->outputSize());
_ctx.desc.outputs.resize(_executors->outputSize());
for (uint32_t i = 0; i < _executors->outputSize(); ++i)
_io_desc.outputs.at(i) = std::make_unique<OutputDesc>(_executors->outputInfo(ir::IOIndex(i)));
_io_desc.updated = false;
_ctx.desc.outputs.at(i) = std::make_unique<OutputDesc>(_executors->outputInfo(ir::IOIndex(i)));
_ctx.shape_updated = false;
}

void Execution::changeInputShape(const ir::IOIndex &index, const ir::Shape &new_shape)
{
// This will be used later to set input tensor dynamic
// Note that 'compiled' model will not be updated with new_shape
// but new_shape will change model input shape while 'running' the model
auto &input_desc = _io_desc.inputs.at(index.value());
auto &input_desc = _ctx.desc.inputs.at(index.value());
if (new_shape != input_desc->info.shape())
{
input_desc->info.shape(new_shape);
_io_desc.updated = true;
_ctx.shape_updated = true;

VERBOSE(Execution) << "Model input shape will be changed at the start of execute()"
<< "(index: " << index << ")" << std::endl;
Expand All @@ -65,7 +65,7 @@ void Execution::setInput(const ir::IOIndex &index, const void *buffer, size_t le
// check if size enough for input is passed
// if input_shape_sig is set, input_shape_sig overrides shape in info
// note: input_shape_sig contains shape passed by nnfw_set_input_tensorinfo()
auto &input_desc = _io_desc.inputs.at(index.value());
auto &input_desc = _ctx.desc.inputs.at(index.value());
if (length < input_desc->info.total_size())
{
throw std::runtime_error{"Too small length"};
Expand All @@ -84,9 +84,9 @@ void Execution::setInput(const ir::IOIndex &index, const ir::Shape &shape, const

void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length)
{
auto &output_desc = _io_desc.outputs.at(index.value());
auto &output_desc = _ctx.desc.outputs.at(index.value());
// Check lenght when output shape is valid
if (!_io_desc.updated && length < output_desc->info.total_size())
if (!_ctx.shape_updated && length < output_desc->info.total_size())
{
throw std::runtime_error{"Too small length"};
}
Expand All @@ -98,39 +98,39 @@ void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length)
void Execution::setOutput(const ir::IOIndex &index, const ir::Shape &shape, void *buffer,
size_t length)
{
auto &output_desc = _io_desc.outputs.at(index.value());
auto &output_desc = _ctx.desc.outputs.at(index.value());
output_desc->info.shape(shape);

setOutput(index, buffer, length);
}

void Execution::setInputLayout(const ir::IOIndex &index, ir::Layout layout)
{
_io_desc.inputs.at(index.value())->layout = layout;
_ctx.desc.inputs.at(index.value())->layout = layout;
}

void Execution::setOutputLayout(const ir::IOIndex &index, ir::Layout layout)
{
_io_desc.outputs.at(index.value())->layout = layout;
_ctx.desc.outputs.at(index.value())->layout = layout;
}

void Execution::setInputType(const ir::IOIndex &index, const ir::TypeInfo &typeInfo)
{
_io_desc.inputs.at(index.value())->info.typeInfo(typeInfo);
_io_desc.updated = true;
_ctx.desc.inputs.at(index.value())->info.typeInfo(typeInfo);
_ctx.shape_updated = true;
}

void Execution::setOutputType(const ir::IOIndex &index, const ir::TypeInfo &typeInfo)
{
_io_desc.outputs.at(index.value())->info.typeInfo(typeInfo);
_io_desc.updated = true;
_ctx.desc.outputs.at(index.value())->info.typeInfo(typeInfo);
_ctx.shape_updated = true;
}

void Execution::execute()
{
VERBOSE(Execution) << "Start execution" << std::endl;

_executors->execute(_io_desc);
_executors->execute(_ctx);
finished = true;

VERBOSE(Execution) << "Execution finished" << std::endl;
Expand Down Expand Up @@ -161,7 +161,7 @@ void Execution::train(uint32_t training_step)
throw std::runtime_error{"Supported only TrainableExecutors"};
}

execs->train(_io_desc, training_step);
execs->train(_ctx, training_step);
finished = true;
}

Expand Down Expand Up @@ -190,7 +190,7 @@ void Execution::iterateTrainableTensors(

ir::Shape Execution::getInputShape(ir::IOIndex ind) const
{
return _io_desc.inputs.at(ind.value())->info.shape();
return _ctx.desc.inputs.at(ind.value())->info.shape();
}

// NNAPI return fail if ANeuralNetworksExecution_getOutputOperandRank or
Expand All @@ -201,18 +201,18 @@ ir::Shape Execution::getInputShape(ir::IOIndex ind) const
// NNAPI frontend.
ir::Shape Execution::getOutputShape(ir::IOIndex ind) const
{
return _io_desc.outputs.at(ind.value())->info.shape();
return _ctx.desc.outputs.at(ind.value())->info.shape();
}

size_t Execution::getInputTotalSize(ir::IOIndex ind) const
{
// TODO Support dynamic shape
return _io_desc.inputs.at(ind.value())->info.total_size();
return _ctx.desc.inputs.at(ind.value())->info.total_size();
}

size_t Execution::getOutputTotalSize(ir::IOIndex ind) const
{
return _io_desc.outputs.at(ind.value())->info.total_size();
return _ctx.desc.outputs.at(ind.value())->info.total_size();
}

} // namespace exec
Expand Down
5 changes: 3 additions & 2 deletions runtime/onert/core/src/exec/ExecutorBase.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,15 @@ void ExecutorBase::execute(const std::vector<backend::IPortableTensor *> &inputs
executeImpl();
}

void ExecutorBase::execute(const IODescription &desc)
void ExecutorBase::execute(const ExecutionContext &ctx)
{
// For thread-safe, use mutex
// TODO: if all used backends on this executor are thread-safe,
// do not need to use mutex (otherwise, use mutex)
std::lock_guard<std::mutex> lock(_mutex);

// Set input(s)
auto &desc = ctx.desc;
assert(_input_tensors.size() == desc.inputs.size());
for (uint32_t i = 0; i < _input_tensors.size(); ++i)
{
Expand All @@ -114,7 +115,7 @@ void ExecutorBase::execute(const IODescription &desc)
tensor->setUserTensor(static_cast<uint8_t *>(const_cast<void *>(desc.inputs[i]->buffer)),
desc.inputs[i]->size);

if (desc.updated)
if (ctx.shape_updated)
{
auto &input_shape = desc.inputs.at(i)->info.shape();
tensor->set_dynamic();
Expand Down
4 changes: 2 additions & 2 deletions runtime/onert/core/src/exec/ExecutorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include "compiler/LoweredGraph.h"
#include "exec/IExecutor.h"
#include "exec/IODescription.h"
#include "exec/ExecutionContext.h"
#include "ir/Graph.h"
#include "ir/OperationIndexMap.h"
#include "util/TracingCtx.h"
Expand Down Expand Up @@ -53,7 +53,7 @@ class ExecutorBase : public IExecutor

const ir::Graph &graph() const final { return _graph; }

void execute(const IODescription &desc) final;
void execute(const ExecutionContext &ctx) final;

void execute(const std::vector<backend::IPortableTensor *> &inputs,
const std::vector<backend::IPortableTensor *> &outputs) override;
Expand Down
4 changes: 3 additions & 1 deletion runtime/onert/core/src/exec/MultiModelExecutors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,10 @@ void MultiModelExecutors::createPkgIOQuantLayers(const IODescription &desc)
}
}

void MultiModelExecutors::execute(const IODescription &desc)
void MultiModelExecutors::execute(const ExecutionContext &ctx)
{
auto &desc = ctx.desc;

// Check supported multi model package
checkSupportedMultimodel();

Expand Down
2 changes: 1 addition & 1 deletion runtime/onert/core/src/exec/MultiModelExecutors.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class MultiModelExecutors : public IExecutors

const ir::OperandInfo &outputInfo(const ir::IOIndex &index) const override;

void execute(const IODescription &desc) override;
void execute(const ExecutionContext &ctx) override;

private:
void checkSupportedMultimodel() const;
Expand Down
2 changes: 1 addition & 1 deletion runtime/onert/core/src/exec/SingleModelExecutors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const ir::OperandInfo &SingleModelExecutors::outputInfo(const ir::IOIndex &index
return entryExecutor()->getOutputTensors().at(index.value())->orig_info();
}

void SingleModelExecutors::execute(const IODescription &desc) { entryExecutor()->execute(desc); }
void SingleModelExecutors::execute(const ExecutionContext &ctx) { entryExecutor()->execute(ctx); }

} // namespace exec
} // namespace onert
2 changes: 1 addition & 1 deletion runtime/onert/core/src/exec/SingleModelExecutors.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class SingleModelExecutors : public IExecutors

const ir::OperandInfo &outputInfo(const ir::IOIndex &index) const override;

void execute(const IODescription &desc) override;
void execute(const ExecutionContext &ctx) override;

private:
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<IExecutor>> _executors;
Expand Down
5 changes: 3 additions & 2 deletions runtime/onert/core/src/exec/train/TrainableExecutor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ void TrainableExecutor::execute(const std::vector<backend::IPortableTensor *> &,
throw std::runtime_error("TrainableExecutor does not support multiple subgraphs yet");
}

void TrainableExecutor::forward(const IODescription &desc, bool training)
void TrainableExecutor::forward(const ExecutionContext &ctx, bool training)
{
// For thread-safe, use mutex
// TODO: if all used backends on this executor are thread-safe,
// do not need to use mutex (otherwise, use mutex)
std::lock_guard<std::mutex> lock(_mutex);

auto &desc = ctx.desc;
// TODO Update IO tensors if desc has dynamic input
// Set input(s)
assert(_input_tensors.size() == desc.inputs.size());
Expand Down Expand Up @@ -137,7 +138,7 @@ void TrainableExecutor::forwardImpl(bool training)
}
}

void TrainableExecutor::backward(const IODescription &, uint32_t training_step)
void TrainableExecutor::backward(const ExecutionContext &, uint32_t training_step)
{
// For thread-safe, use mutex
// TODO: if all used backends on this executor are thread-safe,
Expand Down
6 changes: 3 additions & 3 deletions runtime/onert/core/src/exec/train/TrainableExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ class TrainableExecutor : public IExecutor
public:
const ir::Graph &graph() const final { return _trainable_graph.graph(); }

void execute(const IODescription &desc) override { forward(desc, false); };
void execute(const ExecutionContext &ctx) override { forward(ctx, false); };

void execute(const std::vector<backend::IPortableTensor *> &inputs,
const std::vector<backend::IPortableTensor *> &outputs) override;

void forward(const IODescription &desc, bool training);
void backward(const IODescription &desc, uint32_t training_step);
void forward(const ExecutionContext &ctx, bool training);
void backward(const ExecutionContext &ctx, uint32_t training_step);

// Used only in Dataflow and Parallel Executors
void setIndexedRanks(std::shared_ptr<ir::OperationIndexMap<int64_t>> ranks) final
Expand Down
10 changes: 5 additions & 5 deletions runtime/onert/core/src/exec/train/TrainableExecutors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,21 @@ const ir::OperandInfo &TrainableExecutors::outputInfo(const ir::IOIndex &index)
return entryExecutor()->getOutputTensors().at(index.value())->orig_info();
}

void TrainableExecutors::execute(const IODescription &desc)
void TrainableExecutors::execute(const ExecutionContext &ctx)
{
if (_executors.size() > 1)
throw std::runtime_error("TrainableExecutors does not support multiple executors yet");
entryExecutor()->forward(desc, false);
entryExecutor()->forward(ctx, false);

// TODO Support multple executors
}

void TrainableExecutors::train(const IODescription &desc, uint32_t training_step)
void TrainableExecutors::train(const ExecutionContext &ctx, uint32_t training_step)
{
if (_executors.size() > 1)
throw std::runtime_error("TrainableExecutors does not support multiple executors yet");
entryExecutor()->forward(desc, true);
entryExecutor()->backward(desc, training_step);
entryExecutor()->forward(ctx, true);
entryExecutor()->backward(ctx, training_step);

// TODO Support multple executors
}
Expand Down
Loading

0 comments on commit d1d1a80

Please sign in to comment.