summaryrefslogtreecommitdiff
path: root/runtime/onert/api/src/nnfw_api_internal.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/onert/api/src/nnfw_api_internal.cc')
-rw-r--r--runtime/onert/api/src/nnfw_api_internal.cc267
1 files changed, 153 insertions, 114 deletions
diff --git a/runtime/onert/api/src/nnfw_api_internal.cc b/runtime/onert/api/src/nnfw_api_internal.cc
index 62a043921..9b43dd381 100644
--- a/runtime/onert/api/src/nnfw_api_internal.cc
+++ b/runtime/onert/api/src/nnfw_api_internal.cc
@@ -25,6 +25,7 @@
#include "tflite_loader.h"
#include "trix_loader.h"
#include "json/json.h"
+#include "ir/NNPkg.h"
#include "ir/OpCode.h"
#include "util/TracingCtx.h"
@@ -110,9 +111,7 @@ std::string trim(const std::string &value)
return value.substr(begin, range);
}
-using CfgKeyValues = std::unordered_map<std::string, std::string>;
-
-bool loadConfigure(const std::string cfgfile, CfgKeyValues &keyValues)
+bool loadConfigure(const std::string cfgfile, onert::util::CfgKeyValues &keyValues)
{
std::ifstream ifs(cfgfile);
if (ifs.is_open())
@@ -143,19 +142,6 @@ bool loadConfigure(const std::string cfgfile, CfgKeyValues &keyValues)
return false;
}
-void setConfigKeyValues(const CfgKeyValues &keyValues)
-{
- auto configsrc = std::make_unique<onert::util::GeneralConfigSource>();
-
- for (auto it = keyValues.begin(); it != keyValues.end(); ++it)
- {
- VERBOSE(NNPKG_CONFIGS) << "(" << it->first << ") = (" << it->second << ")" << std::endl;
- configsrc->set(it->first, it->second);
- }
-
- onert::util::config_source_ext(std::move(configsrc));
-}
-
NNFW_TYPE datatype_to_nnfw_dtype(onert::ir::DataType dt)
{
using onert::ir::DataType;
@@ -195,15 +181,59 @@ void fillTensorInfo(nnfw_tensorinfo *ti, const onert::ir::Shape &shape,
ti->dtype = datatype_to_nnfw_dtype(dtype);
}
+std::unique_ptr<onert::ir::Model> loadModel(const std::string filename,
+ const std::string model_type)
+{
+ if (model_type == "tflite")
+ return onert::tflite_loader::loadModel(filename.c_str());
+ if (model_type == "circle")
+ return onert::circle_loader::loadModel(filename.c_str());
+ if (model_type == "tvn")
+ return onert::trix_loader::loadModel(filename.c_str());
+
+ std::cerr << "Unsupported model type" << std::endl;
+ return std::unique_ptr<onert::ir::Model>(nullptr);
+}
+
} // namespace
nnfw_session::nnfw_session()
- : _subgraphs{nullptr}, _compiler{nullptr}, _execution{nullptr},
- _kernel_registry{std::make_shared<onert::api::CustomKernelRegistry>()}, _tracing_ctx{nullptr}
+ : _nnpkg{nullptr}, _coptions{}, _compiler_artifact{nullptr}, _execution{nullptr},
+ _kernel_registry{nullptr}
{
// DO NOTHING
}
+NNFW_STATUS nnfw_session::create(nnfw_session **session)
+{
+ if (session == nullptr)
+ return NNFW_STATUS_UNEXPECTED_NULL;
+
+ // Create session
+ *session = new (std::nothrow) nnfw_session();
+ if (*session == nullptr)
+ {
+ std::cerr << "Error during session creation" << std::endl;
+ return NNFW_STATUS_OUT_OF_MEMORY;
+ }
+
+ // Initialize fields
+ try
+ {
+ (*session)->_kernel_registry = std::make_shared<onert::api::CustomKernelRegistry>();
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during session initialization : " << e.what() << std::endl;
+ delete *session;
+ *session = nullptr;
+
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
nnfw_session::~nnfw_session() = default;
NNFW_STATUS nnfw_session::load_circle_from_buffer(uint8_t *buffer, size_t size)
@@ -219,19 +249,16 @@ NNFW_STATUS nnfw_session::load_circle_from_buffer(uint8_t *buffer, size_t size)
try
{
- _subgraphs = onert::circle_loader::loadModel(buffer, size);
+ auto model = onert::circle_loader::loadModel(buffer, size);
+ _nnpkg = std::make_shared<onert::ir::NNPkg>(std::move(model));
+ _coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
+ _state = State::MODEL_LOADED;
}
catch (const std::exception &e)
{
std::cerr << "Error during model loading : " << e.what() << std::endl;
return NNFW_STATUS_ERROR;
}
-
- _tracing_ctx = std::make_unique<onert::util::TracingCtx>(_subgraphs.get());
-
- _compiler = std::make_unique<onert::compiler::Compiler>(_subgraphs, _tracing_ctx.get());
-
- _state = State::MODEL_LOADED;
return NNFW_STATUS_NO_ERROR;
}
@@ -247,45 +274,28 @@ NNFW_STATUS nnfw_session::load_model_from_modelfile(const char *model_file_path)
}
std::string filename{model_file_path};
- if (filename.size() < 8) // .tflite or .circle
+ // TODO: Use std::filesystem::path when we can use c++17.
+ auto dotidx = filename.find_last_of('.');
+ if (dotidx == std::string::npos)
{
- std::cerr << "Invalid model file path." << std::endl;
+ std::cerr << "Invalid model file path. Please use file with extension." << std::endl;
return NNFW_STATUS_ERROR;
}
-
- std::string model_type = filename.substr(filename.size() - 7, 7);
-
+ std::string model_type = filename.substr(dotidx + 1); // + 1 to exclude dot
try
{
- if (model_type == ".tflite")
- {
- _subgraphs = onert::tflite_loader::loadModel(filename.c_str());
- }
- else if (model_type == ".circle")
- {
- _subgraphs = onert::circle_loader::loadModel(filename.c_str());
- }
- else if (model_type == ".tvn")
- {
- _subgraphs = onert::trix_loader::loadModel(filename.c_str());
- }
- else
- {
- std::cerr << "Unsupported model type" << std::endl;
+ auto model = loadModel(filename, model_type);
+ if (model == nullptr)
return NNFW_STATUS_ERROR;
- }
+ _nnpkg = std::make_shared<onert::ir::NNPkg>(std::move(model));
+ _coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
+ _state = State::MODEL_LOADED;
}
catch (const std::exception &e)
{
std::cerr << "Error during model loading : " << e.what() << std::endl;
return NNFW_STATUS_ERROR;
}
-
- _tracing_ctx = std::make_unique<onert::util::TracingCtx>(_subgraphs.get());
-
- _compiler = std::make_unique<onert::compiler::Compiler>(_subgraphs, _tracing_ctx.get());
-
- _state = State::MODEL_LOADED;
return NNFW_STATUS_NO_ERROR;
}
@@ -334,45 +344,59 @@ NNFW_STATUS nnfw_session::load_model_from_nnpackage(const char *package_dir)
{
auto filepath = package_path + std::string("/metadata/") + configs[0].asString();
- CfgKeyValues keyValues;
+ onert::util::CfgKeyValues keyValues;
if (loadConfigure(filepath, keyValues))
{
- setConfigKeyValues(keyValues);
+ onert::util::setConfigKeyValues(keyValues);
}
}
-
- auto model_file_path = package_path + std::string("/") + models[0].asString(); // first model
- auto model_type = model_types[0].asString(); // first model's type
- if (model_type == "tflite")
+ _nnpkg = std::make_shared<onert::ir::NNPkg>();
+ for (uint32_t i = 0; i < models.size(); ++i)
{
- _subgraphs = onert::tflite_loader::loadModel(model_file_path);
- }
- else if (model_type == "circle")
- {
- _subgraphs = onert::circle_loader::loadModel(model_file_path);
- }
- else if (model_type == "tvn")
- {
- _subgraphs = onert::trix_loader::loadModel(model_file_path);
+ auto model_file_path = package_path + std::string("/") + models[i].asString();
+ auto model_type = model_types[i].asString();
+ auto model = loadModel(model_file_path, model_type);
+ if (model == nullptr)
+ return NNFW_STATUS_ERROR;
+ model->primary_subgraph()->bindKernelBuilder(_kernel_registry->getBuilder());
+ _nnpkg->push(onert::ir::ModelIndex{i}, std::move(model));
+ _coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
}
- else
+
+ auto toIODesc = [](std::string str) {
+ auto indices = nnfw::misc::split(str, ':');
+ if (indices.size() != 3)
+ {
+ std::cerr << "IODesc should be 3-tuple." << std::endl;
+ return onert::ir::IODesc{};
+ }
+ auto model_idx = static_cast<uint32_t>(std::stoi(indices.at(0)));
+ auto subgraph_idx = static_cast<uint32_t>(std::stoi(indices.at(1)));
+ auto operand_idx = static_cast<uint32_t>(std::stoi(indices.at(2)));
+ return onert::ir::IODesc{model_idx, subgraph_idx, operand_idx};
+ };
+ // read pkg-inputs and pkg-outputs
+ const Json::Value &pkg_inputs = root["pkg-inputs"];
+ for (uint32_t i = 0; i < pkg_inputs.size(); ++i)
+ _nnpkg->addInput(toIODesc(pkg_inputs[i].asString()));
+ const Json::Value &pkg_outputs = root["pkg-outputs"];
+ for (uint32_t i = 0; i < pkg_outputs.size(); ++i)
+ _nnpkg->addOutput(toIODesc(pkg_outputs[i].asString()));
+ // read model-connect
+ const Json::Value &fromtos = root["model-connect"];
+ for (uint32_t i = 0; i < fromtos.size(); ++i)
{
- std::cerr << "Unsupported model type in MANIFEST" << std::endl;
- return NNFW_STATUS_ERROR;
+ const Json::Value &tos = fromtos[i]["to"];
+ for (uint32_t j = 0; j < tos.size(); ++j)
+ _nnpkg->addEdge(toIODesc(fromtos[i]["from"].asString()), toIODesc(tos[j].asString()));
}
- _subgraphs->primary()->bindKernelBuilder(_kernel_registry->getBuilder());
+ _state = State::MODEL_LOADED;
}
catch (const std::exception &e)
{
std::cerr << "Error during model loading : " << e.what() << std::endl;
return NNFW_STATUS_ERROR;
}
-
- _tracing_ctx = std::make_unique<onert::util::TracingCtx>(_subgraphs.get());
-
- _compiler = std::make_unique<onert::compiler::Compiler>(_subgraphs, _tracing_ctx.get());
-
- _state = State::MODEL_LOADED;
return NNFW_STATUS_NO_ERROR;
}
@@ -396,9 +420,17 @@ NNFW_STATUS nnfw_session::prepare()
try
{
- _subgraphs.reset();
- std::shared_ptr<onert::exec::ExecutorMap> executors = _compiler->compile();
- _execution = std::make_unique<onert::exec::Execution>(executors);
+ // TODO: Compile all models in case of multiple models
+ if (_nnpkg->model_count() > 2)
+ {
+ std::cerr << "Error during model prepare : more than 3 multiple models are not supported yet."
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ auto compiler = std::make_unique<onert::compiler::Compiler>(_nnpkg, _coptions);
+ _nnpkg.reset();
+ _compiler_artifact = compiler->compile();
+ _execution = std::make_unique<onert::exec::Execution>(_compiler_artifact->_executors);
}
catch (const std::exception &e)
{
@@ -430,13 +462,14 @@ NNFW_STATUS nnfw_session::prepare_pipeline(const char *map_file_path)
try
{
- _subgraphs.reset();
- std::vector<std::shared_ptr<onert::exec::ExecutorMap>> executor_maps =
- _compiler->compile(_package_file_path.c_str(), map_file_path);
+ auto model = _nnpkg->primary_model();
+ auto compiler = std::make_unique<onert::compiler::Compiler>(model, *_coptions[0]);
+ _nnpkg.reset();
+ auto artifacts = compiler->compile(_package_file_path.c_str(), map_file_path);
- for (auto it = executor_maps.begin(); it != executor_maps.end(); ++it)
+ for (auto it = artifacts.begin(); it != artifacts.end(); ++it)
{
- _executions.push_back(std::make_shared<onert::exec::Execution>(*it));
+ _executions.push_back(std::make_shared<onert::exec::Execution>(it->get()->_executors));
}
make_dependency();
_threads.resize(_executions.size());
@@ -740,7 +773,8 @@ NNFW_STATUS nnfw_session::apply_tensorinfo(uint32_t index, nnfw_tensorinfo ti)
{
// In this case, if we apply input shape in primary_subgraph, it will propagate after
// compilation and excution
- auto primary_subgraph = _subgraphs->primary();
+ auto model = _nnpkg->primary_model();
+ auto primary_subgraph = model->primary_subgraph();
auto ind = primary_subgraph->getInputs().at(index);
auto &input = primary_subgraph->operands().at(ind);
@@ -851,12 +885,12 @@ void nnfw_session::make_dependency()
{
for (uint32_t out_exe = 0; out_exe < _executions.size(); out_exe++)
{
- auto out_graph = _executions[out_exe]->primary_subgraph();
+ auto &out_graph = _executions[out_exe]->primary_subgraph();
for (uint32_t in_exe = 0; in_exe < _executions.size(); in_exe++)
{
if (out_exe == in_exe)
continue;
- auto in_graph = _executions[in_exe]->primary_subgraph();
+ auto &in_graph = _executions[in_exe]->primary_subgraph();
for (auto out = out_graph._name_to_output_begin(); out != out_graph._name_to_output_end();
out++)
{
@@ -971,7 +1005,7 @@ NNFW_STATUS nnfw_session::set_available_backends(const char *backends)
if (null_terminating(backends, MAX_BACKEND_NAME_LENGTH) == false)
return NNFW_STATUS_ERROR;
- auto &options = _compiler->options();
+ auto &options = *_coptions[0];
using namespace onert::util;
@@ -1005,7 +1039,7 @@ NNFW_STATUS nnfw_session::set_op_backend(const char *op, const char *backend)
return NNFW_STATUS_ERROR;
}
- auto &opcode_to_backend = _compiler->options().manual_scheduler_options.opcode_to_backend;
+ auto &opcode_to_backend = _coptions[0]->manual_scheduler_options.opcode_to_backend;
opcode_to_backend.emplace(onert::ir::toOpCode(key), backend);
}
catch (const std::exception &e)
@@ -1024,7 +1058,7 @@ NNFW_STATUS nnfw_session::set_config(const char *key, const char *value)
if (!key || !value)
return NNFW_STATUS_UNEXPECTED_NULL;
- auto &options = _compiler->options();
+ auto &options = *_coptions[0];
using namespace onert::util;
@@ -1067,14 +1101,14 @@ NNFW_STATUS nnfw_session::set_config(const char *key, const char *value)
const onert::ir::Graph *nnfw_session::primary_subgraph()
{
- if (_subgraphs)
+ if (_nnpkg != nullptr)
{
- assert(!_execution && _executions.empty());
- return _subgraphs->primary().get();
+ assert(_execution == nullptr && _executions.empty());
+ return _nnpkg->primary_model()->primary_subgraph().get();
}
else
{
- assert(_execution || !_executions.empty());
+ assert(_execution != nullptr || !_executions.empty());
// TODO Remove const_cast
// We assumed the graph will not change after compilation, but shape could change
if (!_executions.empty())
@@ -1094,7 +1128,7 @@ NNFW_STATUS nnfw_session::get_config(const char *key, char *value, size_t value_
if (!key || !value)
return NNFW_STATUS_UNEXPECTED_NULL;
- auto &options = _compiler->options();
+ auto &options = *_coptions[0];
auto check_boundary = [](size_t dest_size, std::string &src) {
if (dest_size < src.length() + 1 /* for '\0' */)
@@ -1138,9 +1172,9 @@ bool nnfw_session::isStateInitialized()
{
if (_state == State::INITIALIZED)
{
- assert(!_subgraphs);
- assert(!_compiler);
- assert(!_execution && _executions.empty());
+ assert(_nnpkg == nullptr);
+ assert(_coptions.empty());
+ assert(_execution == nullptr && _executions.empty());
return true;
}
else
@@ -1153,9 +1187,9 @@ bool nnfw_session::isStateModelLoaded()
{
if (_state == State::MODEL_LOADED)
{
- assert(_subgraphs);
- assert(_compiler);
- assert(!_execution && _executions.empty());
+ assert(_nnpkg != nullptr);
+ assert(!_coptions.empty());
+ assert(_execution == nullptr && _executions.empty());
return true;
}
else
@@ -1168,9 +1202,9 @@ bool nnfw_session::isStatePrepared()
{
if (_state == State::PREPARED)
{
- assert(!_subgraphs);
- assert(_compiler);
- assert(_execution || !_executions.empty());
+ assert(_nnpkg == nullptr);
+ assert(!_coptions.empty());
+ assert(_execution != nullptr || !_executions.empty());
return true;
}
else
@@ -1183,9 +1217,9 @@ bool nnfw_session::isStateRunning()
{
if (_state == State::RUNNING)
{
- assert(!_subgraphs);
- assert(_compiler);
- assert(_execution || !_executions.empty());
+ assert(_nnpkg == nullptr);
+ assert(!_coptions.empty());
+ assert(_execution != nullptr || !_executions.empty());
return true;
}
return false;
@@ -1195,9 +1229,9 @@ bool nnfw_session::isStateFinishedRun()
{
if (_state == State::FINISHED_RUN)
{
- assert(!_subgraphs);
- assert(_compiler);
- assert(_execution || !_executions.empty());
+ assert(_nnpkg == nullptr);
+ assert(!_coptions.empty());
+ assert(_execution != nullptr || !_executions.empty());
return true;
}
else
@@ -1224,9 +1258,14 @@ NNFW_STATUS nnfw_session::output_tensorindex(const char *tensorname, uint32_t *i
NNFW_STATUS nnfw_session::set_backends_per_operation(const char *backend_settings)
{
if (backend_settings == NULL)
- {
return NNFW_STATUS_ERROR;
- }
- _compiler->set_backend_from_str(backend_settings);
+
+ if (!isStateModelLoaded())
+ return NNFW_STATUS_INVALID_STATE;
+
+ // Backend for all
+ auto &ms_options = _coptions[0]->manual_scheduler_options;
+ ms_options.setBackendMap(std::string{backend_settings});
+
return NNFW_STATUS_NO_ERROR;
}