diff options
Diffstat (limited to 'runtime/onert/api/src/nnfw_api_internal.cc')
-rw-r--r-- | runtime/onert/api/src/nnfw_api_internal.cc | 267 |
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; } |